zoukankan      html  css  js  c++  java
  • 秒懂javascript的原型(prototype)对象、原型链的前世今生

    上文中我们通过原型方式,解决了多个实例的方法共享问题,接下来,我们就来搞清楚原型(prototype),原型链的来龙去脉.

    function CreateObj(uName) {
                this.userName = uName;
            }
            CreateObj.prototype.showUserName = function(){
                return this.userName;
            }
            var obj1 = new CreateObj('ghostwu');
            var obj2 = new CreateObj('卫庄');

    1,每个函数都有一个原型属性(prototype) , 这个属性是一个指针,指向构造函数的原型对象( CreateObj.prototype), 如上图中的第1根绿色的线

    2,在默认情况下,所有原型对象都会自动获得一个constructor属性,该属性的作用上文已经解释过,该属性包含一个指向prototype属性所在的函数,如上图的第2根绿色的线

    3,所有的实例( 通过构造函数new出来的, 原型对象[ 如CreateObj.prototype]等 )都包含一个隐式原型(__proto__),该指针指向实例的构造函数的原型对象,

    如上图中的第3根线和第4根线. obj1的构造函数是CreateObj, CreateObj的原型对象是CreateObj.prototype, obj2同理,所以:

    obj1.__proto__ === CreateObj.prototype //true

    obj2.__proto__ === CreateObj.prototype //true

    4,写在构造函数中, 为this赋值的属性和方法, 在画图的过程中,把他们画在对象上面,如userName这个是给对象赋值的属性,所以在obj1和obj2这两个对象上都会存在一个属性userName

    5,写在原型对象上的方法或者属性,应该把他们画在原型对象上,如

    CreateObj.prototype.showUserName = function(){
    return this.userName;
    }
    showUserName这个方法就要画在图中CreateObj.prototype上面
    6,当一个对象访问属性和方法的时候,他的访问规则叫(就近原则), 规则如下:
    当实例上面,存在属性或者方法时,直接用实例上面的,
    如果实例上面不存在属性和方法,就会沿着实例的__proto__指针指向的原型对象继续往上查找,如果找不到,值就是undefined.
    console.log( obj1.showUserName() ); //ghostwu
    console.log( obj2.showUserName() ); //卫庄
    在obj1,obj2上面是不存在showUserName这个方法的,所以会顺着__proto__查找到CreateObj.prototype原型对象上的showUserName方法
    如果,把CreateObj.prototype原型对象上的showUserName注释掉,那么obj1.showUserName和obj2.showUserName就会报错
    // CreateObj.prototype.showUserName = function(){
    // return this.userName;
    // }
    function CreateObj(uName) {
                this.userName = uName;
                this.showUserName = function(){
                    return '100';
                }
            }
            CreateObj.prototype.showUserName = function(){
                return this.userName;
            }
    
            var obj1 = new CreateObj('ghostwu');
            var obj2 = new CreateObj('卫庄');
    
            console.log( obj1.showUserName() ); //100
            console.log( obj2.showUserName() ); //100

     如果在构造函数中为this添加一个showUserName方法, 那么obj1和obj2就会直接调用this上面的,因为这两个方法会被画在图中的实例上,所以:

    console.log( obj1.showUserName === obj2.showUserName ); //false
    现在,你应该能明白,把属性和方法写在构造函数的原型对象(prototype)上之后,能实现多个实例属性和方法的共享的原理了吧
     
    什么是原型链?
    在前面,我有说过,所有的实例(包括原型对象)都有一个隐式原型__proto__,那么CreateObj.prototype这个原型对象,他的__proto__指向谁呢?
     
    function CreateObj(uName) {
                this.userName = uName;
                this.showUserName = function () {
                    return '100';
                }
            }
            CreateObj.prototype.showUserName = function () {
                return this.userName;
            }
    
            console.log( CreateObj.prototype.__proto__ ); //指向Object.prototype
            console.log( CreateObj.prototype.__proto__ === Object.prototype ); //true

    CreateObj.prototype.__proto__指向的是Object.prototype, 通过 全等运算符 (===) 测试之后为true

    Object.prototype.__proto__ 指向的是NULL;

    所以obj1.__proto__.__proto__.__proto__ === NULL

    这就是原型链,通过隐式原型把一些构造函数层层的串起来,通过上面这个图,就知道,为什么自定义的对象能调用toString, valueOf,等方法了吧?

    因为所有的对象都是继承自Object.

     出处:http://www.cnblogs.com/ghostwu 作者:ghostwu。

  • 相关阅读:
    Call KernelIoControl in user space in WINCE6.0
    HOW TO:手工删除OCS在AD中的池和其他属性
    关于新版Windows Server 2003 Administration Tools Pack
    关于SQL2008更新一则
    微软发布3款SQL INJECTION攻击检测工具
    HyperV RTM!
    OCS 2007 聊天记录查看工具 OCSMessage
    CoreConfigurator 图形化的 Server Core 配置管理工具
    OC 2007 ADM 管理模板和Live Meeting 2007 ADM 管理模板发布
    Office Communications Server 2007 R2 即将发布
  • 原文地址:https://www.cnblogs.com/art-poet/p/12112465.html
Copyright © 2011-2022 走看看