js04 原型链

273 阅读2分钟

原型

原型,prototype,中文含义:模具,表示以此为起点,可以生成功能一致的产品。例如:武器设备的原型机;小说中的原型人物。

js中的原型指的是构造函数上的prototype属性。它是js中实现继承的基础。

js中的原型链是用来确认对象属性的查找机制。例如,当我们console.log(obj.p)时,如何在obj对象上找到a这个属性的值? 沿着原型链来找。

想要说明这个问题,先确定两个概念和一个关系

两个概念

  1. 原型

原型:构造器的prototype属性值

  1. 隐式原型 隐式原型: 对象的__proto__属性值

一个关系

原型与隐式原型的关系

先直接给出结论:

对象.__proto__ === 构造器.prototype

用语言来表述是:对象的隐式原型等于 创建这个对象的构造器的原型 (把这句话读出来,念3遍)

用公式表达就是:

如果: 对象 = new 构造器()

那么: 对象.__proto__ === 构造器.prototype

原型链

原型链是用来确认对象属性的查找机制。例如,当我们console.log(obj.p)时,如何在obj对象上找到a这个属性的值? 沿着原型链来找。

寻找属性p的步骤如下:

(1)先在自有属性中找,如果找到,则返回;如果找不到,则进入到它的隐式原型中去找。

(2)由于对象的隐式原型也是一个对象(对象又是属性的集合),所以继续在obj.__proto__的自有属性中去找。找到则返回,找不到,则继续。

(3)在obj.__proto__这个对象的隐式原型中继续找。找到返回,找不到,则继续到obj.__proto__.__proto__中去找。

(4)直到__proto__为null 停止,返回undefined

图片

上图中,红色的箭头标识的路径就是原型链。

原型链的应用

  1. vue2中,在Vue的原型上挂载eventBus,以便所有的组件实例都能访问
Vue.prototype.$eventBus = new Vue()
  1. es5中定义类时,将方法挂载在构造器的prototype上 打开,cdn.bootcdn.net/ajax/libs/v… , ctrl+f,prototype。就可以找到它们

image.png

  1. vue2中对数组元素响应式拦截

vue2中对数组元素响应式拦截时,就用到了Object.create(Array.prototype)的用法

  var arrayProto = Array.prototype;
  var arrayMethods = Object.create(arrayProto);

  var methodsToPatch = [
    'push',
    'pop',
    'shift',
    'unshift',
    'splice',
    'sort',
    'reverse'
  ];

  /**
   * Intercept mutating methods and emit events
   */
  methodsToPatch.forEach(function (method) {
    // cache original method
    var original = arrayProto[method];
    def(arrayMethods, method, function mutator () {
      var args = [], len = arguments.length;
      while ( len-- ) args[ len ] = arguments[ len ];

      var result = original.apply(this, args);
      var ob = this.__ob__;
      var inserted;
      switch (method) {
        case 'push':
        case 'unshift':
          inserted = args;
          break
        case 'splice':
          inserted = args.slice(2);
          break
      }
      if (inserted) { ob.observeArray(inserted); }
      // notify change
      ob.dep.notify();
      return result
    });
  });
  1. 判断数据类型时,使用Object的原型上的toString方法
Object.prototype.toString.call([])