原型,原型链,继承
最近在看js高级程序设计,以前对prototype不了解,重新看完书后得到了很多东西不止是原型这块知识点,还有一些细节点,写法上的性能优化、一些方法的处理机制,这里就不说明了。就来把自己所知道的原型来梳理一下吧
一丶原型是什么
在js里,万物皆对象,Function也是对象,在使用字面量创建基本类型的时候也会实例化成一个对象。 我们在创建对象的时候可以看到,对象里会有一个属性__proto__,可称为隐式原型。
在函数(Function)这个对象中,还有一个特有的属性,prototype(显式原型)。函数的prototype是一个指针,指向一个对象。
function a(){};
a.prototype={};
new a().__proto__ === a.prototype; //true
这里就能知道一个对象的隐式原型指向和构造该对象的构造函数的原型的指向是一样的,这样就保证了能够访问到构造函数原型时定义的方法了。在对象__proto__属性里能看到里面有许多的方法还有一个属性constructor,指向我们的构造函数。
二丶继承
js没有现有的继承的机制,但是可以通过其他的方式来实现继承,比如常见的类式继承,利用原型的特性实现继承
1.类式继承
function SuperClass(){
this.val=true
};
SuperClass.prototype.getVal=function(){
console.log(this.val)
}
SuperClass.prototype.o={
a:1
}
function SubClass(){
this.val=false
}
SubClass.prototype=new SuperClass();
SubClass.prototype.constructor=SubClass;
var sub1=new SubClass();
sub1.getVal(); //false;
sub1.o.a=2;
console.log(new SubClass().o.a)//2
类的原型对象的作用就是为类的原型添加共有方法。当子类的原型对象指向实例化一个父类的时候,再去实例化这个子类的时候,实例化后的对象里的__proto__就是我们父类的prototype对象,所以就能够访问到父类原型对象的方法和构造属性了。
但是有个缺点,因为prototype是指向对象,对象和基本值不一样,是引用,所以我们更改其中的属性也就是相当于更改父类的属性,就会相互影响。
当然也可以通过父类的原型对象for-in循环复制到子类里,只要加上hasownproperty的判断就好啦。
2.构造函数继承
js是灵活的,我们可以使用其他继承方式来解决引用问题,比如常见的构造函数继承
function SuperClass(){
this.val=true;
this.o={
a:1
}
};
function SubClass(){
SuperClass.call(this)
}
var sub1=new SubClass();
sub1.val//true
sub1.o.a=2
var sub2=new SubClass();
console.log(sub2.o.a)//1
当我们实例化子类的时候,执行一遍父类的函数,利用call函数更改为子类的作用域,那么在this添加属性的时候就会对子类的实例化对象添加属性了,这样创建的实例就会单独拥有一份属性了,而不能共用,
这样就违背了代码复用的原则。
3.组合继承
所以结合前两种模式的优点,就有了组合继承。