深切明白 JavaScript 原型继续

继续的实质:重用

在讨论 JavaScript 的原型继续之前,先无妨想一想为何要继续?

斟酌一个场景,假如我们有两个对象,它们一部分属性雷同,另一部属性差别。一般一个好的设计计划是将雷同逻辑抽出来,完成重用。

xiaoMing liLei 两位同砚举例。这两位同砚有本身的名字,并且会引见本身。笼统为顺序对象,能够做以下示意。

var xiaoMing = {
  name : "xiaoMing",
  hello : function(){
    console.log( 'Hello, my name is '+ this.name + '.');
  }
}

var liLei = {
  name : "liLei",
  hello : function(){
    console.log( 'Hello, my name is '+ this.name  + '.');
  }
}

运用过 java 的同砚,能够第一眼就想到了用面向对象来处理这个问题。制作一个 Person 的类,然后实例化 xiaoMingliLei 两个对象。在 ES6 中也有类似于 java 中类的观点:class

下面运用 ES6 的语法,用面向对象的思绪来重构上面的代码。

class Person {
  constructor(name){
    this.name = name
  }

  hello(){
    console.log(this.name);
  }
}

var xiaoMing = new Person('xiaoMing');
var liLei = new Person('liLei');

能够看到,运用类建立对象,到达了重用的目标。它基于的逻辑是,两个或多个对象的构造功用类似,能够笼统出一个模板,遵照模板复制出多个类似的对象。

运用类建立对象,就像自行车制作商一遍一各处重用雷同的蓝图来制作大批的自行车。

然处理重用问题标计划,固然不止一种。传统面向对象的类,只是个中的一种计划。下面轮到我们的主角“原型继续”上台了,它从另一个角度处理了重用的问题。

原型继续的道理

原型对象

JavaScript 中的 object 由两部分构成,一般属性的鸠合,和原型属性。

var o = {
  a : 'a',
  ...
  __proto__: prototypeObj
}

一般属性指的就是 a原型属性 指的是 __proto__。这本不属于范例的一部分,厥后 chrome 经由过程 __proto__ 将这个言语底层属性给暴露出来了,逐步的被人人所接收,也就添加到 ES6 范例中了。 o.__proto__ 的值 prototypeObj 也就是 原型对象 。原型对象实在也就是一个一般对象,之所以叫原型对象的缘由,只是由于它是原型属性所指的值。

原型对象所以特别,是由于它具有一个一般对象没有的才能:将它的属性同享给其他对象。

ES6 范例 中,对它是以下定义的:

object that provides shared properties for other objects

属性读操纵

回到最最先的例子,看看怎样应用原型继续完成重用的目标。

var prototypeObj = {
  hello: function(){
    console.log( 'Hello, my name is '+ this.name  + '.');
  }
  // ...
}

var xiaoMing = {
  name : "xiaoMing",
  __proto__ : prototypeObj
}

var liLei = {
  name : "liLei",
  __proto__ :  prototypeObj
}

xiaoMing.hello(); // Hello, my name is xiaoMing.
liLei.hello();  // Hello, my name is liLei.

xiaoMing liLei 对象上,并没直接具有 hello 属性(要领),然则却能读取该属性(实行该要领),这是为何?

设想一个场景,你在做数学功课,碰到一个很难的问题,你不会做。而你有一个好兄弟,数学很厉害,你去讨教他,把这道题做出来了。

xiaoMing 对象上,没有 hello 属性,然则它有一个好兄弟,prototypeObj。属性读操纵,在 xiaoMing 身上没有找到 hello 属性,就会去问它的兄弟 prototypeObj。所以 hello 要领会被实行。

原型链

照样做数学题的例子。你的数学问题很难,你的兄弟也没有答案,他引荐你去问别的一个同砚。如许直到有了答案或许再也没有人能够问,你就不会再问下去。如许就好像有一条无形链条把你和同砚们牵在了一同。

在 JS 中,读操纵经由过程 __proto__ 会一层一层链下去的构造,就叫 原型链

var deepPrototypeObj = {
  hello: function(){
    console.log( 'Hello, my name is '+ this.name  + '.');
  }
  __proto__ : null
}

var prototypeObj = {
  __proto__ : deepPrototypeObj
}

var xiaoMing = {
  name : "xiaoMing",
  __proto__ : prototypeObj
}

var liLei = {
  name : "liLei",
  __proto__ :  prototypeObj
}

xiaoMing.hello(); // Hello, my name is xiaoMing.
liLei.hello();  // Hello, my name is liLei.

原型继续的完成

在上面的例子中,经由过程直接修改了 __proto__ 属性值,完成了原型继续。然则在现实生产中,
用这类体式格局来转变和继续属性是对机能影响异常严峻的,所以并不引荐。

替代的体式格局是运用 Object.create() 要领。

挪用 Object.create() 要领会建立一个新对象,同时指定该对象的原型对象为传入的第一个参数。

我们将上面的例子改一下。

var prototypeObj = {
  hello: function(){
    console.log( 'Hello, my name is '+ this.name  + '.');
  }
  // ...
}

var xiaoMing = Object.create(prototypeObj);
var liLei = Object.create(prototypeObj);

xiaoMing.name = "xiaoMing";
liLei.name = "liLei";

xiaoMing.hello(); // Hello, my name is xiaoMing.
liLei.hello();  // Hello, my name is liLei.

You-Dont-Know-JS 的作者,对这类原型继续的完成取了一个很好玩的名字 OLOO (objects-linked-to-other-objects) ,这类完成体式格局的长处是没有运用任何类的观点,只要 object,所以它是很相符 javaScript 的特征的。

由于JS 中本无类,只要 object

无法的是,喜好类的顺序员是在太多,所以在 ES6 新增了 class 观点。下一篇会讲 class 在 JS 中的完成道理

小结

经由过程类来建立对象,使得开发者没必要写反复的代码,以到达代码重用的目标。它基于的逻辑是,两个或多个对象的构造功用类似,能够笼统出一个模板,遵照模板复制出多个类似的对象。就像自行车制作商一遍一各处重用雷同的蓝图来制作大批的自行车。

运用原型继续,一样能够到达重用的目标。它基于的逻辑是,两个或多个对象的对象有一部分共用属性,能够将共用的属性笼统到另一个自力大众对象上,经由过程特别的原型属性,将大众对象和一般对象链接起来,再应用属性读(写)划定规矩举行遍历查找,完成属性同享

参考文章

    原文作者:穿越过来的键盘手
    原文地址: https://segmentfault.com/a/1190000008293372
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞