Summer Training Day 10.
构造函数与原型.
继承.
今天补充前两天的内容.
构造函数与原型
构造函数模式.
|
|
要创建新实例,则必须使用new操作符.
new做了5件事情:
1.创建新对象.
2.this指向这个新对象(通过把构造函数的作用域赋于新对象).
3.连接原型链.
4.执行函数(也是在给新对象添加属性).
5.返回新对象.
(Object与Array为原生构造函数)
纯构造函数的缺点.
每个方法要在每个实例上创建一遍,因此,不同实例上的同名函数其实是不相等的.
与其在构造函数内部定义函数,还不如在外部定义,这样每个实例共享一个函数,但是这样做又有问题.
在全局作用域定义函数但是只是让某个对象使用就有点浪费,而且可能需要为此定义许多全局函数.
这个自定义引用类型就毫无封装性可言了.
以上问题可以通过原型模式解决.
原型模式.
每个函数都有一个prototype(原型)属性,该属性为一个指针指向一个对象(原型对象),
这个对象包含特定类型所有实例共享的属性和方法.
使用原型对象可以让所有实例共享它所包含的属性和方法.就不必要在构造函数中定义.
默认情况下,所有原型对象会自动获得一个constructor(构造函数)属性.
此属性为一个指向prototype属性所在函数(即构造函数)的指针.
即:Person.prototype.constructor = Person;
创建了构造函数后,其原型对象默认只会取得constructor属性,其他属性继承Object;
创建新实例后,该实例内部包含一个指针(内部属性)__proto__,指向构造函数的原型对象,该属性对脚本完全不可视.
[需要注意的是,此关系(Person与Person.prototype)存在于构造函数与其原型对象之间,而与实例无关(即person1无prototype属性只有看不见的__proto__)].
但是实例对象共享constructor属性(可能是因为__proto__属性吧).person1.constructor == Person.
虽然__proto__属性无法访问,但的确是可以通过 isPrototypeOf() 方法来确定这个关系.
若__proto__指向Person.prototype,则会返回True.
也可以通过Object.getPrototypeOf()方法返回__proto__的值.
每当代码读取某个对象的某个属性时,都会执行一次搜索.首先从实例开始,如果没找到,
则继续搜索其指针指向的原型对象.有的话就返回其属性值.
也就是说,当我们调用person1.sayName()时,会先后进行两次搜索.
如果在实例找到就不会往上找.
这样就引出了在实例不能重写原型属性,但在属性同名的情况下会屏蔽原型属性的问题.
即便 person1.name = “”; 也不能恢复对原型Person.name的链接.
要想恢复连接,就要用到delete操作符.
hasOwnProperty()方法可以检测一个属性是在原型中还是实例中
Object.getOwnPropertyDescriptor( object , propertyname )方法只能用于实例属性信息获取.
in操作符
单独使用时,会在能够访问给定属性时返回true,无论该属性存在于原型中还是实例中.
Object.keys()方法获取对象上所有可枚举的实例属性.
定义原型对象属性的简便写法:
此方法有个缺陷,就是constructor不再指向Person而是Object(本质上改写了整个prototype),
要指回来需要在花括号里面加上”constructor : Person”:
但是这样做又有一个问题,就是其[[Enumerable]]属性被设置为true,即 可枚举.
若不想让constructor可枚举,则可以换一种添加方法.
Object.defineProperty(object,property,descriptor)
继承
原型链
本质上是把父类型的实例赋予子类型的原型对象.
重写原型对象,代之以一个新类型的实例.
相关继承方式(原型式,寄生式,寄生组合式)以后再议…
以上抄书.