Js中Prototype、__proto__、Constructor、Object、Function关系介绍

Js中Prototype、__proto__、Constructor、Object、Function关系介绍

一    Prototype、__proto__与Object、Function关系介绍

        Function、Object:Js自带的函数对象。
         prototype,每一个函数对象都有一个显示的prototype属性,它代表了对象的原型(Function.prototype函数对象是个例外,没有prototype属性)。
          __proto__: 每个对象都有一个名为__proto__的内部隐藏属性,指向于它所对应的原型对象 (chrome、firefox中名称为__proto__,并且可以被访问到)。 原型链正是基于__proto__才得以形成(note:不是基于函数对象的属性prototype)。
       关于上面提到的函数对象,我们来看以下例子,来说明:
         var o1 = {};
         var o2 = new Object();
        
         function f1(){}
         var f2 =  function(){}
         var f3 =  new Function('str','console.log(str)');
    
        f3('aabb');    //  aabb
        console.log(' typeof Object:'+ typeof Object);             // function
        console.log(' typeof Function:'+ typeof Function);         // function
        console.log(' typeof o1:'+ typeof o1);    // object
        console.log(' typeof o2:'+ typeof o2);    // object
        console.log(' typeof f1:'+ typeof f1);    // function
        console.log(' typeof f2:'+ typeof f2);    // function
        console.log(' typeof f3:'+ typeof f3);    // function
  • 通常我们认为o1、o2是对象,即普通对象;f1、f2、f3为函数。
  • 但是其实函数也是对象,是由Function构造的,
  • f3这种写法就跟对象的创建的写法一样。f1、f2最终也都像f3一样是有Function这个函数构造出来的
  • f1、f2、f3为函数对象,Function跟Object本身也是函数对象。
        Js中每个对象(null除外)都和另一个对象相关联, 通过以下例子跟内存效果图来分析Function、Object、Prototype、__proto__对象 间的关系。

     function Animal(){
        
    }
     var  anim =  new Animal();
    
    console.log('***********Animal anim proto*****************');
    console.log(' typeof Animal.prototype:' + typeof Animal.prototype);   // object 
    console.log('anim.__proto__===Animal.prototype:'+(anim.__proto__===Animal.prototype));   // true
    console.log('Animal.__proto__===Function.prototype:'+(Animal.__proto__===Function.prototype));   // true
    console.log('Animal.prototype.__proto__===Object.prototype:'+(Animal.prototype.__proto__===Object.prototype));   // true
    
    console.log('***********Function proto*****************');
    console.log(' typeof Function.prototype:'+ typeof Function.prototype);   // function
    console.log(' typeof Function.__proto__:'+ typeof Function.__proto__);   // function
    console.log(' typeof Function.prototype.prototype:'+ typeof Function.prototype.prototype);  // undefined
    console.log(' typeof Function.prototype.__proto__:'+ typeof Function.prototype.__proto__);    // object
    console.log('Function.prototype===Function.__proto__:'+(Function.prototype===Function.__proto__));  // true

    console.log('***********Object proto*****************');
    console.log(' typeof Object.prototype:'+ typeof Object.prototype);   // object
    console.log(' typeof Object.__proto__:'+ typeof Object.__proto__);   // function
    console.log('Object.prototype.prototype:'+Object.prototype.prototype);   // undefied
    console.log('Object.prototype.__proto__=== null:'+(Object.prototype.__proto__=== null));   // null

    console.log('***********Function Object  proto关系*****************');
    console.log('Function.prototype===Object.__proto__:'+(Function.prototype===Object.__proto__));    // true
    console.log('Function.__proto__===Object.__proto__:'+(Function.__proto__===Object.__proto__));    // true
    console.log('Function.prototype.__proto__===Object.prototype:'+(Function.prototype.__proto__===Object.prototype));    // true

     /* ******************** 系统定义的对象Array、Date *************************** */
    console.log('**************test Array、Date****************');      
     var array =  new Array();
     var date =  new Date();
    console.log('array.__proto__===Array.prototype:'+(array.__proto__===Array.prototype));    // true
    console.log('Array.__proto__===Function.prototype:'+(Array.__proto__===Function.prototype));   // true
    console.log('date.__proto__===Date.prototype:'+(date.__proto__===Date.prototype));     // true
    console.log('Date.__proto__===Function.prototype:'+(Date.__proto__===Function.prototype));      // true

Function、Object、Prototype、__proto__内存关系图


        上面的内存图跟堆栈结构可以参照文章 Javascript_01_理解内存分配
        堆区图说明:
 
         Function.prototype函数对象图内部表示prototype属性的 红色虚框 ,只是为了说明这个属性不存在。

          通过上图Function、Object、Prototype关系图中,可以得出一下几点:
  1. 所有对象所有对象,包括函数对象的原型链最终都指向了Object.prototype,而Object.prototype.__proto__===null,原型链至此结束。
  2. Animal.prototype是一个普通对象。
  3. Object是一个函数对象,也是Function构造的,Object.prototype是一个普通对象。
  4. Object.prototype.__type__指向null。
  5. Function.prototype是一个函数对象,前面说函数对象都有一个显示的prototype属性,但是Function.prototype却没有prototype属性,即Function.prototype.prototype===undefined,所有Function.prototype函数对象是一个特例,没有prototype属性。
  6. Object虽是Function构造的一个函数对象,但是Object.prototype没有指向Function.prototype,即Object.prototype!==Function.prototype。

二    Prototype跟Constructor关系介绍

         在 JavaScript 中,每个函数对象都有名为“prototype”的属性 (上面提到过Function.prototype函数对象是个例外,没有prototype属性) ,用于引用原型对象。此原型对象又有名为“constructor”的属性,它反过来引用函数本身。这是一种循环引用(i.e.  Animal.prototype.constructor===Animal)。
         通过以下例子跟内存效果图来分析Prototype、constructor 间的关系。
    console.log('**************constructor****************'); 

    console.log('anim.constructor===Animal:'+(anim.constructor===Animal))    ;     // true
    console.log('Animal===Animal.prototype.constructor:'+(Animal===Animal.prototype.constructor))    ;     // true
    console.log('Animal.constructor===Function.prototype.constructor:'+(Animal.constructor===Function.prototype.constructor));    // true
    console.log('Function.prototype.constructor===Function:'+(Function.prototype.constructor===Function));     // true
    console.log('Function.constructor===Function.prototype.constructor:'+(Function.constructor===Function.prototype.constructor));     // true

    console.log('Object.prototype.constructor===Object:'+(Object.prototype.constructor===Object));     // true
    console.log('Object.constructor====Function:'+(Object.constructor===Function));     // true

 prototype、constructor内存关系图(在Function、Object、Prototype关系图上加入constructor元素):


        上图中,红色箭头表示函数对象的原型的constructor所指向的对象。
  1. 注意Object.constructor===Function;本身Object就是Function函数构造出来的        
  2. 如何查找一个对象的constructor,就是在该对象的原型链上寻找碰到的第一个constructor属性所指向的对象。
参考:
http://www.libuchao.com/2012/05/14/prototypes-in-javascript/ (JavaScript 的原型对象 Prototype)
http://rockyuse.iteye.com/blog/1426510 (理解js中的原型链,prototype与__proto__的关系)

在 JavaScript ,每个对象都有一个 __proto__ 属性,指向其构造函数的原型对象。而每个函数都有一个 prototype 属性,指向该函数实例化出来的对象的原型对象。 __proto__ 属性是一个指针,指向该对象的构造函数的原型对象。通过 __proto__ 属性可以访问原型对象的属性和方法。这个属性在 ES6 已经被标准化,可以用 Object.getPrototypeOf() 来获取对象的原型。 prototype 属性是函数的一个特殊属性,指向一个对象。当函数用作构造函数创建实例对象时,该对象的原型会指向构造函数的 prototype 属性指向的对象。也就是说,该对象可以访问构造函数原型对象的属性和方法。 举个例子: ``` function Person(name) { this.name = name; } Person.prototype.sayHello = function() { console.log(`Hello, my name is ${this.name}`); } const p = new Person('Tom'); console.log(p.__proto__ === Person.prototype); // true console.log(Person.prototype.constructor === Person); // true console.log(p.constructor === Person); // true ``` 在这个例子,我们定义了一个构造函数 `Person`,并给其原型对象添加了一个 `sayHello` 方法。我们通过 `new` 关键字实例化了一个 `Person` 对象 `p`。这个对象的 `__proto__` 属性指向了 `Person.prototype`,因此我们可以通过 `p.__proto__.sayHello()` 或者 `Person.prototype.sayHello.call(p)` 来调用 `sayHello` 方法。同时,我们也可以通过 `Person.prototype` 来访问 `Person` 构造函数原型对象的属性和方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值