原型和原型链
原型
自定义一个构造函数 -》 为该函数创建一个prototype属性 -》该属性指向函数的原型对象 -》原型对象的constructor属性指向该函数(prototype属性所在的函数)
实例化一个对象 -》 实例内部包含一个内部属性指向原型对象
示例:
// 自定义一个构造函数 function User() { } User.prototype.name = 'qq'; var user1 = new User();
图解:
js的new到底做了些什么?
1)新建一个对象
2)将这个对象的_ptoto_指向User原型对象
3)将构造函数的作用域赋给新对象,即执行了User.call(user1),this指向user1
题外话:es6中new增加了new.target属性,new.target的值为构造函数,可在构造函数中使用;若使用new创建实例,new.target为构造函数,若采用call或apply方式调用生成实例,则为undefined
原型链
原型链存在于继承关系中,本质在于将父类的实例赋值给子类的构造函数的原型,以此实现子类可以访问父类属性和方法,达到继承的目的。
但原型链仅适用于方法的继承,并不适合属性的继承,原型链实现的继承中属性是各实例共享的,适用于静态属性的继承,不能独立于实例。因此利用在子类构造函数中调用父类构造函数的方式达到公有属性的目的。
总结如下:
1)通过原型链实现静态属性的继承
2)通过原型链实现方法的继承
3)通过子类构造函数中调用父类构造函数继承到父类的属性(非静态)
4)子类私有属性在子类构造函数中通过this.a这种方式实现
5)子类私有方法通过子类原型定义
原型式继承,包含上述1)、2)、3)项:
function SuperClass () { this.property = 1;
this.a = ['a']; } SuperClass.prototype.staticProperty = 3; SuperClass.prototype.getSuperProperty () { return this.property; } function SubClass () { this.subProperty = 2; } SubClass.prototype = new SuperClass(); SubClass.prototype.getSubProperty () { return this.subProperty; } var subInstance = new SubClass();
借用构造函数可实现子类传参赋值给父类构造函数:
function SuperClass(name) { this.name = name; } funtion SubClass(name) { SuperClass.call(this, name); }
解决原型继承导致的引用类型值会被共享,例: this.a。
寄生式继承:
组合寄生式继承: