JavaScript 继承机制的设计思想就是,原型对象的所有属性和方法,都能被实例对象共享。也就是说,如果属性和方法定义在原型上,那么所有实例对象就能共享,不仅节省了内存,还体现了实例对象之间的联系。
function Parent(name1){
this.name1 = name1
}
Parent.prototype.pMethod = function(){
console.log(this.name1)
}
function Child(name2, name1){
Parent.call(this, name1) // 得分点
this.name2 = name2
}
Child.prototype.__proto__ = Parent.prototype
//上面这句代码的古板写法应该是下面三句
//const empty = function(){}
//empty.prototype = Parent.prototype
//Child.prototype = new empty()
//古板写法额外加两分
Child.prototype.cMethod = function(){
console.log(this.name2)
}
//如果写成下面这种,就扣两分
//Child.prototype = {
// cMethod: function(){
// console.log(this.name2)
// }
//}
上面代码中,构造函数Animal的prototype属性,就是实例对象cat1和cat2的原型对象。原型对象上添加一个color属性,结果,实例对象都共享了该属性。
原型对象的属性不是实例对象自身的属性。只要修改原型对象,变动就立刻会体现在所有实例对象上。
JavaScript 规定,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个“原型链”(prototype chain):对象到原型,再到原型的原型……
如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性。也就是说,所有对象都继承了Object.prototype的属性。这就是所有对象都有valueOf和toString方法的原因,因为这是从Object.prototype继承的。
那么,Object.prototype对象有没有它的原型呢?回答是Object.prototype的原型是null。null没有任何属性和方法,也没有自己的原型。因此,原型链的尽头就是null。
class继承
大多数浏览器的 ES5 实现之中,每一个对象都有__proto__属性,指向对应的构造函数的prototype属性。Class 作为构造函数的语法糖,同时有prototype属性和__proto__属性,因此同时存在两条继承链。
class Parent{
constructor(name1){
this.name1 = name1
}
pMethod(){
console.log(this.name1)
}
}
class Child extends Parent{
constructor(name2, name1){
super(name1) // 得分点
this.name2 = name2
}
cMethod(){
console.log(this.name2)
}
}