原型相关总结 | 青训营笔记

78 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的第3天

原型

在JavaScript中,每当定义一个函数数据类型(普通函数、类)时候,都会天生自带一个prototype属性,这个属性指向函数的原型对象,并且这个属性是一个对象数据类型的值。

3js高级_01.webp

每一个对象数据类型(普通的对象、实例、prototype......)也天生自带一个属性proto,属性值是当前实例所属类的原型(prototype)。实例原型中有一个属性constructor, 它指向构造函数

当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层Object为止。Object是JS中所有对象数据类型的基类

3js高级_02.webp

Function和Object的关系

(一)juejin.cn/post/684490…

function Foo(){
    //属性和方法
}
var f1 = new Foo();
f1的原型链:
  1. f1为普通对象,它的构造器为Foo,以Foo为原型,原型链第一链为f1.__proto__ == Foo.prototype;
  2. Foo.prototype(注意这边不是Foo)为json对象,即普通对象,构造器为Object,以Object为原型,得出原型链第二链Foo.prototype.__proto__ == Object.prototype;
  3. Object.prototype以Null为原型,原型链第三链为Object.prototype.__proto__ == null;

3js高级_03.webp

Foo的原型链:
  1. Foo为函数对象,它的构造器为Function,以Function为原型,原型链第一链为Foo.__proto__ == Function.prototype;
  2. Function.prototype为json对象,即普通对象,构造器为Object,以Object为原型,原型链第二链为Function.prototype.__proto__ == Object.prototype;
  3. 最后Object.prototype以Null为原型,原型链第三链为Object.prototype.__proto__ == null;

3js高级_04.webp

小结:

当js引擎执行对象的属性或方法时,先查找对象本身是否存在该方法,如果不存在则会在原型链上查找。

因而f1拥有Foo、Object的原型方法,Foo拥有Function、Object的原型方法。

注意,虽然f1原型链其中有一链是涉及到函数对象Foo,但f1并不拥有Function的原型方法,因为原型链并没有延伸到Function。

(二)juejin.cn/post/684490…

Object、Function和其它对象的关系可以归纳为下面四点:

  1. 一切对象都最终继承自Object对象,Object对象直接继承自根源对象null
  2. 一切函数对象(包括Object对象)都直接继承自Function对象
  3. Object对象直接继承自Function对象
  4. Function对象直接继承自己,最终继承自Object对象

下面进行逐条解释:

1.一切对象都最终继承自Object对象,Object对象直接继承自根源对象null

(1)一切对象的原型链最终都是.... → Object.prototype → null。例如定义一个num变量var num = 1,则num的原型链为x → Number.prototype → Object.prototype → null; 定义一个函数对象fnfunction fn() {},则fn的原型链为fn → Function.prototype → Object.prototype → null;等等...

(2)一切对象都包含有Object的原型方法,Object的原型方法包括了toString、valueOf、hasOwnProperty等等,在js中不管是普通对象,还是函数对象都拥有这些方法

2.一切函数对象(包括Object对象)都直接继承自Function对象

​ 函数对象包括了Function、Object、Array、String、Number,还有正则对象RegExp、Date对象等等,它们在js中的构造源码都是function xxx() {[native code]);,Function其实不仅让我们用于构造函数,它也充当了函数对象的构造器,甚至它也是自己的构造器。

从原型链可以佐证:

3js高级_05.webp

js中对象.__proto__ === 构造器.prototype,由此可以见得它们之间的关系。

疑问:Object对象都继承自Function对象了,而一切对象又都继承自Object对象,这边是不是有矛盾,Object对象和Function对象的关系是不是有点复杂?

答:其实疑问的内容就是上面结论的三四点,它们没有矛盾,关系也不复杂。

1.一切对象都继承自Object对象是因为一切对象的原型链最终都是.... → Object.prototype → null,包括Function对象,只是Function的原型链稍微绕了一点,Function的原型链为Function → Function.prototype → Object.prototype → null,它与其它对象的特别之处就在于它的构造器为自己,即直接继承了自己,最终继承于Object,上面的原型链可以在浏览器验证:

3js高级_06.webp

2.Object继承自Function,Object的原型链为Object → Function.prototype → Object.prototype → null,原型链又绕回来了,并且跟第一点没有冲突。可以说Object和Function是互相继承的关系。

3、4点的解答在第2点中

疑问:一切对象继承自Object,Object又继承自Function,那一切对象是不是都有Function的原型方法?

答:不对,普通对象都没有Function的原型方法。从我们所写原型链中可以看出,Object是继承自Function,而Object也有Function的原型方法(比如bind),但Object继承得到的方法储存于__proto__属性中,普通对象从Object继承到的原型方法却在于prototype属性中,因而不对。

疑问:Function对象怎么那么怪,自己继承自己?

答:是的。

总结:

Object对象直接继承自Function对象,一切对象(包括Function对象)直接继承或最终继承自Object对象。

3js高级_07.png