• javaScritp 中prototype属性继承原理详解


             转载请说明出处:http://blog.csdn.net/liuqiwen0512/article/details/8095306

                 上一篇文章我们说了jQuery  运用jQuery.fn.init.prototype = jQuery.fn;巧妙的避开了 instanceof 的运算。

           要解释这个问题就需要先了解prototype属性的继承原理,比如toString方法,我们创建一个对象不用给对象

           添加toString方法照样可以用。这是为什么,是创建对象的时候js自动给对象添加了toString方法,还是通过上面途径

           找到了toString方法。这里可以告诉你我们用new关键字创建出来的对象要是你没给它添加toString属性的话,

           那么它调用的就是Object对象的prototype.toString。这是为什么,有的童鞋说是继承,但是它又是怎样继承的,

           toString到底放在哪,看完这篇文章你就明白了。还有一个问题就是instanceof运算符到底是怎么运算的,

           它的依据和原理是什么,同样看完这篇文章你也就明白了。

    protype继承原理:

                 其实我们用function关键字声明的方法,在后台js会把他们创建成Function对象。这个对象中有两个属性,一个是prototype

                 这个属性是显式属性也就是说我们可以访问的属性。还有一个属性就是__proto__这个属性是隐式的,也就是说默认

                 情况下我们不可以访问,而且这个属性在个浏览器的表示可能还不一致,默认情况下是__proto__。这个属性在chrome

                 浏览器是可以访问的,但是在IE下就不可以访问,不知道是IE不让访问,还是表示不一样,没研究。

                 prototype属性是一个指针,指向一个实例化的Object对象。这个对象默认有两个属性,一个是显式属性constructor,

                 这个属性是指向prototype属性所在的构造函数,这样prototype属性所指向的Object对象和构造函数就形成了循环

                 指向。还有一个隐式属性默认是__proto__指向它的父对象也就是js内置的Object对象的prototype属性所指向的

                 一个实例化的Object对象。

    下面看例子说话:

    [javascript] view plain copy
     
     print?
    1. function Person(){  
    2.       this.name="刘奇文";  
    3.       this.age=22;  
    4. }  
    5.     Person.prototype={  
    6.            showName:function(){  
    7.               console.log(this.name);  
    8.            },  
    9.            name:"liuqiwen"  
    10.     }  
    11. function Man(){  
    12.       this.name="刘奇文man";  
    13.       this.age=22;  
    14. }  
    15.     Man.prototype=Person.prototype;  
    16.   
    17. var man1=new Man();  
    18. console.log(man1.name);//结果:刘奇文man  
    19. man1.showName();//结果:刘奇文man  
    20. delete man1.name;//删除实例中的name属性  
    21. console.log(man1.name);//结果:liuqiwen  
    22. man1.showName();//结果:liuqiwen  
    23. console.log(man1.constructor);//结果:function Object() {[native code]}  
    24. console.log(man1 instanceof Man);//结果:true  
    25. console.log(man1 instanceof Person);//结果:true  
    26. console.log(man1 instanceof Object);//结果:true  

    上面代码解释:

                 创建一个构造函数Person,给构造函数添加两个属性。然后再初始化构造函数的原型链prototype属性,

           给prototype添加两个属性,在创建一个构造函数Man,给构造函数添加两个属性。然后再初始化 构造函数

          的原型链prototype属性,让prototype属性等于Person的prototype属性,也就是说这两个构造函数的prototype

          指向的是同一个Object对象。然后创建一个man1的一个实例,调用man1的name属性得到结果正是实例中

          属性的值,调用man1的showName方法得到也是实例中属性值结果都正确,我们再删除实例中name属性

          我们再重复上面的操作发现结果是原型链中属性的值,我们再调用man1的constructor属性,这个属性

          上面已经说过是得到这个实例的构造函数的引用,上面我们既没有给实例定义这个属性,原型链中也

          没有这个属性,那么调用这个属性得到的值是哪里来的,为什么还是Object。

    对象属性的查找顺序:

                 其实我们没有给prototype属性赋值时,prototype属性默认指向的Object对象是有

          constructor这个属性的,由于这个属性是显式的是我们可控制的,所以当我们给prototype属性初始化

          时是让它指向了另一个对象,而这个对象中没有此属性,我们也可加上这个属性。当对象在实例中

          没有找到要调用的属性,那么他会从他的隐式属性__proto__所指向的原型链中查找,如果还没找到,

           那么他会继续查找原型链中的隐式__proto__属性所指向的对象,

          也就是实例的父对象Object对象的原型链,所以返回值是Object的构造函数。

    总结:实例对象属性查找顺序是   实例对象内部---->构造函数原型链---->实例对象父对象的原型链。

    instanceof运算符:

            上面man1 instanceof Man结果为true,运算符先运算Man.prototype然后再查找man1中的__proto__

            所指向的Object是否为Man.prototype。由于Person.prototype和Man.prototype指向的是同一个Object

            所以man1 instanceof Person结果为true。man1 instanceof Object由于man1中的__proto__指向的

            不是Object.prototype所以运算符会继续查找__proto__指向的对象中的__proto__属性,也就是实例

             父对象的prototype指向的对象,Object是实例man1的父对象所以运算结果为true。

    通过关系图来了解他们之间的关系

    继承关系图:

     下篇分析下构造函数和Object之间的关系 ,js内置对象之间的关系。

    上图中 Function 和 Object之间的关系有些地方好像不太对,

    还需研究,如果哪位仁兄知道的话,请赐教。

     转载请说明出处:http://blog.csdn.net/liuqiwen0512/article/details/8095306

  • 相关阅读:
    sudo命令 sudoers文件
    sscanf函数
    printf格式化输出
    c文件操作
    string和char*
    c去除空格 小写转大写
    主机序和网络序转换
    ulimit用法
    mysql基础(附具体操作代码)
    ES6 class
  • 原文地址:https://www.cnblogs.com/shiguangshuo/p/5217760.html
Copyright © 2020-2023  润新知