欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

js的__proto__,prototype、constructor属性

程序员文章站 2024-03-12 23:12:38
...

根据JavaScript核心以及原文JavaScript. The core.加上自己的理解做一个总结。

prototype与__proto__、constructor理解

  • prototype是每个函数都有的属性,它指向的是一个(原型)对象,是创建原型链的重要属性;

  • __proto__描述实例化对象与其原型对象之间的关系,每一个对象均可看成另一个对象的实例对象,故每一个对象都有__proto__属性;

  • constructor是每个原型对象都有的属性,始终指向创建该对象(自身)的构造函数,每一个函数都有prototype属性,prototype.constructor指向该构造函数。

以内置对象Object()为例:

    var obj=new Object();  
    typeof obj.__proto__;//"object"  
    obj.__proto__===Object.prototype;//true  
    obj.constructor;//function Object(){native code}  
    Object.prototype.constructor===obj.constructor;//true  

  obj是构造函数Object()的实例化对象,则必然有__proto__属性指向构造该实例对象的原型即Object.prototype,也是一个对象。

js的__proto__,prototype、constructor属性

  可以从结果知道obj.constructor指向了obj对象的构造函数Object(),然而这并不表明obj自身有constructor属性,而是根据原型链向上查找。当自身没有找到属性,就会查找obj.__proto__,就是Object.prototype,从而找到constructor属性,由Object.prototype.constructor===obj.constructor;返回true就可以知道。

内置函数与Function.prototype的关系

js的__proto__,prototype、constructor属性

这个图表明了整个js中函数与对象的关系,以及prototype、__proto__、constructor的指向。

  由上图可以知道,Object()其实也是一个Function()函数的实例化对象,也有__proto__属性,指向Function.prototype从而形成了原型链。

W3C中对Math对象有如**释:

Math 对象并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math(),像 Math.sin() 这样的函数只是函数,不是某个对象的方法。您无需创建它,通过把 Math 作为对象使用就可以调用其所有属性和方法。

在控制台运行以下代码,以Object()、Array()、以及Math对象为例:

    Object.__proto__===Function.prototype;//true
    Object.constructor;//function Function(){native code}
    Object.constructor===Object.__proto__.constructor;//true
    Array.__proto__===Function.prototype;//true
    Array.constructor;//function Function(){native code}
    Array.constructor===Array.__proto__.constructor;//true
    Math.__proto__===Object.prototype;//true
    Math.prototype;//undefined
    Math.constructor;//function Object(){native code}
    Math.constructor===Math.__proto__.constructor;//true
  • 除了Math对象以外,其他的内置对象均是Function通过new创建出来的,也是函数,既然是函数则肯定有prototype属性,它所指向的是它们自身的原型函数Array.prototype,String.prototype等。

  • 它们的__proto__属性均指向它们构造函数的原型Function.prototype。它们的constructor属性均指向它们的构造函数function Function(){...};

  • Math对象虽然没有prototype属性,但是它也有__proto__属性,指向Object.prototype。

注意:实例化对象自身是没有constructor属性,是从其__proto__原型中继承过来的。

Function()函数是通过new自己本身创建出来的,Function.__proto__指向的是Function.prototype,Function.constructor指向的是function Function(){...}。

Function.prototype与Object.prototype的关系

  由上面可以知道内置对象(除Math)的__proto__属性都指向Function.prototype,那Function.prototype呢?
在控制台运行以下代码:

    typeof Function.prototype;//function
    Function.prototype.prototype;//undefined
    Function.prototype.__proto__===Object.prototype;//true
    typeof Object.prototype;//"object"
    Object.prototype.__proto__;//null

可以看出Function.prototype其实是一个函数,但是它的prototype指向的值却是undefined,这算是一个特例。Function.prototype的__proto__属性指向Object.prototype。

**所有的对象原型包括函数对象原型最终都指向Object.prototype,而Object.prototype的__proto__指向null**

普通函数和对象的prototype、__proto__、constructor

  自定义构造函数Test(),查看它的prototype、__proto__、constructor:

    function Test(num1,num2){
         this.n1=num1;
         this.n2=num2;
    }
    var obj=new Test();

结果如下:
js的__proto__,prototype、constructor属性

object.prototype形成了原型链;Test.__proto__指向构造函数Function()的原型Function.prototype,而Function.prototype.__proto__指向Object.prototype也形成了原型链;Test.prototype的constructor属性指向了构造该对象原型的构造函数function Test()。

总结:

  • 每一个函数都有prototype属性,可以指向一个对象或者null;

  • __proto__描述实例化对象与其原型对象之间的关系,每一个对象均可看成另一个对象的实例对象,故每一个对象都有__proto__属性;

  • 每一个function.prototype对象默认有一个属性constructor,且constructor始终指向创建该对象原型的构造函数;

  • 所有内置对象中,除了Math对象没有构造函数以外,其余所有内置对象均为Function()函数通过new创建出来的实例化对象,Function()函数是通过new自己本身创建出来的,Function.__proto__指向的是Function.prototype,Function.constructor指向的是function Function(){...}。

  • Function.prototype是一个函数,但它是个特例,没有prototype属性。


参考

1:http://weizhifeng.net/javascript-the-core.html
2:http://dmitrysoshnikov.com/ecmascript/javascript-the-core/