Object,Array,Number,String,普通函数,普通对象,Function等的原型链关系——多次面试失败总结的经验

以前说到原型链就只知道通过原型链继承,构造函数和它的实例之间的原型链的关系啊这些东西,最近面试被问得很懵,后来看到一篇文章总结的特别好,当时看明白了,后来面试又忘了一部分,所以今天打算自己总结一下,加深印象。

JS中没有类的概念,万物皆是对象

其他语言中的继承于类,在JS中是 对象继承于对象。所以万物都有__proto__属性,但是prototype属性却不是所有对象都有,只有构造函数才有。
例如 使用instanceof用来测试变量是不是Object类型,除了基本数据类型外,其他的比如函数、数组、键值对对象以及比较特殊的几个构造函数——Number、Array、String、Boolean、Function等,用instanceof Object结果都是true

  1. instanceof的原理是通过原型链一直查找,找到相同的原型就会返回true
  2. 在我们平时使用构造函数实例化对象的过程中,我们知道对象有一个属性叫__proto__,这个属性是指向它的构造函数的原型prototype

面试中被问到typeof Object返回什么?
这个回答上来了,是function,因为Object是对象的构造函数,它是Function的实例,实际上所有的构造函数例如Array、Number都是Function的实例。下面我们通过代码使用上面两条测试来证明:

Object instanceof Function // true
Array instanceof Function //true
Object.__proto__ === Function.prototype // true
Number.__proto__ === Function.prototype // true

所以说Number、Array、String、Boolean这些构造函数都是Function的实例,那么Function也是构造函数,那么Function是不是 Function 自身的实例呢?
答案是:是的。

Function instanceof Function // true
Function.__proto__ === Function.prototype // true

如上所示,这就是神奇的地方所在了,Function的对象属性__proto__指向了它自己的原型prototype
到这里我们可以得出几个结论:

  • 任何对象都有__proto__属性,但是只有函数才有prototype属性
  • 同一个对象的__proto__属性和prototype属性是没有关联的,除了Function
  • 对象的__proto__属性是用来和其父“类”关联的,构造函数的prototype是用来和其实例关联的,所以对于同时存在这两个属性的构造函数来说,这两个属性之间是没有什么关系的,也就对应上一条。
  • 任何构造函数都是Function的实例,任何对象都是Object的实例
  • 任何对象直接调用方法,例如obj.foo(),在实例本身没有这个属性的情况下,都是从其__proto__属性上查找的,也就是从该对象的构造函数的prototype属性上查找。

这里有一道典型的题目就是考对上面几条的理解,我们都知道Object.prototype.toString方法可以用来判断数据类型,那么用Object.toString可以吗。
答案是:不可以。
因为Object.toStringObject.__proto__.toString,也就是Function.prototype.toString,和Object.prototype.toString根本不是同一个函数。

下面我们通过一张图来描述JS中的原型链。

JS中的原型链

在这里插入图片描述
OK,这就是JS中的原型链的样子,都是围绕前面提到的几点进行绘制的。

参考链接

附上之前看的文章的链接:再谈javascriptjs原型与原型链及继承相关问题

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章