js中的__proto__和prototype

原文地址:https://blog.csdn.net/god_wen/article/details/78996302

这两天想看看 jquery的源代码。可是一开始就懵逼了。什么是js的原型链呢?于是在网上寻找答案,发现还挺多的。于是就来这里总结一番。

想弄清原型链其实就是弄清楚__proto__和prototype的关系。

任何对象都有一个__proto__属性 
任何方法都有一个prototype属性,prototype也是一个对象 ,所以其中也有一个___proto__

我们先来看prototype属性

   var fn=function(){

    };
    console.log(fn.prototype);

这里写图片描述

可以看见prototype中有两个属性constructor和__proto__。constructor指向函数自己。同时可以看见prototype中也有__proto__。因为prototype也是一个对象。

prototype是拿来干什么的呢。它的作用很像java中的静态属性/方法。其中的对象可以给所有实例使用,如

    var fn =function (){

    };
    fn.prototype.name='wen';
    fn.prototype.age='18';

    var obj1=new fn();
    var obj2=new fn();


    console.log(obj1.name);
    console.log(obj2.age);

输出

wen
18

那么__proto__是什么呢?像要弄清这点我们想要知道js中创建对象的一些细节。js创建对象我们有如下三种方法

1 通过构造函数创建对象

var obj=new Object();
  • 2通过Object.create创建对象
var obj1={};
var obj2= Object.create(obj1);

3 通过花括号创建,如

var obj={};
  • 其实上述三种方法都是通过构造函数创建的。而第三种其实调用的时Object()方法创建的。所以我们可以怎么认为

js中的对象都是new +构造函数创建的。而这个构造函数就是我们定义的函数。

而所有的对象中都有__proto__属性,这个属性就是一个指针,指向构造函数中的prototype属性。

我们可以做一个简单的验证


    var obj1={};
    console.log(obj1.__proto__===Object.prototype);
  • //输出
true
  • 通过上面的分析,我们知道js中声明的方法其实就是一个类,它的构造函数就是自己。我们可以向其中的prototype塞入各种对象。这些对象会被所有实例继承。而所有的实例都有一个proto指针指向着构造函数的prototype属性。

tips:

遵循ECMAScript标准,someObject.[[Prototype]] 符号是用于指向 someObject的原型。从 ECMAScript 6 开始,[[Prototype]] 可以用Object.getPrototypeOf()和Object.setPrototypeOf()访问器来访问。这个等同于 JavaScript 的非标准但许多浏览器实现的属性 __proto__。

————————————-分割线—————————————————- 
下面是深入的分析。

非函数对象的创建

非函数对象只有__proto__,它指向构造函数的prototype属性。我们知道prototype的属性中也有__proto__。那么该__proto__指向谁呢。回忆下一我之前说的所有对象的__proto__指向创建它们的构造函数的prototype。那么谁创建的prototype的呢?。那当然是Object构造函数了。 
所以函数中的prototype属性中的__proto__指向的是Object构造函数的prototype属性。但是问题又来了,这个prototype中也有__proto__,这不死循环了。很高兴的告诉你这个prototype中__proto__等于null的。所以不会死循环的,除非你把它改了。

如下图 
这里写图片描述

图片是我之前存下来的,忘了出自哪里了。如果侵害了别人的别人的著作。希望告诉我,我会主动下架的。

我们来验证一下


    var obj1={};


    console.log(obj1.__proto__.__proto__===null);

//输出

true
  • 好我们接着思考

函数对象的创建

函数对象有prototype和__proto__属性。prototype中的__proto__指向的是Object构造函数,这就不用多说了。我们来看__proto__。

函数对象的__proto__指向构造函数的prototype。而函数的构造函数是Function构造函数。接着 
Function的prototype中的__proto__指向谁呢?前面已经说了指向Object构造函数。那么Function函数的__proto__指向谁呢。答案是指向自己,因为Function函数也是一个函数。来给大家上一张神图。

这里写图片描述

接着我们拿出点佐证出来。

    var fn =function (){

    };
    //fn.prototype.__proto__->Object.prototype
    //Object.prototype.__proto__===null?
    console.log(fn.prototype.__proto__.__proto__===null);
    //fn.__proto__->Function.prototype
    //Function.prototype.__proto__->Object.prototype
    //Object.prototype.__proto__===null
    console.log(fn.__proto__.__proto__.__proto__===null);

从上图你可以看见其实Object构造函数的__proto__ 
也是指向Function构造函数的。

总结

通过上面的分析,我们可以发现js代码的设计是非常巧妙的。

总结一下,当你需要理清js中的__proto__和prototype的链接顺序,你只需记住。

1函数对象有__proto__和prototype属性 
2非函数对象只有__proto__属性 
3prototype中有__proto__属性。且是Object构造函数创建的 
4函数对象__proto__指向它的创建者及Function构造函数 
5Function构造函数__proto__指向它自己 
6Object对象的prototype中的__proto__是null

猜你喜欢

转载自blog.csdn.net/weixin_36185028/article/details/81220423
今日推荐