zoukankan      html  css  js  c++  java
  • Javascript原型钩沉

    写在前面的总结:

    JS当中创建一个对象有好几种方式,大体上就是以下几种:

    ①通过var obj ={...}

    这种方式一般称为字面量方式,{}直接写需要定义的字段

    var obj = new Object()

    Object对象是JS的内建对象

    ③通过构造函数创建对象

    例如:

    function father(){
    this.name = "I'm your father!"
    }
    var f = new father();

    这里通过构造函数的方式创建了一个对象实例f

    ④通过Object.create创建对象

    Object.create(proto [, propertiesObject ]) E5中提出的一种新的对象创建方式,第一个参数是要继承的原型,如果不是一个子函数,可以传一个null,第二个参数是对象的属性描述符,这个参数是可选的。

    1.原型是什么?

    首先应该知道我们创建的每一个函数都有一个prototype属性,这个属性是一个指向原型对象的指针,这个原型对象的用途是包含由特定类型所有实例共享的属性和方法。

    也就是说,每创建一个函数,就会创建一个对应的原型对象。

    一个对象的真正原型是被对象内部的[[Prototype]]属性(property)所持有。ECMA引入了标准对象原型访问器Object.getPrototype(object),到目前为止只有Firefox和chrome实现了此访问器。除了IE,其他的浏览器支持非标准的访问器__proto__,如果这两者都不起作用的,我们需要从对象的构造函数中找到的它原型属性。 

    还是挺抽象,举个例子吧:

    function Person(){
        this.name="大橙子";
        this.age = 26;
        this.sex = "纯爷们";
    }
    
    var p = new Person();
    
    console.log(p.name);
    console.log(p.age);
    console.log(p.sex);
    console.log(p.career);
    
    Person.prototype.career = "程序员";
    console.log(p.career);
    
    输出结果:
    [Web浏览器] "大橙子"     
    [Web浏览器] "26"     
    [Web浏览器] "纯爷们"     
    [Web浏览器] "undefined"     
    [Web浏览器] "程序员"     

    上面Person.prototype.career = "程序员";就是通过原型来添加的属性,所有继承这个Person的对象,都具有career这个属性。

    这个过程是这样的,当输出p.career的时候,首先会在对象p找,因为p对象没有career这个属性,这就是为什么会输出undefined的原因,然后继续向上查找,在Person.prototype中找到了career,然后就输出了“程序员”。 

    要了解原型的概念,应该知道_proto_prototype以及constructor他们之间是什么联系

    那么就来分析一下var p = new Person(); 这个过程

    上面这个分析图可以很好的展示,三者的关系,

    首先要知道几个地方,

    第一点:就是Empty()函数,这个函数是所有函数的原型,并且他很特殊没有prototype

    第二点:__proto__是内部原型,prototype是构造器原型(构造器其实就是函数,所以上面才说这个是函数对象才有的,而_proto_是每个对象都有的。我的理解它才是构成原型链的原因

    ①.从中间开始看,首先我创建了一个函数person(),同时JS帮我创建了一个原型对象person.prototype

    并把我的person()prototype指针指向了它,原型对象中有一个constructor属性,指向了我的person()函数。

    ②.当我new一个person实例的时候,新创建的实例对象p_proto_指向了person.prototype

    这也是为什么,我在person.prototype中添加属性,p也能反映出来的根本原因。

    ③.person.prototype也是一个对象,那么他的_proto_是谁呢,如上图就是Object.prototype,这也不难理解,因为ObjectJavascript中所有对象的父级对象,我们创建的所有对象都继承于此,包括内建对象。同样因为它也是对象,那么它也拥有_proto_,图上表示了它的原型就是null

    我们可以打印每一属性的值来进行确认:

    //Person函数的原型对象
    console.log(Person.prototype);
    //Person原型对象的Constructor
    console.log(Person.prototype.constructor);
    //判断实例对象p的原型,是不是Person.prototype
    console.log(p.__proto__ === Person.prototype?true:false);
    //函数对象Person的_proto_,是不是Empty()
    console.log(Person.__proto__);
    //Empty()是不是没有prototype
    console.log(Person.__proto__.prototype);
    //Empty()的__proto__是不是Object.prototype
    console.log(Person.__proto__.__proto__ === Object.prototype?true:false);
    //Person.prototype的_proto_是不是Object.prototype
    console.log(Person.prototype.__proto__ === Object.prototype?true:false);
    //Object.prototype的_proto_是不是null
    console.log(Object.prototype.__proto__);
    
    输出结果:
    [Web浏览器] "[object Object]"    
    [Web浏览器] "function Person(){
        this.name="大橙子";
        this.age = 26;
        this.sex = "纯爷们";
    }"    
    [Web浏览器] "true"
    [Web浏览器] "function Empty() {}"    
    [Web浏览器] "undefined"    
    [Web浏览器] "true"    
    [Web浏览器] "true"    
    [Web浏览器] "null"    

    2.原型链

    上面的原型我们举的例子没有特别明显的显示这个链的过程,看不到具体的继承关系,所以再分析一个例子

    Object.prototype.dead = true;
    
    function animal(){} 
    animal.prototype.eat=true;
    animal.prototype.sleep=true;
          
          
    function bird(){
        this.fly = true; 
    }
    
    
    bird.prototype = new animal();
    var a = new animal(); 
    var b = new bird();
    
    console.log(a.fly);
    console.log(a.eat);
    console.log(a.sleep);
    console.log(a.dead);
    console.log(b.fly);
    console.log(b.eat);
    console.log(b.sleep);
    console.log(b.dead);
    
    
    测试输出:
    [Web浏览器] "undefined"     
    [Web浏览器] "true"     
    [Web浏览器] "true" 
    [Web浏览器] "true"     
    [Web浏览器] "true" 
    [Web浏览器] "true"     
    [Web浏览器] "true"     
    [Web浏览器] "true" 

    下面我再画图分析一下这个

    ①下图是在bird.prototype = new animal();之前,创建好函数之后的状态

    ②继续执行程序

    从上图就可以明显看到

    实例对象b->bird.prototype->animal.prototype->Object.prototype->null有一个链式的继承关系

    也就是为什么

    console.log(b.eat);

    console.log(b.sleep);

    console.log(b.dead);

    会打印出来true的原因了。

     

  • 相关阅读:
    error: gnu/stubs32.h: 没有那个文件或目录
    vim配色方案
    Linux文件合并、去除重复
    Debian网络安装中的驱动问题
    汽油、柴油标号
    Debian SSH登录慢的解决办法
    Debian下的时间和时区问题
    解决vim、gvim在windows下中文乱码
    使用本地Debian ISO镜像作为网络安装源
    Debian如何永久添加静态路由
  • 原文地址:https://www.cnblogs.com/dcz2015/p/5391971.html
Copyright © 2011-2022 走看看