我最近在与客户合作的项目中,需要充分利用的 ECMAScript 5,在此我遇到一个非常有趣的问题。 该问题源于一个非常常见的模式: mixin , 也就是在 JavaScript 中把一个对象的属性或者方法 mixin 到另一个。
大多数 mixin 的功能看起来像这样:
复制代码 代码如下:
function mixin(receiver, supplier) {
for (var property in supplier) {
if (supplier.hasOwnProperty(property)) {
receiver[property] = supplier[property];
}
}
}
在此 mixin() 函数中,一个 for 循环遍历 supplier 对象的属性并赋值给 receiver 对象。 几乎所有的 JavaScript 库有某种形式的类似功能,让您可以编写这样的代码:
复制代码 代码如下:
mixin(object, {
name: "Nicholas",
sayName: function() {
console.log(this.name);
}
});
object.sayName(); // outputs "Nicholas"
在此示例中,object 对象接收了属性 name 和方法 sayName()。 这在 ECMAScript 3 中运行良好,但在 ECMAScript 5 上却没那么乐观。
这是我遇到的问题:
复制代码 代码如下:
(function() {
// to be filled in later
var name;
mixin(object, {
get name() {
return name;
}
});
// let's just say this is later
name = "Nicholas";
}());
console.log(object.name); // undefined
这个例子看起来有点做作,但它准确的描述这个问题。 进行 mixin 的属性使用了 ECMAScript 5 的新特性:一个 getter 属性存取器。 getter 引用一个未初始化的局部变量 name,因此这个属性未定义 undefined。
后来,name 被分配了一个值,以便使存取器 getter 可以返回一个有效的值。 不幸的是,object.name(被 mixin 的属性)始终返回 undefined。
这是怎么回事呢?
我们仔细分析 mixin() 函数。 事实上,在循环语句中,并没有把属性从一个对象重新赋值给到另一个对象。 它实际上是创建一个同名的属性,并把 supplier 对象的存取器方法 getter 的返回值赋值给了它。 (译注:目标对象得到的不是 getter 这个方法,而是得到了 getter 方法的返回值。@justjavac)
在这个例子中,mixin() 的过程其实是这样的:
复制代码 代码如下:
receiver.name = supplier.name;
属性 receiver.name 被创建,并且被赋值为 supplier.name 的值。 当然,supplier.name 有一个 getter 方法用来返回本地变量 name 的值。 此时,name 的值为 undefined,所以 receiver.name 存储的是 值。 并没有为 receiver.name 创建一个 getter 方法,因此它的值永远不会改变。
要解决这个问题,你需要使用属性描述符(译注:descriptor)将属性从一个对象 mixin 到另一个对象。 一个纯粹的 ECMAScript 5 版本的 mixin() 应该这样写:
复制代码 代码如下:
function mixin(receiver, supplier) {
Object.keys(supplier).forEach(function(value, property) {
Object.defineProperty(receiver, property, Object.getOwnPropertyDescriptor(supplier, property));
});
}
在这个新版本函数中,Object.keys() 用来获取一个数组,包含了 supplier 对象的所有枚举属性。 然后,foreach() 方法用来遍历这些属性。 调用 Object.getOwnPropertyDescriptor() 方法获取 supplier 对象的每个属性描述符(descriptor)。
由于描述符(descriptor)包含了所有的属性信息,包括 getter 和 setter 方法, 该描述符(descriptor)可以直接传递给 Object.defineProperty() ,用来在 receiver 对象上创建相同的属性。 使用这个新版本的 mixin() ,可以解决前面遇到的问题,从而得到你所期望的结果。 getter 方法被正确地从 supplier 传递到了 receiver。
当然,如果你仍然需要支持旧的浏览器,那么你就需要一个函数,回落的 ECMAScript 3:
复制代码 代码如下:
function mixin(receiver, supplier) {
if (Object.keys) {
Object.keys(supplier).forEach(function(value, property) {
Object.defineProperty(receiver, property, Object.getOwnPropertyDescriptor(supplier, property));
});
} else {
for (var property in supplier) {
if (supplier.hasOwnProperty(property)) {
receiver[property] = supplier[property];
}
}
}
}
如果您需要使用一个 mixin() 函数,一定要仔细检查它在 ECMAScript 5 可以正常工作,特别是 getter 和 setter 方法。 否则,你会发现自己陷入像我一样的错误。
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。
更新动态
- 刘德华《劲歌集》24K金碟港版[WAV+CUE][1.2G]
- Faker五冠王什么意思 世界赛五冠王Faker选手介绍
- faker塞拉斯s14决赛什么出装 faker塞拉斯s14决赛出装介绍
- LOLtoc9魔法口令在哪可以找到 2024云顶之弈toc观赛魔法口令兑换码
- 黑鸭子2008《影视经典·珍藏版》试音碟[WAV+CUE]
- 碧娜《温柔吻语2》[WAV+CUE]
- Stravinsky-Symphonies,Volume1-OrquestaSinfonicadeGalicia,DimaSlobodeniouk(2024)[24-
- 外媒评Switch2:向下兼容是关键 但挑战依然存在
- 任天堂提醒:宠物的尿或唾液或会让NS故障 把它放好!
- 《博德3》再创新高 Steam掌机总游玩时长近2000年
- 张玮伽《想你的夜DSD》东升 [WAV+CUE][1G]
- 姚璎格《 粤 24KGOLD》正版低速原抓[WAV+CUE][1G]
- 杨千嬅《如果大家都拥有海》寰亚 [WAV+CUE][998M]
- 孟庭苇.1994-1990-1994钻石精选集2CD(2022环球XRCD限量版)【上华】【WAV+CUE】
- 群星.1998-华纳好情歌精选17首【华纳】【WAV+CUE】