• js原型和原型链[转]


    附上原文出处:http://hzjavaeyer.group.iteye.com/group/wiki/3086-JavaScript-core-concepts

    一、概念:

    原型对象:JavaScript对象是一个属性的集合,另外有一个隐式的对象:原型对象。原型的值可以是一个对象或者null。一般的引擎实现中,JS对象会包含若干个隐藏属性,对象的原型由这些隐藏属性之一引用,我们在本文中讨论时,将假定这个属性的名称为"__proto__"(事实上,SpiderMonkey内部正是使用了这个名称,但是规范中并未做要求,因此这个名称依赖于实现)。

    原型链:由于原型对象本身也是对象,根据上边的定义,它也有自己的原型,而它自己的原型对象又可以有自己的原型,这样就组成了一条链,这个就是原型链,JavaScritp引擎在访问对象的属性时,如果在对象本身中没有找到,则会去原型链中查找,如果找到,直接返回值,如果整个链都遍历且没有找到属性,则返回undefined.原型链一般实现为一个链表,这样就可以按照一定的顺序来查找。

    二、实例:

    No1:

     1 var base = {
     2     name : "base",
     3     getInfo : function(){
     4        return this.name;
     5     }
     6 }
     7  
     8 var ext1 = {
     9     id : 0,
    10     __proto__ : base
    11 }
    12  
    13 var ext2 = {
    14     id : 9,
    15     __proto__ : base
    16 }
    17  
    18 print(ext1.id);
    19 print(ext1.getInfo());
    20 print(ext2.id);
    21 print(ext2.getInfo());

    结果为:

    0
    base
    9
    base

    图1:上例中对象的原型链

    可以看到,当执行ext1.id时,引擎在ext1对象本身中就找到了id属性,因此返回其值0,当执行ext1.getInfo时,ext1对象中没有找到,因此在其原型对象base中查找,找到之后,执行这个函数,得到输出”base”。

    我们将上例中的ext1对象稍加修改,为ext1对象加上name属性:

    NO2:

     1 var base = {
     2     name : "base",
     3     getInfo : function(){
     4        return this.name;
     5     }
     6 }
     7  
     8 var ext1 = {
     9     id : 0,
    10     name : "ext1",   
    11     __proto__ : base
    12 }
    13  
    14 print(ext1.id);
    15 print(ext1.getInfo());

    可以得到:

    0
    ext1

    这个运行效果同样验证了原型链的运行机制:从对象本身出发,沿着__proto__查找,直到找到属性名称相同的值(没有找到,则返回undefined)。

    我们对上例再做一点修改,来更好的演示原型链的工作方式:

    NO3:

     1 var base = {
     2     name : "base",
     3     getInfo : function(){
     4        return this.id + ":" + this.name;
     5     }
     6 }
     7  
     8 var ext1 = {
     9     id : 0,
    10     __proto__ : base
    11 }
    12  
    13 print(ext1.getInfo());

    我们在getInfo函数中加入this.id,这个id在base对象中没有定义。同时,删掉了ext1对象中的name属性,执行结果如下:

    0:base

    应该注意的是,getInfo函数中的this表示原始的对象,而并非原型对象。上例中的id属性来自于ext1对象,而name来自于base对象。这个特性的机制在10.3小节再做讨论。如果对象没有显式的声明自己的”__proto__”属性,这个值默认的设置为Object.prototype,而Object.prototype的”__proto__”属性的值为”null”,标志着原型链的终结。

    三、构造器:

    我们在来讨论一下构造器,除了上边提到的直接操作对象的__proto__属性的指向以外,JavaScript还支持构造器形式的对象创建。构造器会自动的为新创建的对象设置原型对象,此时的原型对象通过构造器的prototype属性来引用。

    我们以例子来说明,将Task函数作为构造器,然后创建两个实例task1, task2:

     1 function Task(id){
     2     this.id = id;
     3 }
     4  
     5 Task.prototype.status = "STOPPED";
     6 Task.prototype.execute = function(args){
     7     return "execute task_"+this.id+"["+this.status+"]:"+args;
     8 }
     9  
    10 var task1 = new Task(1);
    11 var task2 = new Task(2);
    12  
    13 task1.status = "ACTIVE";
    14 task2.status = "STARTING";
    15  
    16 print(task1.execute("task1"));
    17 print(task2.execute("task2"));

    结果:

    execute task_1[ACTIVE]:task1
    execute task_2[STARTING]:task2

    构造器会自动为task1,task2两个对象设置原型对象Task.prototype,这个对象被Task(在此最为构造器)的prototype属性引用,参看下图中的箭头指向。

    图2:构造器方式的原型链

    由于Task本身仍旧是函数,因此其”__proto__”属性为Function.prototype, 而内建的函数原型对象的”__proto__”属性则为Object.prototype对象。最后Obejct.prototype的”__proto__”值为null.

  • 相关阅读:
    LeetCode对撞指针汇总
    167. Two Sum II
    215. Kth Largest Element in an Array
    2018Action Recognition from Skeleton Data via Analogical Generalization over Qualitative Representations
    题解 Educational Codeforces Round 84 (Rated for Div. 2) (CF1327)
    题解 JZPKIL
    题解 八省联考2018 / 九省联考2018
    题解 六省联考2017
    题解 Codeforces Round #621 (Div. 1 + Div. 2) (CF1307)
    题解Codeforces Round #620 (Div. 2)
  • 原文地址:https://www.cnblogs.com/zhangxue521/p/6715515.html
Copyright © 2020-2023  润新知