第6章
1.ES有两种属性:数据属性和访问器属性。属性中包含各种特性,表示属性的各种特征。
数据属性:[[Configurable]],[[Enumerable]],[[Writable]],[[Value]]
修改属性使用方法:Object.defineProperty()
访问器属性:[[Configurable]],[[Enumerable]],[[Get]],[[Set]]
访问器属性不包含数值。只能通过Object.defineProperty()定义。通过设置set和get函数,分别设置读取和写入的时候的行为。P141
2.属性的特性的其他方法:
Object.defineProperties()设置多个属性和其特性
Object.getOwnPropertyDescriptor()读取属性的特性
3.创建对象的模式:
4.工厂模式:解决了重复代码问题,但无法识别对象类型
5.构造函数模式:能够识别对象类型,但每个方法都要在实例上重新创建一遍。不同实例上的同名函数不等。
一个函数通过new来调用就是构造函数,直接调用就是普通函数。
6.原型模式:不必在构造函数中定义对象实例的信息,而是将这些信息直接添加到原型对象中,让所有对象实例共享它包含的属性和方法。
原型对象:(1)创建新函数时,同时创建函数的prototype属性,指向该函数的原型对象。
(2)原型对象生成一个constructor属性,指向原型所在函数。
(3)调用构造函数创建新实例,实例内部包含一个指针[[prototype]],指向原型对象
原型对象的方法:Object.prototype.isPrototypeOf(实例) 确定某原型是否为某实例的原型。
Object.getPrototypeOf(实例) 返回某个实例原型对象
实例.hasOwnProperty(属性) 当某属性存在于某实例中时,返回true
in操作符:属性 in 对象,该对象存在某属性时返回true
Objet.key(实例or原型) 遍历实例或者原型里可以枚举的属性名,返回一个字符串数组
Object.getOwnPropertyNames(实例或原型) 遍历实例或者原型里的所有属性名,不管是否可枚举,返回一个字符串数组
如果在调用构造函数创建一个实例后,重写原型对象,那么实例的[[prototype]]无法指向新的原型对象。P156
原型模式弊端:所有实例拥有相同属性值,由于共享,实例1的修改会在实例2中体现出来
7.组合使用构造函数模式和原型模式:将属性定义在构造函数中,原型定义方法和需要共享的属性
8.动态原型模式:当方法不存在时,就在原型创建方法
9.寄生构造函数模式:在构造函数中创建新对象,再返回该对象。
构造函数在不返回值的时候,默认会返回新对象实例。通过在构造函数的末尾添加一个return,可以重写调用构造函数返回的值。
10.稳妥构造函数模式:避免使用this和new,某些属性值只有通过唯一的方法才能访问。
继承方法:
11.原型链:让原型对象等于另一类型的实例。
假设另一类型使用原型模式,作为实例,它继承了另一类型的所有属性。内部有个[[prototype]]指针指向另一类型的原型对象。作为原型对象,它拥有本类型的方法,它的 constructor属性指向另一类型。
所有函数的默认原型都是Object的实例,所以另一类型作为Object的实例,有[[prototype]]指针指向Object的原型对象。
必须在实现继承后再增加原型的方法。否则,方法只会存在于原来默认的原型对象中
原型链弊端:原型对象作为另一类型的实例,继承了另一类型的实例属性。则,该实例属性在本类型的所有实例中,成了共享的原型属性。本类型的实例1对该属性的修改会在实例2体现出来。
同时,创建子类型的实例时,不能向超类型的构造函数传递参数。
12.借用构造函数:在子类型构造函数内部使用call()调用超类型构造函数,可以避免子类型继承的属性被共享,同时可以向超类型传参。
弊端:方法在构造函数定义,无法复用。
13.组合继承:使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承。
子类型借用超类型的构造函数,相当于是在子类型上创建了同名的实例属性,从而屏蔽了子类型的原型对象上那个继承而来的属性,避免了属性被共享。
弊端:会两次调用超类型。一次在创建子类型原型的时候,一次在创建子类型实例时,调用了超类型构造函数为子类型创建属性
14.原型式继承:将已有的对象a作为新建对象b的原型,则b的实例共享a的属性和方法。相当于对a执行了一次浅复制。现有方法:Object.create()
15.寄生式继承:创建一个仅用于封装继承过程的函数,其中方法无法复用。
16.寄生组合式继承:为了避免组合继承中两次调用超类型构造函数造成的子类型实例和原型中存在同名的属性,可以使用借用构造函数来继承属性,通过原型链的混成形式来继承方法。
使用寄生式继承来继承超类型的原型,再将结果指定给子类型的原型。将此替换组合类型中为子类型原型赋值的语句。
第7章 函数表达式
1.在使用递归的时候,在函数内部使用arguments.callee来调用自己。
2.闭包:有权访问另一个函数作用域中的变量的函数。
创建方式:在一个函数内部创建另一个函数,并返回。
外部函数在执行完毕后,其执行环境的作用域链会被销毁,但其活动对象不会被销毁,因为内部匿名函数的作用域链仍然在引用这个活动对象。直到内部匿名函数被销毁后,外部函数的活动对象才被销毁。
3.闭包保存的是整个变量对象,而不是某个特殊的变量,因此闭包只能取得包含函数中任何变量的最后一个值。
4.匿名函数的执行环境具有全局性,因此this对象通常指向window。闭包中搜索this和arguments这两个变量时,只会搜索到其活动对象,并不会沿着作用域链访问外部函数的this和arguments。
5.模仿块级作用域:
1 (function(){ 2 //这里是块级作用域 3 })();
将函数声明包含在一对圆括号中表示它是一个函数表达式。紧跟着另一对圆括号表示立即调用这个函数。
6.特权方法:有权访问私有变量和私有函数的公有方法。
(1)在构造函数中定义特权方法(在构造函数中将特权方法定义为构造函数的方法,通过对象实例来访问)。弊端:必须使用构造函数模式。
(2)在私有作用域中定义私有变量和函数。在原型上定义了公有方法(在原型对象中将特权方法定义为方法。),体现了原型模式,增加了代码复用。弊端:每个实例都没有自己的私有变量。P188
7.模块模式:为单例(只有一个实例的对象)创建私有变量和特权方法(将特权方法定义在函数返回的对象字面量中)。
8.增强的模块模式:将返回的对象字面量换成某种类型的实例。用于规定单例是某种类型的实例的情况。