美文网首页
重新理解js原型集成的要点

重新理解js原型集成的要点

作者: sorry510 | 来源:发表于2019-10-30 17:35 被阅读0次
    1. 每个实例对象( object )都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象( __proto__ ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节
    function doSomething(){}
    doSomething.prototype.foo = "bar"; // add a property onto the prototype
    var doSomeInstancing = new doSomething();
    doSomeInstancing.prop = "some value"; // add a property onto the object
    console.log( doSomeInstancing );
    

    你会发现doSomeInstancing 中的__proto__是 doSomething.prototype,但这是做什么的呢?当你访问doSomeInstancing 中的一个属性,浏览器首先会查看doSomeInstancing 中是否存在这个属性。

    如果 doSomeInstancing 不包含属性信息, 那么浏览器会在 doSomeInstancing 的 proto 中进行查找(同 doSomething.prototype). 如属性在 doSomeInstancing 的 __proto__ 中查找到,则使用 doSomeInstancing 中 __proto__ 的属性。

    否则,如果 doSomeInstancing 中 __proto__ 不具有该属性,则检查doSomeInstancing 的 __proto__ 的 __proto__ 是否具有该属性。默认情况下,任何函数的原型属性 __proto__ 都是 window.Object.prototype. 因此, 通过doSomeInstancing 的__proto__ 的 __proto__ ( 同 doSomething.prototype 的 __proto__ (同 Object.prototype)) 来查找要搜索的属性。

    如果属性不存在 doSomeInstancing 的 __proto__ 的 __proto__ 中, 那么就会在doSomeInstancing 的 __proto__ 的 __proto__ 的 __proto__ 中查找。然而, 这里存在个问题:doSomeInstancing 的 __proto__ 的 __proto__ 的 __proto__ 其实不存在。因此,只有这样,在 __proto__ 的整个原型链被查看之后,这里没有更多的 __proto__ , 浏览器断言该属性不存在,并给出属性值为 undefined 的结论。

    1. 不同对象继承的是什么
    var o = {a: 1};
    
    // o 这个对象继承了 Object.prototype 上面的所有属性
    // o 自身没有名为 hasOwnProperty 的属性
    // hasOwnProperty 是 Object.prototype 的属性
    // 因此 o 继承了 Object.prototype 的 hasOwnProperty
    // Object.prototype 的原型为 null
    // 原型链如下:
    // o ---> Object.prototype ---> null
    
    var a = ["yo", "whadup", "?"];
    
    // 数组都继承于 Array.prototype 
    // (Array.prototype 中包含 indexOf, forEach 等方法)
    // 原型链如下:
    // a ---> Array.prototype ---> Object.prototype ---> null
    
    function f(){
      return 2;
    }
    
    // 函数都继承于 Function.prototype
    // (Function.prototype 中包含 call, bind等方法)
    // 原型链如下:
    // f ---> Function.prototype ---> Object.prototype ---> null
    
    1. 不要在 f 函数的原型上直接定义 f.prototype = {b:3,c:4};这样会直接打破原型链
    function f(){}
    f.prototype.b = 3
    f.prototype.c = 3
    // f.prototype = {b:3,c:4};
    
    1. 要检查对象是否具有自己定义的属性,而不是其原型链上的某个属性,则必须使用所有对象从 Object.prototype 继承的 Object/hasOwnProperty 方法

    hasOwnProperty是 JavaScript 中唯一一个处理属性并且不会遍历原型链的方法
    tips: Object.keys()遍历时也不会遍历原型链

    1. prototype和实例的对象共享数据
      function A 有一个叫做 prototype 的特殊属性。该特殊属性可与 JavaScript 的 new 操作符一起使用。对原型对象的引用被复制到新实例的内部 [[Prototype]] 属性。例如,当执行 var a1 = new A(); 时,JavaScript(在内存中创建对象之后,和在运行函数 A() 把 this 指向对象之前)设置 a1.[[Prototype]] = A.prototype;。然后当您访问实例的属性时,JavaScript 首先会检查它们是否直接存在于该对象上,如果不存在,则会 [[Prototype]] 中查找。 这意味着你在 prototype 中定义的所有内容都可以由所有实例有效地共享,你甚至可以稍后更改部分 prototype,并在所有现有实例中显示更改(如果有必要的话)

    因此,当你执行:

    var o = new Foo();
    

    JavaScript 实际上执行的是:

    var o = new Object();
    o.__proto__ = Foo.prototype;
    Foo.call(o);
    

    相关文章

      网友评论

          本文标题:重新理解js原型集成的要点

          本文链接:https://www.haomeiwen.com/subject/ubqavctx.html