JavaScript高级程序设计解释
继承是OO语言中的一个最为人津津乐道的概念.许多OO语言都支持两种继承方式: 接口继承 和 实现继承 .接口继承只继承方法签名,而实现继承则继承实际的方法.由于js中方法没有签名,在ECMAScript中无法实现接口继承.ECMAScript只支持实现继承,而且其 实现继承 主要是依靠原型链来实现的.
原型和实例的关系
每个构造函数(constructor)都有一个原型对象(prototype),原型对象都包含一个指向构造函数的指针,而实例(instance)都包含一个指向原型对象的内部指针.
什么是原型对象prototype
因为构造函数生产的实例无法共享属性,所以可以通过一个原型对象实现继承共用。
let a = function() {}
a.prototype.say = function() {
console.log('say hello')
}
let b = new a()
let c = new a()
b.say() // say hello
c.say() // say hello
以上构造函数和原型方法不能使用箭头函数,this会指向window而不是对应的构造函数
let a = () => {}
let b = new a() // a is not a constructor
let a = function() {}
let b = new a()
a.prototype.who = () => {
console.log(this)
}
b.who() // window
a.prototype.who = function() {
console.log(this)
}
b.who() // a
什么是原型链?__proto__又有什么用?
一个对象或函数通过__proto__这个属性连接者它所对应父级的原型对象prototype
let a = function() {}
let b = new a()
b.__proto__ === a.prototype // true
a.__proto__ === Function.prototype // true
通过__proto__一层层往上寻找继承从而形成“原型链”,这里a.prototype.__proto__往上则是Object.prototype,最顶端则是null。还有这里寻找是就近原则,如果在第一层找到对应的属性就不会向上寻找了。
js中每一个对象或函数都有__proto__属性,但是只有函数对象才有prototype属性。
instanceof 可以在继承关系中用来判断一个实例是否属于它的父类型
let a = function() {}
let b = new a()
b instanceof a // true
详细用法可以参考
developer.mozilla.org/zh-CN/docs/… www.ibm.com/developerwo…
constructor属性
let a = function() {}
let b = new a()
b.constructor === a // true
使用constructor属性可以查询到实例对象的父级构造方法,但是这个constructor属性是继承过来的
let a = function() {}
a.prototype = {}
let b = new a()
b.constructor === a // false
这个constructor属性是继承原型对象prototype的,原型对象prototype的constructor属性是指向该构造函数
let a = function() {}
a.prototype.constructor === a // true
看图说话(图片来自 blog.csdn.net/cc188688768…

上图,Foo构造函数new Object()生成一个实例对象f1,这个new Object()过程可以理解成三步:
1.新建了一个空对象f1
2.将空对象的__proto__指向了Foo函数的原型对象prototype
3.将Foo函数中的this指针指向f1,f1有了Foo构造函数中的属性或方法 ,然后Foo函数返回的是对象,直接返回Foo函数中的对象否则返回f1
let f1 = {}
f1.__proto__ = Foo.prototype
let newObj = Foo.apply(f1, arguments)
return typeof newObj === 'object' ? newObj : f1
Object.create()可以作为对象继承,步骤也可以分为三步:
1.新建了一个空构造函数f1
2.将空构造函数的原型对象prototype指向了Foo函数
3.将空构造函数实例化成新对象
let f1 = function () {};
f1.prototype = Foo;
let newObj = new f1();
return newObj;
new Object()与Object.create()的区别就是:
1.Object.create()不会把构造函数的属性传下来,而new Object()会根据参数赋值
2.Object.create()创建的新对象的原型指向接收的参数对象,new Object() 创建的新对象的原型指向的是 Object.prototype
3.Object.create(null)可以创建一个没有原型prototype的对象,而 new Object() 创建的对象是 Object的实例,原型链指向Object.prototype
let a = Object.create(null)
let b = new Object()
console.log(a.__proto__) // undefined
console.log(b.__proto__) // Object.prototype