上周一面试腾讯,面试的题很根底,我自认为我的根底还算不错,然而 … 如同不是。看一下题吧
[].__proto__ === ?
[].__proto__.__proto__ === ?
[].__proto__.__proto__.__proto__ === ?
平时关注原型链关注的最多的就是函数,素来没有想过数组的原型链,看到了本人根底的破绽。
讲原型链,就先从原型讲起吧,以下内容就是我学习原型和原型链之后对这块的了解。
如有谬误,望斧正~
1. 原型
每个函数都会创立一个 prototype 属性,这个属性是一个对象,蕴含应该由特定援用类型的实例共享的属性和办法。实际上,这个对象就是通过调用构造函数创立的对象的原型。–《Javascript 高级程序设计》
下面这句话能够失去三个信息:
- 当咱们创立一个函数的时候,就会随之创立一个 prototype 属性,这个属性是一个 js 对象。(同时原型对象会取得一个 constructor 的属性,也是一个对象,指向相干的构造函数自身,例如:Person.prototype.constructor === Person;)
- 原型的用途是:在原型上的办法和属性能够被对象实例共享。比如说想给数组定义一个办法,让所有创立进去的数组应用,那就能够在 Array.prototype 上定义;
- 对象实例的__proto__指向构造函数的 prototype。
到这我对原型就有了一个大略的理解。然而我还搞不懂一个问题,不是说“每个函数都会创立一个 prototype 属性”吗?Array 是一个数组对象,为什么它会有 prototype 属性。
对于这个问题,我看了一下 MDN,如图:
Array 结构器会依据给定的元素创立一个 JavaScript 数组,然而当仅有一个参数且为数字时除外。咱们创立数组的时候能够间接 [] 创立,也能够 new Array()创立。
也就是说对于 Array(),是我的了解谬误,它并不是一个数组,而是一个构造函数,那么它有 prototype 属性也就不难理解啦。
2. 原型链
这里还是援用书上的话对原型链做出解释吧。
重温一下构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型有一个属性指回构造函数,而实例有一个外部指针指向原型。如果原型是另一个类型的实例呢? 那就意味着这个原型自身有一个外部指针指向另一个原型,相应地另一个原型也有一个指针指向另一个构造函数。这样就在实例和原型之间结构了一条原型链。这就是原型链的根本构想。–《Javascript 高级程序设计》
也就是说每个由构造函数创立进去的实例对象都有一个隐式原型__proto__,指向构造函数的原型 prototype,并且这个原型也有一个__proto__属性,就这样始终向上,直到止境 null。
到这里其实面试题的答案就曾经进去了,我把以上总结为谁的__proto__指向实例对象的 prtotype。其中的非凡状况是:Function 的__proto__指向本身的 prototype,
Object 的 prototype 的__proto__指向 null。
依照我的论断再看看面试题:
[].__proto__ === ?
[].__proto__.__proto__ === ?
[].__proto__.__proto__.__proto__ === ?
答案应该顺次为 Array.prototype,Object.prototype,null
第一个应该很好了解,[]是 new Array()创立进去的,所以 [].__proto__就指向了 Array 的原型 prototype;
第二个由第一个能够转换为 Array.prototype.__proto__,在原型那块说过 prototype 是一个 js 对象,那还能够转换为 Object.__proto__,最初就是 Object.prototype
第三个就是 Object.prototype.__proto__,也就是 null。
过后不会这个题的时候我对面试官说不太理解数组的原型,函数和对象的还能够,而后又给我出了个题,也不会。。。。
({}).__proto__ === ?
当初看很显著了,就是 Object.prototype。为啥用括号括起来呢,为了避免报错。