任何函数在被创建时,都会被附带一个新创建的原型对象。
原型和实例的关系:每个构造函数附带一个原型对象prototype,原型有一个constructor指向构造函数,实例对象有一个__proto__属性指向原型prototype。
函数的原型具有两面性,当作为实例对象时,它的原型(proto)指向Function构造函数的原型对象,当作为构造函数时,它的原型(prototype)指向自身创建的原型对象。
一、js的继承方式
1.原型链继承:简而言之即为让子类的原型对象指向父类的一个实例对象。
function Father() {
this.sex = 'male'
this.colors = ['red','green','yellow']
};
Father.prototype.eat = function(){
console.log('恰饭')
};
function Son() {}
// 继承
Son.prototype = new Father
const son1 = new Son
const son2 = new Son
son1.colors.push('blue')
son2.colors // ['red','green','yellow','blue']
2.构造函数继承:在子类中调用父类的构造函数,利用父类构造函数生成自身属性。
function Father() {
this.sex = 'male'
}
function Son() {
// 将子类实例对象注入到父类的执行上下文中。
Father.call(this)
}
const son = new Son;
son.sex // 'male'
3.组合继承:综合原型链继承与构造函数继承的优点,用原型链继承原型上的属性和方法,借助构造函数继承实例属性。
function Father() {
this.sex = 'male'
this.colors = ['red','green','yellow']
};
Father.prototype.eat = function(){
console.log('恰饭')
};
function Son() {
Father.call(this) // 第一次调用Father()
}
// 继承
Son.prototype = new Father // 第二次调用Father()
const son = new Son
son.sex // 'male'
4.原型式继承:创建一个临时的构造函数,将传入的对象赋值给这个构造函数的原型,然后返回这个临时类型的一个实例。
function createAnother(original){
// 创造一个原型继承original的对象
let clone = Object.create(original)
return clone
}
const original = {
name:'neo',
colors:['red','green','yellow','blur']
}
const another = createAnother(original)
another.colors.push('purple')
const other = createAnother(original)
other.colors // ['red','green','yellow','blur','purple']
原型的缺陷:js的继承主要依托于原型模式,由于它的共享机制,当原型含有引用类型值时,它往往可以被实例对象所篡改,