网站怎么做长截图,做ps的网站有哪些功能吗,广州市招投标网站,做一个简单网页第6章 面向对象的程序设计 ECMAScript中没有类的概念#xff1b; 1.创建对象-历史
1.1 创建实例#xff0c;添加方法和属性 → 对象字面量 缺点#xff1a; 使用同一接口创建很多对象#xff0c;产生大量重复代码 var person new Object()
person.name Y
pe…第6章 面向对象的程序设计 ECMAScript中没有类的概念 1.创建对象-历史
1.1 创建实例添加方法和属性 → 对象字面量 缺点 使用同一接口创建很多对象产生大量重复代码 var person new Object()
person.name Y
person.age 18
person.job policeperson.sayName function() {alert(this.name)
}↓
var person {name Y,age 18,job police,sayName function() {alert(this.name)}
}1.2 工厂模式 (返回对象) 缺点 没有解决对象识别的问题怎样知道一个对象的类型 特点 内部创建对象并返回 function createPerson(name, age, job) {var o new Object()o.name nameo.age ageo.job jobo.sayName function () { alert(this.name)}return o
}1.3 构造函数模式 缺点 每个方法都要在每个实例上重新创建一遍不同实例上的同名函数是不相等的然而创建2个完成同样任务的Function实例的确没有必要。 特点 没有显示创建对象 没有return 将方法属性赋值给this对象 首字母大写 构造函数创建的实例标识为一种特定的类型 1.3.1 理解面试题
调用构造函数创建对象实际会经历以下4个步骤
创建一个新对象将构造函数的作用域赋值给新对象this指向这个新对象执行构造函数代码为这个新对象添加属性方法返回新对象
function Person(name, age, job) {this.name namethis.age agethis.job jobthis.sayName function () { // 每定义一个函数就是实例化一个对象alert(this.name)}
}
var p1 new Person(Y,18,police)
var p2 new Person(H,8,teacher)
// p1.constructor Person
// p2.constructor Person// ( p1 instanceOf Object ) true
// ( p1 instanceOf Person ) true
// ( p2 instanceOf Object ) true
// ( p2 instanceOf Person ) true在全局作用域调用函数this总是指向GLOBAL对象
function person(name, age, job) {this.name namethis.age agethis.job jobthis.sayName function () { alert(this.name)}
}
person(Leo, 16, doctor)
window.sayName() //leo1.3.2 将构造函数当做函数
任何函数只要通过new操作符来调用便可以作为构造函数若不用即与普通函数无异。this会指向Global对象在浏览器中就是window
1.3.3 将方法定义到构造函数外部 缺点 在全局作用域上定义的函数若只能被某个对象调用不合理并且如果对象需要定义很多方法则需要定义很多个全局函数对于这个自定义的引用类型就丝毫没有封装性可言。 function Person(name, age, job) {this.name namethis.age agethis.job job
}
function sayName() {alert(this.name)
}1.4 原型模式
1.4.1 理解原型模式
function Person() {}
Person.prototype.name Y
Person.prototype.age 18
Person.prototype.job police Person.prototype.sayName function () {alert(this.name)
}使用原型对象的好处让所有的对象实例共享它所包含的属性和方法只要创建了一个新函数就会为该函数创建一个prototype属性指向函数的原型对象原型对象会自动获得constructor属性该属性包含一个指向prototype属性所在函数的指针constructor属性指向构造函数对象的constructor属性最初是用来表示对象类型的构造函数创建的实例实例内部包含一个指针指向构造函数的原型对象Person.prototype.isPrototypeOf(p1) // trueObject.getPrototypeOf(p1) Person.prototype // true代码读取某个对象某个属性时先搜索对象实例若无再搜索原型对象若实例中添加的属性和原型属性同名会屏蔽原型中的属性因为实例只能访问原型中的值而不能重写若将实例中的同名属性设为null并不能恢复与原型的连接需要使用delete操作符完全删除实例属性p1.hasOwnProperty(name)// true hasOwnProperty()方法可以检测一个属性是存在于实例中还是存在于原型若来自实例则返回true
1.4.2 in操作符
in操作符会在通过对象能访问给定属性时返回true无论属性存在于实例还是原型中
name in p1 // true1.4.3 确认属性存在于原型
function hasPrototypeProperty(object,name) {return !object.hasOwnProperty(name) (name in object)
}1.4.4 更简单的原型语法 缺点 constructor属性不再指向Person切断了实例和原型对象的联系对包含引用类型值的属性被实例共享会造成问题。 特点 减少不必要的输入每添加一个属性/方法就要多敲一遍Person.prototype 将Person.prototype设置为一个以对象字面量形式创建的新对象本质上重写了prototype对象创建函数时自动创建的原型对象导致constructor属性指向Object构造函数尽管instanceof还能返回正确的结果。
function Person() {}
Person.prototype {name : Y,age : 18,job : police,sayName: function () {alert(this.name)}
}
p1 instanceof Object // true
p1 instanceof Person // true
p1.constructor Person // false
p1.constructor Object // true增加constructor属性确保该属性能访问到适当的值。
function Person() {}
Person.prototype {constructor : Person,name : Y,age : 18,job : police,sayName: function () {alert(this.name)}
}1.4.5 原生对象的问题
function Person() {}
Person.prototype {constructor : Person,friends:[Yoona,Jessica], // 数组引用类型name : Y,age : 18,job : police,sayName: function () {alert(this.name)}
}
p1.friends.push(Krystal)
p1.friends p2.friends1.4.6 组合使用构造函数模式和原型模式
构造函数模式用于定义实例属性原型模式用于定义方法和共享的属性。实例属性中的引用类型互不干扰
function Person(name, age, job) {this.name namethis.age agethis.job jobthis.friends [Yoona,Jessica]
}Person.prototype {constructor : Person,sayName: function () {alert(this.name)}
}1.4.7 原生对象的原型
通过原生对象的原型不仅可以取得所有默认方法的引用也可以定义新方法。但不推荐在产品化的程序中修改原生对象的原型 如果因为某个实现中缺少某个方法就在原始对象的原型中添加那么当在另一个支持该方法的实现中运行代码时就可能会导致命名冲突而且这样做也可能会意外地重写原生方法。
1.5 梳理 1.6 修改原生对象的原型
String.prototype.startsWith function(){}在当前环境中所有字符串都可以调用startsWith但不推荐可能会产生命名冲突也可能会意外地重写原生方法。
String.prototype.
toString function () {console.log(修改原生对象默认方法)
}str.toString() // 修改原生对象默认方法将原生对象原型指向空没效果
String.prototype null
console.log(str.toString()) // str2. 属性类型 P139
2.1 数据属性
[[Configurable]]:能否通过delete删除属性默认为true[[Enumerable]]能否通过for-in循环返回属性默认为true[[Writeable]]能否修改属性的值默认为true[[Value]]属性值默认为undefined
一旦把属性定义为不可配置的就不能再把它变回可配置了要修改属性默认的特性必须使用Object.defineProperty()3个参数对象、属性名、描述符对象属性必须是数据属性若不指定数据属性则默认为false
2.2 访问器属性
包含一对getter和setter函数都不是必须的有4个特性 1 [[Configurable]] 2 [[Enum而able]] 3 [[Get]]:读取属性时默认调用的函数默认值undefined 4 [[Set]]:写入属性时默认调用的函数默认值undefined
属性 _year 前面的下划线用于表示只能通过对象方法访问的属性使用访问器属性的常见方式设置一个属性的值会导致其他属性发生变化
2.3 读取属性
Object.getOwnPropertyDescriptor()2个参数对象、属性
var descriptor Object.getOwnPropertyDescriptor(person,age)
alert(age.value)
alert(age.enumerable)
alert(age.configurable)
alert(age.get)方法集合
Object.defineProperty() // 修改属性默认值
Object.getOwnPropertyDescriptor() //读取属性的描述符
谁谁的原型对象.isPrototypeOf(实例) // 参数是实例判断实例内部是否有指向构造函数原型对象的指针
hasOwnProperty() // 检测属性来自实例返回true还是原型3. 继承子类继承父类的特征和行为
3.1 原型链
原型链的问题
P166 原型链虽然很强大可以用它来实现继承但它也存在一些问题其中最主要的问题来自包含引用类型值的原型。包含引用类型值的原型属性会被所有实例共享因此要在构造函数而不是原型对象中定义属性。在创建子类型的实例时不能向超类型的构造函数中传递参数。没有办法在不影响所有对象实例的情况下给超类型的构造函数传递参数
让原型对象等于另一个类型的实例。
SubType.prototype new SuperType()SubType的实例指向SubType的原型进而又指向SuperType的原型
3.2 默认的原型
所有引用类型默认都继承了Object所有函数的默认原型都是Object的实例因此默认原型都会包含一个内部指针指向Object.prototype这也正是所有自定义类型都会继承toString()、valueOf()等默认方法的根本原因。完整的原型链如下
instance instanceof Object // true
instance instanceof SuperType // true
instance instanceof SubType // trueObject.prototype.isPrototypeOf(instance) // true
SuperType.prototype.isPrototypeOf(instance) // true
SubType.prototype.isPrototypeOf(instance) // truefunction Fun() {}console.log(Fun.prototype.__proto__Object.prototype) // true3.3 组合继承
父构造函数内有引用类型属性值子构造函数内使用call保证了实例不会都指向同一个引用类型子构造函数原型指向父构造函数原型Object.create子构造函数原型里的构造器指向自己知晓实例由谁创建
4. 方法整理 A.isPrototypeOf(a) // 实例a的__proto__指向A的原型 // 判断原型对象A是否是实例a的原型是则返回truea.hasOwnProperty(‘name’) 判断属性是否存在于实例中实例属性是则返回true Object.keys() 获得对象上所有可枚举的属性‘name’ in a 无论原型/实例只要是能访问得到的属性in操作符返回true包括constructorname’字符串 for-in循环返回所有能通过对象访问的、可枚举的属性 遍历一个实例对象原型上的属性也会打印、要只打印实例属性需要配合hasOwnPropertyObject.getOwnPropertyNames(),得到所有实例属性包括constructor function Test(name) {this.name name
}
Test.prototype.name hhh
let tObj new Test(yyy)
console.log(name in tObj) // true
console.log(constructor in tObj) // true
for(var prop in tObj){console.log(for-in, prop) // name
}