1)关于原型
创建的新函数有一个prototype指针,指向一个原型对象。原型对象有一个construct属性,指回去函数,形成一个环。函数创建一个新实例后,实例会有一个内部属性__proto__ ,指向原型对象。
2)关于重写原型对象
一般我们给原型对象添加属性和方法的时候,都会这样添加:
Person.prototype.name="zakas";
Person.prototype.sayName=function(){
console.log(this.name);
}
如果用对象字面量的话:
Person.prototype={
name:"zakas",
sayName:function(){
console.log(this.name);
}
}
就会重写了整个原型对象,即constructor属性不再指向Person了。如果这个constructor的值真的重要的话,可以手动加入代码:
Person.prototype={
constructor:Person,
name:"zakas",
sayName:function(){
console.log(this.name);
}
}
3)关于继承——原型链继承
SubType.prototype=new SuperType();
子函数要继承父函数的时候,将子函数的prototype指针指向一个父函数的实例,,父函数实例就会有一个__proto__属性,指向父函数的原型对象。
用子函数创建一个实例后,子函数实例的内部__proto__指向子函数的原型对象,子函数的原型对象(即父函数的实例)的内部__proto__指向父函数的原型对象。
原型链的缺点就是:
1、父函数里面的属性,在实例后,就变成了子函数的prototype对象的属性,如果这个属性是个引用类型的话(如数组),那么所有的子函数的实例将共享这 个属性(因为如果是基本类型的话,属性的赋值就会是在实例中添加新的属性,原型对象中的属性是不变的,但是如果是引用类型的话,如数组,往数组里面push数据是真的往原型对象的属性push数据);
2、子函数无法向父函数的构造函数传递参数
4)关于继承——借用构造函数
var SubType=function(){
SuperType.call(this);
}
借用构造函数的缺点就是:
1、只是借用了父函数的构造函数,并没用借用到父函数的原型对象,就没有了所谓的函数复用
5)关于继承——寄生组合式
1 var object=function(o){ 2 var F=function(){}; 3 F.prototype=o; 4 return new F(); 5 }; 6 var inheritPrototype=function(subType,superType){ 7 var prototype=object(superType.prototype); 8 prototype.constructor=subType; 9 subType.prototype=prototype; 10 }; 11 12 var SuperType=function(name){ 13 this.name=name; 14 }; 15 SuperType.prototype.sayName=function(){ 16 alert(this.name); 17 }; 18 var SubType=function(name,age){ 19 SuperType.call(this,name); 20 this.age=age; 21 }; 22 inheritPrototype(SubType,SuperType);
寄生组合式的原理是:
1、第19行代码,用call解决了原型链的两个缺点。call只是借用了构造函数,然后其他就是下面一点了
2、object函数的作用,说得通俗一点,就是将SuperType的构造函数抽空,然后返回一个实例(为什么抽空构造函数呢,因为SuperType的构造函数已经用call解决了),然后inheritPrototype函数将SubType的原型对象设置为该实例
所以,寄生组合式真正实现了继承吧。。。。
5)关于instanceof
我们通常会用instanceof来判断一个变量是不是某个对象的实例
如obj instanceof class
那么内在是如何运作的,其实instanceof判断的而是obj原型链上的原型是否与class的原型是同一个对象,是返回true,不是返回false
所以说,用instanceof来判断一个变量是否是某个对象的实例是不精准的,任何一个函数,只要改写他的prototype,它都可能“成为某个实例的对象”