javaScript中实例,类,原型等是js语言的核心概念,在充分理解并掌握的情况下,才能在编程中得心应手。近期进行知识归类总结,对js中的实例,类,类的原型,实例的原型,类的prototype,实例的prototype进行一个总结。
核心概念:prototype指的是原型对象, __proto__指的是原型
看一个简单的例子:
class a{
constructor(options){
console.log('options',options)
this.testThis()
}
ready(){
console.log('a的ready属性')
}
testThis(){
this.ready()
}
}
class b extends a {
constructor(options){
super(options)
this.testExtendsThis()
}
testExtendsThis(){
console.log('testExtendsThis')
}
}
接下来分别创建实例A, 实例B,并获取实例A的原型,实例B的原型,类a的protoype, 类b的prototype,a的原型,b的原型等,并进行比较。
const B = new b();
const A = new a();
const get_proto_a = Object.getPrototypeOf(a)
const get_proto_b = Object.getPrototypeOf(b)
const get_proto_B = Object.getPrototypeOf(B)
const get_proto_A = Object.getPrototypeOf(A)
const proto_a = a.prototype;
const proto_b = b.prototype;
const proto_A = A.prototype;
const proto_B = B.prototype;
const get_get_proto_b = Object.getPrototypeOf(get_proto_b);
const get_get_proto_B = Object.getPrototypeOf(get_proto_B)
进行比较:
//类的原型和类 得出 类的原型等于其继承的类
console.log(get_proto_b === a)//true
//类的原型对象prototype和类的原型 二者没有直接联系
console.log(_.isEqual(get_proto_a, a.prototype))//false 这里判断两个对象不能直接使用===
//实例的原型 和实例 实例的原型指向实例
console.log(_.isEqual(get_proto_B , B))//true 这里判断两个对象不能直接使用===
//实例的原型如果有继承,再指向自身后,指向继承类的实例
console.log(_.isEqual(get_get_proto_B , new a()))//true 这里判断两个对象不能直接使用===
//实例的原型指向实例的构造函数的prototype
console.log(get_proto_A === A.constructor.prototype)//true
//实例的构造函数指向类
console.log(A.constructor.prototype === a.prototype)//true
//实例的原型的原型,指向其构造函数继承类的实例
console.log(get_get_proto_B === get_proto_A)//true
//console.log(A.prototype)//实例默认没有原型对象
总结:通过上面的代码归结出规律:
1,实例的原型指向实例(先指向自身),类的原型指向类
2,实例的原型指向实例的构造函数的prototype
3,实例的构造函数指向类
4,实例的原型对象默认不存在
5,实例不能被继承
引申:
Class 作为构造函数的语法糖,同时有prototype
属性和__proto__
属性,因此同时存在两条继承链。
(1)子类的__proto__
属性,表示构造函数的继承,总是指向父类。
(2)子类prototype
属性的__proto__
属性,表示方法的继承,总是指向父类的prototype
属性。
子类实例的__proto__
属性的__proto__
属性,指向父类实例的__proto__
属性。也就是说,子类的原型的原型,是父类的原型。
参考:http://es6.ruanyifeng.com/#docs/class-extends#Object-getPrototypeOf