美文网首页
JavaScript.prototype 和 继承 - 01

JavaScript.prototype 和 继承 - 01

作者: 人话博客 | 来源:发表于2019-02-27 19:57 被阅读0次

    我为什么要把 javascript.prototype 原型单独拿出一系列博客来写?

    因为平时写js代码的时候很少用到!!!!

    我为什么平时写js代码的时候很少用到?

    因为平时我写js代码,特别是对象的时候.不出意外,99.99999%的情况都是使用字面量的写法!!!!

    var obj = {
        .....
    }
    

    一个简单的场景

    我们使用字面量(99.9999%的情况都是如此)声明一个对象.

    var obj = {
        name: '李四',
        age: 22
    }
    

    然后调用

    obj.showInfo()
    

    不出意外,肯定报错.且报错信息是 obj.showInfo is not function..

    image.png

    到目前为止,从来都没有人怀疑过.

    这里就应该报错.因为你没有定义这个方法.

    那如果我调用obj.toString()方法呢?

    [object Object]
    

    我没有定义 toString 方法,为什么不报错,还正确执行了呢?

    这个 toString 的方法是哪里来的?


    Object.prototype

    在解释 toString 方法哪里来的之前

    有一个规则需要知道: (什么是规则?规则就是你可以先不去理解,但是必须强行记忆和知道的知识)

    在js中函数也是对象,所有的函数对象上会有一个 .prototype 的属性.

    Object 也是一个函数,所以,它也有 .prototype 属性.===> Object.prototype

    打印一下 Object.prototype 这个对象上有哪些属性?
    (请注意,在浏览器环境中打印,在Node.js环境中打印将会返回一个空对象)

    image.png

    所以,我们可以先暂时假定: obj.toString 方法是来自 Object.prototype 对象上的.

    代码改造

    之前我们的代码是

    var obj = {
        name: '李四',
        age: 22
    }
    
    console.log(obj.toString())
    
    [object Object]
    

    之前也说过,一般在书写js代码创建一个对象时.

    不夸张的说 99.9999999% 的情况都是写的对象字面量(就像上述那样)

    但实际上,这段代码也可以改写成这样.

    var obj = new Object()
    obj.name = '李四'
    obj.age = 22
    

    我们可以理解成,对象字面量其实是一个语法糖.
    它帮我们隐式的调用了 new Object().

    所以,在我们写js代码利用对象字面量创建对象的时候,new Object() 其实无处不在(因为99.9999%的情况下,我们都是使用对象字面量来创建对象.反而忽略了new的存在.).


    new Object()

    现在我们知道了,使用对象字面量创建对象只是一个语法糖.
    其内部帮我们调用了 new Object().

    如果要了解为什么 obj.toString() 没问题.

    还需要知道一个前置规则(第一个是:所有的函数都包含一个.prototype属性)

    所有构造的对象(隐式或显式(用new).都会从它的构造函数对象的prototype对象继承.

    于是,可以画一下面这张图.

    image.png
    • Object 是一个函数,它有一个属性叫 .prototype.
    • .prototype 属性本身也是一个对象,它也右边那些属性和方法.
    • obj 实际上是 Object 函数构造出出来的实例.所以,根据第二条规则,通过 new Object() 创建出来的对象,都会从 Object.prototype 对象上继承属性和方法.
    • 所以,我们调用 obj.toString 实际上是调用的 Object.protoype.toString 方法.

    证明obj.toString === Object.prototype.toString

    我们先尝试修改一下 Object.prototype.toString 让它专门为 obj 对象来使用.

    Object.prototype.toString = function () {
      console.log(this.name, this.age)
    }
    
    obj.toString()
    
    李四 22
    

    关于 prototype 对象属性的COW(copy on write)

    现在在创建一个对象字面量,但内部没有 nameage 属性.

    const obj2 = {}
    

    根据上述的规则一 & 规则二.所以下列这条等式是成立的.

    console.log(obj2.toString === Object.prototype.toString) // true.
    

    如果我现利用 obj2 修改了 toString 函数,会对 obj 产生影响吗?

    obj2.toString = function() {
        console.log('toString函数被我重写了.')
    }
    
    obj.toString()
    

    结果

    李四 22
    

    除非修改 prototype 对象本身,否则继承自这个 prototype 对象的对象,做的任何修改只会影响此对象自己.
    而不会影响到其他的对象.
    这个就叫做原型对象的 COW ==copy on write 写时复刻==

    相关文章

      网友评论

          本文标题:JavaScript.prototype 和 继承 - 01

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