周一面试腾讯,面试的题很基础,我自认为我的基础还算不错,但是…好像不是。看一下题吧
[].__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。为啥用括号括起来呢,为了防止报错。
|