V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
xiaomuchen
V2EX  ›  JavaScript

__proto__ 和 prototype 会出现在什么地方?它们之间是什么关系?

  •  
  •   xiaomuchen · 2017-11-05 13:40:42 +08:00 · 2150 次点击
    这是一个创建于 2579 天前的主题,其中的信息可能已经有所发展或是发生改变。
    __proto__ 和 prototype 的区别

    1.JavaScript 中每一个对象都拥有原型链(__proto__)指向其构造函数的原型( prototype )

    var a = {}
    a.__proto__ === Object.prototype // true
    
    function Person () {}
    Person.__proto__ === Function.prototype // true
    
    var p = new Person()
    p.__proto__ === Person.prototype // true
    

    2.JavaScript 中每一个函数都拥有原型( prototype ),原型也是一个对象,这个对象包括:原型链、原型方法(属性)、函数构造,同理它的原型链指向其构造函数的原型

    function Person () {}
    Person.prototype.getName = function () {}
    Object.getOwnPropertyNames(Person.prototype) // ["constructor", "getName"]
    Person.prototype.__proto__ === Object.prototype // true
    

    3.当访问一个函数上的属性时,先尝试访问自身上的属性,再尝试访问其原型上的属性。当访问一个对象上的属性时,先尝试访问自身上的属性,再通过原型链尝试访问其构造函数原型上的属性。如果没有则通过原型上的原型链,继续向上查找,直到访问 Object.prototype 上的属性,如果还是没有,因为 Object.prototype 是一个没有 __proto__ 的对象,则查询到此为止,返回 undefined。

    function Person () {}
    Person.getName = function () {
      console.log('Person1')
    }
    Person.prototype.getName = function () {
      console.log('Person2')
    }
    var p = new Person()
    
    Person.getName() // Person1
    p.getName() // Person2
    console.log(typeof p.getClass) // undefined
    
    继承

    JavaScript 函数通过原型和原型链实现继承

    function superA (name) {
      this.name = name
    }
    superA.prototype.getName = function () {
      console.log(this.name)
    }
    function subA (name) {
      superA.call(this, name) // 继承属性
    }
    subA.prototype = new superA() // 继承方法
    
    var a1 = new subA('xiaomuchen')
    a1.getName() // xiaomuchen
    

    上述代码,描述了一个函数的经典继承,其工作原理是这样的:

    1. 声明父类 superA、子类 subA
    2. 重写子类 subA 的原型,指向 superA 的实例
    3. 当实例化 a1 时,a1.__proto__ => subA.prototype => new superA() => superA.prototype,所以 a1 的构造函数是 superA
    4. 同时,运行 subA 也就是 superA.call(this, 'xiaomuchen'),其中 this 指向 a1 所以 a1 继承了 name 属性
    5. 这样子类 subA 的实例 a1 就继承了 superA 的原型方法和属性

    原文

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1829 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 16:29 · PVG 00:29 · LAX 08:29 · JFK 11:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.