# 什么是原型
在学习原型对象前,先属性一下两个 Object
的方法,因为后面的 demo
中会用到。
Object.setPrototypeOf()
和 Object.create()
.
// 它是将prototype作为已知对象obj的原型
// 方法设置一个指定的对象的原型 ( 即,内部 [[Prototype]] 属性)到另一个对象或 null。
Object.setPrototypeOf(obj, prototype);
// 它是创建一个以prototype为原型的对象
// 方法用于创建一个新对象,使用现有的对象来作为新创建对象的原型
Object.create(prototype);
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();
};
}
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);
那对象的这个 [[prototype]]
属性有什么作用,可以来一段代码理解一下
let myObj = {
name: "qile",
};
// 创建一个关联到myObj的对象
let anotherObj = Object.create(myObj);
console.log(anotherObj.name); // "qile"
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"
2
3
4
5
6
7
8
9
10
11
12
因此,当我们通过各种语法进行属性查找是都会查找 [[prototype]]
链,直到找到属性或者查找完整条原型链。
那这个时候其实我脑海中其实还是不明白啥事原型链,这个链有尽头吗?
答案是有,就是 Object.prototype
,所有普通的 [[prototype]]
链最终都会指向内置的 Object.prototype
。
而 Object.prototype
又会指向哪里?它通过 .__proto__
会指向 null
总结一下原型的作用:
- 对象关联