原型和原型链

错误之处,欢迎指正。


1. 原型和原型链

  1. 所有函数都有prototype这个属性,这个属性指向该函数的原型。原型是一个对象格式。
  2. 所有对象都有__proto__这个属性,这个属性指向该对象的构造函数的原型。注意:使用__proto__是不被推荐的一种方式,推荐使用Object上的静态方法Object.getPrototypeOf(obj)来获取该对象的构造函数的原型。
  3. 函数也是对象,函数也具有__proto__这个属性,指向构造函数Function的原型。
  4. Function可以理解为是javascript帮我们写好的,Function.__proto__ === Function.prototype
  5. Object.prototype.__proto__ === null
  6. 当调用一个对象/函数上的属性时,先去自身找,如果自身没有,去__proto__上找(构造该对象的构造函数的原型,xxx.__proto__),如果构造函数的原型上没有,去该构造函数的原型的__proto__上找(构造函数的原型的构造函数的原型xxx.__proto__.__proto__),一直到找到,或者返回null为止。

2. 例题

const F = function () {};  //构造函数F
const obj = new F();  //构造函数F构造的对象obj
Object.prototype.a = 'chris';
Function.prototype.b = '22';
console.log(obj.a);
console.log(obj.b);
console.log(F.a);
console.log(F.b);
  1. 首先看obj.aobj是一个对象,它自身没有a这个属性,那么去它的构造函数原型(obj.__proto__)上寻找,它的构造函数是F,那么该构造函数的原型是F.prototype,然而依然没有,那么继续找F.prototype.__proto__F.prototype是一个对象,它的构造函数是Object,因此,找到了Object.prototype,所以obj.a输出的是chris
  2. 再看obj.b,这里就不再赘述了,从Object.prototype开始说,在这里依然没找到b,那么继续向上找Object.prototype.__proto__,此时返回了null,所以obj.b输出的是undefined
  3. F.aF.bF是一个函数,它自身没有ab这两个属性,那么去它的构造函数原型(F.__proto__)上寻找,它的构造函数是Function,那么该构造函数的原型是Function.prototype,然而依然没有a,但是此时找到了b,所以F.b输出的是22,那么继续找Function.prototype.__proto__Function.prototype是一个对象,它的构造函数是Object,因此,找到了Object.prototype,所以F.a输出的是chris

3. 和原型相关的关键字和属性

  1. instanceof
const obj = {};
function a() {};
console.log(obj instanceof Object);  //true
console.log(obj instanceof Function);  //false
console.log(a instanceof Object);  //true
console.log(a instanceof Function);  //true

简单来说,可以把instanceof当做“是”,例如上述:
obj是个对象”,就正确;“obj是个方法”,很明显这是不正确的。实际上,instanceof是判断obj的原型链上是否有Object的原型。

  1. isPrototypeOf
const obj = {};
function a() {}
console.log(Object.prototype.isPrototypeOf(obj));  //true
console.log(Function.prototype.isPrototypeOf(obj));  //false
console.log(Object.prototype.isPrototypeOf(a));  //true
console.log(Function.prototype.isPrototypeOf(a));  //true

通过isPrototypeOf来判断obj的原型链上是否有object的原型。

  1. hasOwnProperty
Object.prototype.age = '22';
const obj = {
    name: 'chris'
}
console.log(obj.name); //chris
console.log(obj.age);  //22
console.log(obj.hasOwnProperty('name'));  //true
console.log(obj.hasOwnProperty('age'));  //false

判断是自身的属性,还是原型上的属性。

  1. Object.create()
Object.prototype.name = 'chris';
const obj = Object.create(Object.prototype);
console.log(obj.name);  //chris

Object.prototypeobj的隐式原型创建obj

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 众所周知js原型及原型链是很多开发者的一个疼点(我也不例外),我也曾多次被问起,也问过不少其他人,如果在自己没有真...
    奔跑的痕迹阅读 376评论 0 6
  • 为什么要理解原型和原型链,因为有利于我们理解和实现 JS对象继承。 __proto__ __proto__是什么W...
    微风玉米阅读 542评论 0 2
  • 构造函数是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创...
    Primers阅读 166评论 0 0
  • 记住一句“内功”: 「对象.__proto __ === 函数.prototype」 一. prototype原...
    Jason_Shu阅读 328评论 0 0
  • 一、原型 上回讲到,生成一个对象我们可以通过new构造函数来实现,如下: 但是,上面这样也有个缺陷,比如每个per...
    Da_xiong阅读 358评论 0 1