原型对象和原型链

2019/8/10 javascript你不知道的 javascript

# 什么是原型

在学习原型对象前,先属性一下两个 Object 的方法,因为后面的 demo 中会用到。

Object.setPrototypeOf()Object.create().

// 它是将prototype作为已知对象obj的原型
// 方法设置一个指定的对象的原型 ( 即,内部 [[Prototype]] 属性)到另一个对象或 null。
Object.setPrototypeOf(obj, prototype);

// 它是创建一个以prototype为原型的对象
// 方法用于创建一个新对象,使用现有的对象来作为新创建对象的原型
Object.create(prototype);
1
2
3
4
5
6
7
// Object.setPrototypeOf()的polyfill

if (!Object.setPrototypeOf) {
  // 仅适用于 Chrome 和 FireFox,在 IE 中不工作:
  Object.prototype.setPrototypeOf = function (obj, proto) {
    if (obj.__proto__) {
      obj.__proto__ = proto;
      return obj;
    } else {
      // 如果你想返回 prototype of Object.create(null):
      var Fn = function () {
        for (var key in obj) {
          Object.defineProperty(this, key, {
            value: obj[key],
          });
        }
      };
      Fn.prototype = proto;
      return new Fn();
    }
  };
}

// Object.create()的polyfill

if (!Object.create) {
  Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
  };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

JavaScript 中的对象有一个特殊的 [[prototype]] 属性,其实就是对于其他对象的应用。几乎所有的对象在创建时 [[prototype]] 属性

都会被赋予一个非空值。

注意对象的 [[prototype]] 可以为空,但很少见

const emptyObj = Object.create(null);
1

tu

那对象的这个 [[prototype]] 属性有什么作用,可以来一段代码理解一下

let myObj = {
  name: "qile",
};

// 创建一个关联到myObj的对象
let anotherObj = Object.create(myObj);

console.log(anotherObj.name); // "qile"
1
2
3
4
5
6
7
8

从上面可以看到我们用 Object.create() 我们将 myObj 的原型对象来作为 anotherObj 对象的原型

所以当 anotherObj.name 时能打印出值,其实是当我们视图引用一个对象的属性时会触发 [[Get]] 操作,对于

默认的 [[Get]] 操作来说,第一步是检查对象本身是否有这个属性,如果有就直接使用它,没有的话就会继续访问对象的 [[prototype]] 链。

这个过程就是 anotherObj.name 时自己是没有 name 属性的时并且 [[prototype]] 不为空的话,就会继续查找下去并且是查找整条原型链

如果还是没有找到就会返回 undefined

再举一个例子:使用 for...in 遍历对象时原理和查找原型链类似,任何可以通过原型链访问到(并且是 enumerable)的属性都会被枚举。使用 in

操作符来检查属性对象中是否存在时,同样会查找对象的整条原型链(无论属性是否可枚举):

let myObj = {
  name: "qile",
};

// 创建一个关联到myObj的对象
let anotherObj = Object.create(myObj);

for (const key in anotherObj) {
  console.log("found: " + k);
}

// "found: name"
1
2
3
4
5
6
7
8
9
10
11
12

因此,当我们通过各种语法进行属性查找是都会查找 [[prototype]]链,直到找到属性或者查找完整条原型链。

那这个时候其实我脑海中其实还是不明白啥事原型链,这个链有尽头吗?

答案是有,就是 Object.prototype,所有普通的 [[prototype]] 链最终都会指向内置的 Object.prototype

Object.prototype 又会指向哪里?它通过 .__proto__会指向 null

tu

总结一下原型的作用:

  1. 对象关联
Last Updated: 2022/8/28 下午3:19:34