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

  • 相关阅读:
    微信小程序倒计时,小程序60秒倒计时,小程序倒计时防止重复点击
    微信小程序嵌套h5页面,h5页面返回小程序,小程序和h5的页面和交互方法,h5点击分享小程序页面
    LeetCode—— 括号生成
    LeetCode—— 合并两个有序链表
    LeetCode—— 有效的括号
    LeetCode—— 删除链表的倒数第N个节点
    LeetCode—— 四数之和
    LeetCode—— 电话号码的字母组合
    LeetCode—— 最接近的三数之和
    ***LeetCode—— 三数之和
  • 原文地址:https://www.cnblogs.com/chunlei36/p/6641021.html
Copyright © 2011-2022 走看看