原文:Are your mixins ECMAScript 5 compatible?
作者:Nicholas C. Zakas
译文:你的 mixin 兼容 ECMAScript 5 吗?
译者:justjavac
好久没更新博客了,今天在 nczonline 看到了这篇博客,于是第一时间把它翻译了过来。英语水平有限,大家忍者点看,以下是正文:
我最近在与客户合作的项目中,需要充分利用的 ECMAScript 5,在此我遇到一个非常有趣的问题。 该问题源于一个非常常见的模式: mixin (译注:很多文章翻译成「混入」,我觉得还是保留原文吧。如今 mixin 的流程程度不亚于 Closure,什么!你不知道?拜托,如果你是从火星来的,请自觉 Google 吧。@justjavac), 也就是在 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 方法。 否则,你会发现自己陷入像我一样的错误。
分享到:
相关推荐
本篇文章主要讲述了,在JavaScript 中把一个对象的属性或者方法 mixin 到另一个
你想保留你的mixin吗? 你想念自动绑定this给你的方法? 这对你来说是完美的! react-compat-component允许您在不更改太多代码的情况下为组件使用新的 ES6 类结构。 并且它允许您继续使用 mixin 而无需任何特殊...
ruby-destroyed_at, 用于安全销毁的ActiveRecord Mixin DestroyedAt 查找帮助?如果是一个 Bug ,请在GitHub上打开一个问题。安装将 destroyed_at gem 添加到 Gemfilegem 'destroyed_at'你可以在每个模块中
MIXIN是使用ASM的Java的特性/混合框架
mixin是一个闪电交易快速的点点对的数字交道项目,它拥有非常好的技术栈。
A Swift mixin for UITableViewCells and UICollectionViewCells.zip,A Swift mixin for reusing views easily and in a type-safe way (UITableViewCells, UICollectionViewCells, custom UIViews, ViewControllers...
y-mixin 是来自阅文前端团队的 CSS 预处理器 mixin 库
小程序 mixin 混入, Page 选项合并
modernizr-mixin, 在Sass中,针对测试的简单而全面的mixin hardwarebutton混合 一种简单的DRYier测试方法,在Sass中更快更。安装要求 ruby 3.4或者 LibSass 3.2Libsass警告:在 Libsass 3.2.3中有一个已知 Bug,它...
资源分类:Python库 所属语言:Python 资源全名:colcon_mixin-0.1.3-py3-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
React观察者混合 具有ES5和ES6兼容语义的 Mixin提供了尊重组件生命周期的托管事件侦听器,以及与React不变式兼容并适用于一次性事件处理程序的状态设置器。 该模块没有运行时相关性,最小约为1.3kB。为什么会存在? ...
面试官:说说你对vue的mixin的理解,有什么应用场景? 面试官:说说你对slot的理解?slot使用场景有哪些? 面试官:Vue.observable你有了解过吗?说说看 面试官:你知道vue中key的原理吗?说说你对它的理解? 面试官...
混合Mixin BFT-DAG网络参考实现,受信任的执行环境尚未集成到此存储库中。开始使用按照此指南安装golang并设置GOPATH 。 $ git clone https://github.com/MixinNetwork/mixin.git$ cd mixin$ go build mixin命令既是...
面试官:说说你对vue的mixin的理解,有什么应用场景? 面试官:说说你对slot的理解?slot使用场景有哪些? 面试官:Vue.observable你有了解过吗?说说看 面试官:你知道vue中key的原理吗?说说你对它的理解? 面试官...
面试官:说说你对vue的mixin的理解,有什么应用场景? 面试官:说说你对slot的理解?slot使用场景有哪些? 面试官:Vue.observable 你有没有解过?说说看 面试官:你知道vue中key的原理吗?说你对它的理解? 面试官...
Mixin.js Mixin是将功能重复混合到原型JavaScript类中的简便方法。 它会自动处理覆盖的原型方法和调用构造函数的组合。 而且,它将通知已混合到另一个类中的混合构造函数。 这可用于构造依赖的混合层次结构。 安装 ...
mixin混入来封装axios请求 我们通过mixin来封装axios请求这样每一个组件直接通过混入来进行axios请求。 不必每次需要时都要import引入一次 首先需要下载axios的包 //用npm、cnpm或者yarn都行 npm install axios ...
Mixin Client Java SDK这里是 Mixin Client Java SDK,其它语言的 Mixin SDK:NodeJS:Go:Python:更多 Mixin 开发资源:mixin_dev_resource:MiXin_Player:Java SDK v0.2当前版本 v0.2,主要功能是 Mixin 机器人:...
#react-validate-mixin npm install react-validate-mixin或者 bower install react-validate-mixin##例子 var validate = require ( 'react-validate-mixin' ) ;var Compoent = React . createClass ( { mixins ...