zoukankan      html  css  js  c++  java
  • JS的prototype和__proto__(含es6的class)

    JS的prototype和__proto__(含es6的class)

    一、prototype和__proto__的概念

    prototype是函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象。它是显示修改对象的原型的属性。
    __proto__是一个对象拥有的内置属性(请注意:prototype是函数的内置属性,__proto__是对象的内置属性),是JS内部使用寻找原型链的属性。

    用chrome和FF都可以访问到对象的__proto__属性,IE不可以。

    二、new 的过程

    var Person = function(){};
    var p = new Person();
    

    new的过程拆分成以下三步:

    (1) var p={}; 也就是说,初始化一个对象p
    (2) p.__proto__ = Person.prototype;
    (3) Person.call(p); 也就是说构造p,也可以称之为初始化p
    

    关键在于第二步,我们来证明一下:

    var Person = function(){};
    var p = new Person();
    alert(p.__proto__ === Person.prototype);
    

    这段代码会返回true。说明我们步骤2是正确的。

    三、示例

        var Person = function(){};
        Person.prototype.sayName = function() {
            alert("My Name is Jacky");
        };
        Person.prototype.age = 27;
        var p = new Person();
        p.sayName();
    

    p是一个引用指向Person的对象。我们在Person的原型上定义了一个sayName方法和age属性,当我们执行p.age时,会先在this的内部查找(也就是构造函数内部),如果没有找到然后再沿着原型链向上追溯。这里的向上追溯是怎么向上的呢?这里就要使用__proto__属性来链接到原型(也就是Person.prototype)进行查找。最终在原型上找到了age属性。

    个人联系笔记(纯粹个人好理解的写法)
    console.log('测试')
    class css {
      constructor(dd) {  this.dd = '33333333333';  }
      rr() {   return 'rr'  }
    }
    class aa extends css {
      constructor() {
        super() //extends的类里使用constructor必须要有super
        this.b = this.b.bind(this);
        this.dd = '2222222222222'  }
      b() {    return 'ceshi'  }
      c() {  return this.dd }//dd被修改   // return this  b:function ()   dd:"2222222222222"
    }
    const bb = new aa()
    // 上一个自身(constructor):__proto__ ; 自己:prototype 口诀:aa.__proto__.prototype
    // aa的上一个自身的自己===上一个的自己
    // ★★★★ 类里的__proto__找的是父级的constructor,类里的__proto__.prototype找的是父级的自己(父级.prototype)
    // ★★★★ 实例对象的__proto__找的是父级的自己,即父级.prototype
    console.log('-----------------------------------------') //
    console.log('aa', aa) //
    console.log('css', css) //
    console.log('css.prototype', css.prototype) // 指向自身
    console.log('css.prototype.__proto__', css.prototype.__proto__) // 指向自身
    console.log('css.__proto__', css.__proto__) //function () { [native code] }
    console.log('css.__proto__.__proto__', css.__proto__.__proto__) //
    console.log('aa.__proto__', aa.__proto__) //  指向css的constructor aa.__proto__===css
    console.log('aa.prototype', aa.prototype) //  指向自身
    console.log('aa.__proto__.prototype', aa.__proto__.prototype) // 指向css的自身  aa.__proto__.prototype===css.prototype===aa.prototype.__proto__
    console.log('aa.prototype.__proto__', aa.prototype.__proto__) // 同上
    console.log('-----------------------------------------') //
    console.log('bb', bb) // 指向aa的constructor, bb即aa的实例对象
    console.log('bb.__proto__', bb.__proto__) //  指向父级自身即aa.prototype  bb.__proto__===aa.prototype
    console.log('bb.prototype', bb.prototype) //  undefined
    console.log('bb.__proto__.__proto__', bb.__proto__.__proto__) // 指向css自己 bb.__proto__.__proto__css.prototype 
    console.log('bb.__proto__.__proto__.__proto__', bb.__proto__.__proto__.__proto__) // bb.__proto__.prototype===aa.__proto__.prototype===css.prototype===aa.prototype.__proto__
    console.log('bb.__proto__.__proto__.__proto__.__proto__', bb.__proto__.__proto__.__proto__.__proto__) // null
    console.log('bb.__proto__.prototype', bb.__proto__.prototype) // undefined, 已经是自身了
    // console.log('bb.prototype.__proto__',bb.prototype.__proto__) //  err
    console.log('-----------------------------------------') //
    // const aaa = () => '1234567'
    // console.log(aaa()) (()=>{a}) // 等价于 (function () {   a; }); ()=>(a) // 等价于
    // (function () {   return a; });
    console.log('********************************')
    var Person = function(){ return 222;};
    Person.prototype.sayName = function() {   return 'cs'};
    Person.prototype.age = 27;
    var p = new Person();
    p.__proto__.cs = 'cs'; //在Person.prototype里添加了cs='cs'
    console.log('Person',Person)  //Person function (){return 222}
    console.log('Person.prototype',Person.prototype) //person自己
    console.log('Person.prototype.__proto__',Person.prototype.__proto__)  //Person.prototype.__proto__===Person.__proto__.__proto__===p.__proto__.__proto__
    console.log('Person.__proto__',Person.__proto__) //function () { [native code] }
    console.log('Person.__proto__.__proto__',Person.__proto__.__proto__)
    console.log('p',p) // {}
    console.log('p.prototype',p.prototype) //undefined
    console.log('p.__proto__',p.__proto__)  //p.__proto__===Person.prototype
    console.log('p.__proto__.__proto__',p.__proto__.__proto__)  //p.__proto__.__proto__ ==Person.__proto__.__proto__===Person.prototype.__proto__
    console.log('********************************')
    
    测试结果:

    春雷原创:http://www.cnblogs.com/chunlei36

  • 相关阅读:
    Oracle Core 学习笔记二 Transactions 和 Consistency 说明
    Oracle AUTO_SPACE_ADVISOR_JOB 说明
    Windows 下 ftp 上传文件 脚本
    Oracle 11g 中 Direct path reads 特性 说明
    Linux 使用 wget 下载 Oracle 软件说明
    Oracle 10g read by other session 等待 说明
    Oracle 11g RAC INS06006 Passwordless SSH connectivity not set up between the following node(s) 解决方法
    SecureCRT 工具 上传下载数据 与 ASCII、Xmodem、Ymodem 、Zmodem 说明
    Oracle RAC root.sh 报错 Timed out waiting for the CRS stack to start 解决方法
    Oracle RESETLOGS 和 NORESETLOGS 区别说明
  • 原文地址:https://www.cnblogs.com/chunlei36/p/6641021.html
Copyright © 2011-2022 走看看