JavaScript 原型与继承机制详解(3)

1 function foo () { 2 this.x = 1; 3 this.y = 2; 4 } 5 6 foo.prototype.z = 3 7 8 var obj1 = new foo(); 9 10 console.log(obj1.__proto__); //{z:3}

  除了使用 new 操作符和函数的 [[prototype]] 属性定义对象的原型之外,我们还可以直接在对象上显示的通过 __proto__  来定义,这种定义对象原型的方式更能够体现出 JavaScript 语言的本质,更能够使初学者理解原型链继承的机制。

1 var father = {x:1};
2
3 var child = {
4    y:2,
5     __proto__:father
6 };
7
8 console.log(child.x);  //1

  现在我们来完成之前那个自定义 new 操作(如果你还不能理解这个函数,没有关系,跳过它,这并不影响你接下来的学习):

1 function newOpertor (cls, ...args) { 2 var obj = Object.create(cls.prototype); 3 cls.apply(obj, args); 4 return obj; 5 } 6 7 function foo (x, y) { 8 this.x = x; 9 this.y = y; 10 } 11 12 foo.prototype.z = 3 13 14 var obj1 = newOpertor(foo, 1, 2) 15 16 console.log(obj1.z); //3

 三、原型链

  介绍完原型之后,同学们需要明确以下几个概念:

  JavaScript 采用原型的机制实现继承;

  原型是一个具有实际空间的对象,所有关联的子对象共享一个原型;

  那么 JavaScript 当中的原型是如何实现相互关联的呢?JS 引擎又是如何查找这些关联的属性呢?如何实现多个对象的关联形成一条原型链呢?

1 var obj1 = {
2    x:1
3 }
4
5 var obj2 = {
6    y:2,
7     __proto__:obj1
8 }
9
10 var obj3 = {
11    z:3,
12     __proto__:obj2
13 }
14
15 console.log(obj3.y);  //2
16 console.log(obj3.x);  //1

  在上面这段代码,我们可以看出,对象的原型可以实现多层级的关联的操作,obj1 是 obj2 的原型, obj2 同时又是 obj3 的原型,这种多层级的原型关联,就是我们常说的原型链。在访问一个处于原型链当中的对象的属性,会沿着原型链对象一直向上查找,我们可以把这种原型遍历操作看成是一个单向的链表,每一个处于原型链的对象都是链表当中的一个节点,JS 引擎会沿着这条链表一层一层的向下查找属性,如果找到了一个与之匹配的属性名,则返回该属性的值,如果在原型链的末端(也就是 Object.prototype)都没有找到与之匹配的属性,则返回 undefined。要注意这种查找方式只会返回第一个与之匹配的属性,所以会发生属性屏蔽:

1 var obj1 = {
2    x:1
3 }
4
5 var obj2 = {
6    x:2,
7     __proto__:obj1
8 }
9
10 var obj3 = {
11    x:3,
12     __proto__:obj2
13 }
14
15 console.log(obj3.x);  //3

  若要访问原型的属性,则需要一层的一层的先向上访问原型对象:

1 console.log(obj3.__proto__.x); //2 2 console.log(obj3.__proto__.__proto__.x); //1

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/9fffa9f22ed89d78b1b09dc5ec45d6c5.html