`

「译」你的 mixin 兼容 ECMAScript 5 吗?

阅读更多

原文: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 方法。 否则,你会发现自己陷入像我一样的错误。

20
13
分享到:
评论

相关推荐

    你的 mixin 真的兼容 ECMAScript 5 吗?

    然而,当涉及到ECMAScript 5的兼容性时,一些常见的mixin实现可能会出现问题,特别是在处理getter和setter等新特性时。本文将深入探讨这个问题,并提供一个解决方案。 首先,让我们回顾一下传统的mixin函数,它通常...

    react-compat-component:将 ES6 与 mixin 等结合起来

    你想保留你的mixin吗? 你想念自动绑定this给你的方法? 这对你来说是完美的! react-compat-component允许您在不更改太多代码的情况下为组件使用新的 ES6 类结构。 并且它允许您继续使用 mixin 而无需任何特殊...

    Mixin,MIXIN是使用ASM的Java的特性/混合框架.zip

    Mixin框架是Java编程语言中的一个开源项目,它利用ASM库来实现对类的低级别修改,也就是所谓的"混合"(Mixins)。这个框架的核心概念是将功能或行为注入到目标类中,而无需继承或者使用代理模式。在游戏开发、模块化...

    前端大厂最新面试题-mixin.docx

    Vue 中的 Mixin 及其应用场景 在 Vue 中,Mixin 是一种提供了方法实现的类,其他类可以访问 Mixin 类的方法而不必成为其子类。Mixin 类通常作为功能模块使用,在需要该功能时“混入”,有利于代码复用又避免了多...

    ECMAScript 6入门.pdf

    ECMAScript 6,也被简称为ES6,是JavaScript语言的下一代标准,它的发布目的是为了让JavaScript语言能够用于编写更复杂的大型应用程序,进而成为企业级开发语言。ES6在2015年6月正式发布,并且按照计划,标准制定者...

    小程序mixin混入Page选项合并

    在微信小程序的开发中,`mixin` 是一种常见的代码复用机制,它允许开发者定义一组通用的方法或者属性,然后将这些通用部分混入(mix in)到不同的页面(Page)或组件(Component)中,避免了代码重复,提高了代码的...

    ymixin是来自阅文前端团队的CSS预处理器mixin库

    当在`.my-element`选择器中使用`@include border-radius(5px)`时,这个mixin会被展开,将5px作为边框圆角值应用到对应的元素上。 ymixin库中包含了一系列实用的mixin,涵盖了布局、动画、响应式设计等多个方面,如...

    ruby-destroyed_at, 用于安全销毁的ActiveRecord Mixin.zip

    ruby-destroyed_at, 用于安全销毁的ActiveRecord Mixin DestroyedAt 查找帮助?如果是一个 Bug ,请在GitHub上打开一个问题。安装将 destroyed_at gem 添加到 Gemfilegem 'destroyed_at'你可以在每个模块中

    mixin白皮书

    mixin是一个闪电交易快速的点点对的数字交道项目,它拥有非常好的技术栈。

    A Swift mixin for UITableViewCells and UICollectionViewCells.zip

    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...

    forge-mixin-example:在Minecraft Forge 1.12.2中使用Mixin的示例

    例如,如果你想要修改玩家类的行为,你可以创建一个新的类并用`@Mixin(PlayerEntity.class)`来指定目标。 3. **@Shadow注解**:用于标记那些在目标类中存在的但不直接在注入类中定义的方法或字段。这使得Mixins可以...

    modernizr-mixin, 在Sass中,针对测试的简单而全面的mixin.zip

    modernizr-mixin, 在Sass中,针对测试的简单而全面的mixin hardwarebutton混合 一种简单的DRYier测试方法,在Sass中更快更。安装要求 ruby 3.4或者 LibSass 3.2Libsass警告:在 Libsass 3.2.3中有一个已知 Bug,它...

    react-observer-mixin:具有ES5和ES6兼容语义的React.js Mixin,它提供托管事件侦听器和安全的状态设置方法

    React观察者混合 具有ES5和ES6兼容语义的 Mixin提供了尊重组件生命周期的托管事件侦听器,以及与React不变式兼容并适用于一次性事件处理程序的状态设置器。 该模块没有运行时相关性,最小约为1.3kB。为什么会存在? ...

    vue面试题说说你对vue、双向绑定、SPA(单页应用)、的v-show和v-if、Vue实例挂载的过程的理解?

    面试官:说说你对vue的mixin的理解,有什么应用场景? 面试官:说说你对slot的理解?slot使用场景有哪些? 面试官:Vue.observable你有了解过吗?说说看 面试官:你知道vue中key的原理吗?说说你对它的理解? 面试官...

    mixin:Mix Mixin TEE-BFT-DAG网络参考实现

    混合Mixin BFT-DAG网络参考实现,受信任的执行环境尚未集成到此存储库中。开始使用按照此指南安装golang并设置GOPATH 。 $ git clone https://github.com/MixinNetwork/mixin.git$ cd mixin$ go build mixin命令既是...

    vue前端大厂面试题集合

    面试官:说说你对vue的mixin的理解,有什么应用场景? 面试官:说说你对slot的理解?slot使用场景有哪些? 面试官:Vue.observable你有了解过吗?说说看 面试官:你知道vue中key的原理吗?说说你对它的理解? 面试官...

    前端项目-universal-mixin.zip

    【前端项目-universal-mixin.zip】是一个针对前端开发的压缩包,其主要目的是提供一个跨JavaScript引擎的混合(mixin)解决方案,使开发者能够在旧的、现代的以及未来的JavaScript环境中编写兼容性强、轻量级的特性...

Global site tag (gtag.js) - Google Analytics