讲解一下关于原型链的知识。
instanceof
语法:
1 | object instanceof constructor; |
instanceof
运算符用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上。
简单来说就是检查constructor.prototype
是否出现在object.__proto__
上面。
注意:这个对比的不是输入时的参数,而是他们的原型,这也是和isPrototypeOf
的区别
听起来是不是很奇怪?为什么是
constructor.prototype
是否出现在object.__proto__
上面,而不是object.__proto__
出现在constructor.prototype
上面?
大家都知道这个是用来判断继承或者一个实例是否是某个类的。
这就要想清楚继承的真正含义,别被想当然给误解了。
类 A 继承 Z,那么 A 的实例 a 应该都“属于”A 和 Z,也就是 instaceof 都是 true。继承其实是子类包含父类,而不是父类包含子类。
那为什么说子类属于父类呢?
这个是从不同概念上来说的,子类属于父类是从抽象的概念上来说的,上面说的包含是从内容上面来说。比如男人女人都属于人类,但是男人包含了所有人类这个层面抽象的所有内容。
1 | 从抽象概念上说:子类是父类的一部分,属于父类。 |
isPrototypeOf
isPrototypeOf() 方法用于测试一个对象是否存在于另一个对象的原型链上。
1 | prototypeObj.isPrototypeOf(object) |
检测prototypeObj
是否在object
的原型链上。
注意:这个做对比时,就是
prototypeObj
本身,而不是他的原型,这是和instanceof
的区别。写是o
,那对比的就是o
,写的是o.__proto__
,对比的就是o.__proto__
1 | function C(){} |
Object.create
1 | let o=Object.create(proto[, propertiesObject]) |
Object.create()
方法创建一个新对象o
,使用现有的对象proto
来提供新创建的对象o
的__proto__
。
Object.getPrototypeOf
Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)
1 | let proto = Object.getPrototypeOf(object); |
proto
就是object
的__proto__
new 运算符
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。new 关键字会进行如下的操作:
- 创建一个空的简单 JavaScript 对象(即{});
- 链接该对象(即设置该对象的构造函数)到另一个对象 ;
- 将步骤 1 新创建的对象作为 this 的上下文 ;
- 如果该函数没有返回对象,则返回 this。
1 | function Car() { |
因为函数有自己的返回值,所以实例化的对象就是返回的对象,而不是 this;
1 | function Car(name) { |
这里解释为什么car2
的name
有值,car3
没有;
首先要明白new
运算符的执行过程;从上面定义我们知道,创建的car1
是有属性name
的,car1
的__proto__
是指向Car.prototype
,这上面是没有name
的。
然后需要明白Object.create
的使用,它是把创建的对象的__proto__
指向了传入的对象。
因此car2.__proto__===car1
,因此有name
属性;car3.__proto__
指向car1.__proto__
也就是Car.prototype
,所以没有name
属性。