美文网首页
深入理解Javascript中的Prototype原型

深入理解Javascript中的Prototype原型

作者: HalShaw | 来源:发表于2019-07-17 22:25 被阅读0次
    Prototype
    • 刚开始学Javascript的时候觉得很简单,其中的东西也就是那是基本的,但是还是太年轻,最近因为面试中常被问到关于原型和原型链的问题,然后自己也是模棱两可的,含含糊糊说不清楚,所以痛下思定,决定好好下一番功夫来搞懂吃透原型与原型链究竟是什么。

    关于new

    new的过程

    • 新生成了一个对象
    • 链接到原型
    • 绑定 this
    • 返回新对象
      知道了new的原理后,也可以自己实现一个new函数:
    function myNew() {
        // 创建一个空的对象
        let obj = new Object()
        // 获得构造函数
        let Con = [].shift.call(arguments)
        // 链接到原型
        obj.__proto__ = Con.prototype
        // 绑定 this,执行构造函数
        let result = Con.apply(obj, arguments)
        // 确保 new 出来的是个对象
        return typeof result === 'object' ? result : obj
    }
    

    先来看几个例子:

    • 普通函数
    function test(name){
        console.log(name);  
    }
    typeof(test) // function
    
    • 使用new新建对象
    function test(name){
        console.log(name);  
    }
    
    var te = new test("Hal");
    typeof(te) // object
    console.log(JSON.stringify(test.prototype)) //{},是个空对象
    console.log(JSON.stringify(te.prototype)) //undefined
    
    • 直接声明的函数拥有prototype这个属性,而new构造出来的函数不存在prototype

    关于prototype

    每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象 prototype,这个对象就是我们所说的prototype,每一个对象都会从prototype"继承"属性。除了new出来的函数,每个函数都有一个prototype属性,如下,在prototype上可以设置属性,然后打印出一些东西:

    function Employee() {}
    
    // prototype是函数才会有的属性
    Employee.prototype.name = 'Hal';
    var employee1 = new Employee();
    var employee2 = new Employee();
    console.log(employee1.name) // Hal
    console.log(employee2.name) // Hal
    console.log(employee1.constructor) // Employee() {}
    console.log(employee1.constructor.name) // Employee
    console.log(employee1.prototype) // undefined
    console.log(employee1.__proto__) // {name: "Hal", constructor: ƒ}
    console.log(Employee.prototype) // {name: "Hal", constructor: ƒ}
    console.log(Employee.prototype === employee1.__proto__) // true
    console.log(Employee.prototype.constructor === Employee) // true
    

    关于__proto__

    从刚才的例子中已经可以很清楚地看出了,employee1的__proto__和Employee.prototype是相等的,也就是指向同一个对象,也就是说,实例中有一个__proto__指针指向构造函数的prototype。使用Object.getPrototypeOf__proto__是同样的效果。

    Object.getPrototypeOf(employee1) === Employee.prototype //true
    

    关于constructor

    从上面可以看到,原型prototype里面还有一个constructor的属性,然后这个constructor又指向了函数本身。
    好像有一点绕,但是看一下下面的图就一目了然了:

    原型链

    总结

    • Object 是所有对象的祖先,所有对象都可以通过 __proto__ 找到它
    • Function 是所有函数的祖先,所有函数都可以通过 __proto__找到它
    • Function.prototypeObject.prototype 是两个特殊的对象,由引擎创建,而且Function.__proto__.__proto__是指向Object.prototype
      即:
      Function.__proto__.__proto__ === Object.prototype // true
    • 除了以上两个特殊对象,其他对象都是通过构造器 new 出来的
      函数的 prototype 是一个对象,也就是原型
    • 对象的 __proto__ 指向原型, __proto__ 将对象和原型连接起来组成了原型链

    参考

    相关文章

      网友评论

          本文标题:深入理解Javascript中的Prototype原型

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