[[Prototype]]
在 JavaScript
中,所有的对象都有一个隐藏的 [[Prototype]]
属性,它要么是另一个对象,要么就是 null
proto
- 通过
[[Prototype]]
引用的对象被称为“原型”,用obj.__proto__
访问它let animal = { eats: true }; let rabbit = { jumps: true }; rabbit.__proto__ = animal; // 设置 rabbit.[[Prototype]] = animal // rabbit 能使用 animal 的所有属性和方法 console.log(rabbit.eats) // true
__proto__
的值可以是对象,也可以是 null。而其他的类型都会被忽略__proto__
与内部的[[Prototype]]
不一样。__proto__
是[[Prototype]]
的 getter/setter。__proto__
属性有点过时了,用函数Object.getPrototypeOf/Object.setPrototypeOf
来取代__proto__
去 get/set 原型
“this” 的值
无论在哪里找到方法:在一个对象还是在原型中。在一个方法调用中,this
始终是点符号 .
前面的对象。
// animal 有一些方法
let animal = {
walk() {
if (!this.isSleeping) {
alert(`I walk`);
}
},
sleep() {
this.isSleeping = true;
}
};
let rabbit = {
name: "White Rabbit",
__proto__: animal
};
// 修改 rabbit.isSleeping
rabbit.sleep();
alert(rabbit.isSleeping); // true
alert(animal.isSleeping); // undefined(原型中没有此属性)
for…in 循环
for..in
循环会迭代继承的属性,即会获得原型的属性Object.keys
只返回自己的key
obj.hasOwnProperty(key)
:如果obj
具有自己的(非继承的)名为key
的属性,则返回true
- 思考 任务
F.prototype
F.prototype
属性仅在 new F 被调用时使用,它为新对象的 [[Prototype]]
赋值
function F() {}
let f = new F
f.__proto__ == F.prototype // true
- 每个实例对象都会保持对旧的
prototype
的引用 - 每个函数都有
prototype
属性,默认的 "prototype" 是一个只有属性constructor
的对象,属性constructor
指向函数自身。F.prototype.constructor == F // true
- 通过实例对象的
constructor
来创建一个和它类似的对象let ff= new f.constructor() // ff 为 F 的实例对象
- 给
prototype
增加属性F.prototype.name = "ddd" // {name: "ddd", constructor: ƒ}
- 任务思考链接
原生的原型
Object.prototype
let obj = {}
obj.__proto__ === Object.prototype // true
let obj = {}
创建了一个对象,其相当于new Object()
,因此obj
的[[Protopype]]
会指向Object.prototype
其他内建原型
内建对象,像 Array、Date、Function 及其他,都在 prototype 上挂载了方法。所有的内建原型顶端都是 Object.prototype
。(更直观的图示)
- null:
Object.prototype.__proto__ === null
let arr = [1, 2, 3]; // 它继承自 Array.prototype? alert( arr.__proto__ === Array.prototype ); // true // 接下来继承自 Object.prototype? alert( arr.__proto__.__proto__ === Object.prototype ); // true // 原型链的顶端为 null。 alert( arr.__proto__.__proto__.__proto__ ); // null
基本数据类型
- 字符串、数字和布尔值上会被包装成对象,然后调用
String.prototype
、Number.prototype
和Boolean.prototype
中的方法。 null
和undefined
没有对象包装器
更改原生原型
String.prototype.show = function() {
alert(this);
}
"BOOM!".show(); // BOOM!
- 原型是全局的,所以很容易造成冲突
原型方法,没有 _proto_ 的对象
proto 被认为是过时且不推荐使用的,可以用新方法代替。现代的方法有:
Object.create(proto, [descriptors])
—— 利用给定的 proto 作为[[Prototype]]
和可选的属性描述来创建一个空对象。Object.getPrototypeOf(obj)
—— 返回对象 obj 的[[Prototype]]
。Object.setPrototypeOf(obj, proto)
—— 将对象 obj 的[[Prototype]]
设置为 proto。let animal = { eats: true }; // 创建一个以 animal 为原型的新对象 let rabbit = Object.create(animal, { jumps: { value: true } }); alert(rabbit.eats); // true alert(Object.getPrototypeOf(rabbit) === animal); // true Object.setPrototypeOf(rabbit, {}); // 将 rabbit 的原型修改为 {}
- 比复制 for..in 循环中的属性更强大的对象克隆方式:
let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj)); // 此调用可以对 obj 进行真正准确地拷贝,包括所有的属性
"Very plain" objects
obj.__proto__ = 11
该表达式能否正确运行??(详情)__proto__
是obj
的原型即Object.prototype
的访问器属性,因此每次赋值的时候只会调用原型中对应方法。- 如何使
__proto__
成为对象的属性?let o = Object.create(null) // 原型为 null,没有继承的 __proto_ 访问器属性 o.__proto__ = 111 // right
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!