js原型链小总结

最近在刷掘金的时候,发现有人发js原型继承方面的东西。关于js原型集成,我在刚学js的时候也比较浅入的研究过,当时是记住了,到现在我依旧是很模糊,于是乎我决定研究一次,并将结果记录下来,方便以后查阅。

JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。


准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的prototype属性上,而非对象实例本身。


在传统的 OOP 中,首先定义“类”,此后创建对象实例时,类中定义的所有属性和方法都被复制到实例中。在 JavaScript 中并不如此复制——而是在对象实例和它的构造器之间建立一个链接(它是__proto__属性,是从构造函数的prototype属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法

以上是来自于 MDN 对js中原型的描述。

__proto__prototype 区别

我们可以通过 __proto__ 或者 Object.getPrototypeOf(obj) 来获取一个对象的原型对象,从而实现自下向上通过原型链来查找方法和属性,而 prototype 是一个对象通过new操作符来创建一个新对象的时候,赋予新对象 __proto__ 属性,也就是上面括号中加粗文本的总结。

( new Foo ).__proto__ === Foo.prototype
( new Foo ).prototype === undefined

Object.O1='';
Object.prototype.Op1='';

Function.F1 = '';
Function.prototype.Fp1 = '';

Cat = function(){};
Cat.C1 = '';
Cat.prototype.Cp1 = '';

mycat = new Cat();
o = {};

// EDITED: using console.dir now instead of console.log
console.dir(mycat);
console.dir(o);

测试以上代码我们可以发现上图的原型链关系。

这其中最奇怪的是: Object.__proto__ === Function.prototype, 而不是 Object.prototype,这表明 Object 是 Function的实例。

Object是夏娃,Function是亚当,亚当(Function)使用它的第七根肋骨(Function.prototype)创造了夏娃(Object)。但是又是谁创造了亚当(Function)呢? 肯定不是神。。。答案就是创建js语言的作者(也就是:世界上根本没有神,只是某些人做到了普通人办不到的事情...)

实际上 Object 类是 Function的实例。比如正常的Foo类是Function的实例,Foo.__proto__ === Function.prototype。原因:当我们在js中创建一个类的时候,我们直接上就是创建一个函数(function,我们能进行new操作的,其类型都是function),它应该是Function的实例(Function本身也是一个函数)。Object和Function都比较特殊,实际上他们都是正常的Foo类本质一样。

因此,下边的四个值中的任意一个都(===)其他3个

Function.prototype
Function.__proto__
Object.__proto__
Cat.__proto__

这也就意味着,我们往Function.prototype上添加属性,也会自动添加到对象__proto__为Function.prototype的一些对象(Date,Array,Number,Object,Boolean,String,Event,Error,RegExp)上:

Function.prototype.address = 'china'
"china"

Array.address
"china"

Object.address
"china"

现在我们原型从Foo.__prototype__Function.__proto__ ,我查看下 Function.__proto__ 的类型:

typeof Function.__proto__
"function"

啊!是不是惊呆了,我们一直说原型对象,类型竟然不是对象。。。以下是 ECMAScript 5 定义:

15.3.4 Properties of the Function Prototype Object


Function 原型对象是一个函数对象([class] Function),当在调用时,接收任何参数并且返回 undefined

原型链我们追溯到了 Function.__proto__ ,我们知道 Function.__proto__ === Function.prototype,并且此时的类型是function,我们再往上找 只能是 Function.__proto__.__proto__ ,也就是 Function.prototype.__proto__,

typeof Function.prototype.__proto__
"object"

typeof Object.prototype
"object"

目前我们发现,这俩货居然类型一样,莫非。。。没错:函数也是对象,Function.prototype(类型是function)也是Object的实例

Object.prototype === Function.prototype.__proto__
true

我们查找原型链目前是 Foo.__prototype__, Function.__proto__, Function.__proto__.__proto__(Object.prototype),好嘛,终于跟Object扯上关系了,好,我们接着往上找,

Object.prototype.__proto__
null

我直呼好家伙,终于到头了

最后附上两种总结图:

posted @ 2021-05-06 23:05  韩帅  阅读(75)  评论(0编辑  收藏  举报