Dojo1.11官方教程文档翻译(4.3)对象扩张

原文地址:https://dojotoolkit.org/documentation/tutorials/1.10/augmenting_objects/index.html
本翻译项目放在GitBook上,欢迎参与。
GitBook地址:https://www.gitbook.com/book/limeng1900/dojo1-11-tutorials-translation-in-chinese/details
转载请注明出处:http://blog.csdn.net/taijiedi13/ – 碎梦道


当你使用JavaScript时,你是在和对象打交道。dojo/_base/lang可以让你在使用dojo/_base/declare时用lang.mixinlang.extenddeclare.safeMixin来扩张对象和原型。

入门

lang.mixinlang.extenddeclare.safeMixin用来从一个或多个其它对象的属性扩张原始对象。在本文中其它对象称为“混入类”(mixins)。这些函数有一些小差异,来适用不同的应用场景。在我们深入之前先看一个简要概述:

Method:lang.mixindeclare.safeMixinlang.extend
Operates onobjectobjectobject.prototype
Mixes in constructor propertyyesnoyes
Mixes in multiple objects at onceyesnoyes
Annotates functions to support this.inheritednoyesno
Speedfastslowfast
Use primarily withA plain objectA declare instanceA constructor

lang.mixin

lang.mixin方法是一个简单的通用函数,可以用任意数量的对象作为参数,把随后的对象的属性添加到第一个对象上并返回它。例如,我们已经有一个对象需要添加一些额外属性。它可能是表单数据的集合、模板的一些数据、一个命名空间对象或者一个设置对象。在任何例子中如果不用lang.mixin,复制属性得像下面这样:

var formData = domForm.formToObject(dom.byId('form'));
formData.name = currentUser.name;
formData.phone = currentUser.phone;
formData.address = currentUser.address;
formData.city = currentUser.city;
formData.province = currentUser.province;
formData.country = currentUser.country;
formData.postalCode = currentUser.postalCode;

这样从一个对象复制数据到另一个需要输入很多内容。假设第二个对象的属性的都要复制到第一个里,lang.mixin可以很简单:

var formData = domForm.formToObject(dom.byId("form"));
lang.mixin(formData, currentUser);

注意这个调用的返回值被丢弃了。因为lang.mixin直接作用在传入的第一个对象里,所以我们不用再手动更新formData变量。
lang.mixin也可以同时混入多个对象。例如,如果你设置的对象有一个原型,在它创建新实例时经常需要包含默认的值,你可以这么写:

var defaultSettings = {
    useTheForce: true,
    isEvil: false,
    length: 75,
    color: "blue"
};

function Lightsaber(settings){
    // `defaultSettings` is first mixed into the blank object,
    // then `settings` is mixed into the blank object, overriding
    // any properties from `defaultSettings` without altering
    // the `defaultSettings` object
    this.settings = lang.mixin({}, defaultSettings, settings);
}

var darthsaber = new Lightsaber({
    isEvil: true,
    color: "red"
});

// { useTheForce: true, isEvil: true, length: 75, color: "red" }
console.log("darthsaber:", darthsaber.settings);

View Demo

declare.safeMixin

declare.safeMixin主要完成lang.mixin相同的任务,但有三点不同:
- 它一直只能混入一个对象
- 它不能混入constructor属性
- 它会为函数添加注释便于declarethis.inherited功能属性正常功能

尽管如名称暗示的没有原始lang.mixin的不安全成分,但除了:
- 你在往declare创建的对象的一个实例里添加功能,并且:
- 你依赖调用this.inherited,或者
- 混入的一个或多个对象包含一个constructor属性。

因此,在declare过的类的实例的实例的情况之外,lang.mixin基本就够用了。
declare过的构造器有一个extend方法,它是将带有declare的构造器的原型作为第一个参数的declare.safeMixin。这个不要和下面要说的lang.extend混淆。

lang.extend

lang.extendlang.mixin非常相似,处理它是给第一个对象的prototype添加属性而不是直接在对象本身添加。对于想要将改变立即在全部继承的实例上生效的情况,直接扩张对象的原型很有用:

// Assume Lightsaber is defined as in the previous example

var darthsaber = new Lightsaber({
    isEvil: true,
    color: "red"
});

var weaponMixin = {
    hp: 5,
    maxHp: 10,
    repair: function() {
        if(this.hp >= this.maxHp) {
            console.log("Can't repair!");
            return;
        }

        this.hp++;
    },
    swing: function() {
        if(!this.hp) {
            console.log("Weapon is broken!");
            return;
        }

        this.hp--;
        console.log(Math.random() >= 0.5 ? "hit!" : "miss!");
    }
};

lang.extend(Lightsaber, weaponMixin);

// Now we can call swing() on our Lightsaber instance,
// even though we augmented the prototype after creating the instance.
darthsaber.swing(); // "hit!" (or "miss!" if you are unlucky)

View Demo

这比在创建的每一个新对象上调用lang.mixin更加高效,它只修改一个被继承的对象而不是几个子对象。它也比用declare.safeMixin更快。然而,当你需要对this.inherited调用的功能增加一个declare过的构造器功能,你应该使用declare.safeMixin或者构造器上的extend方法:

var Lightsaber = declare({
    constructor: function(settings){
        this.settings = lang.mixin({}, defaultSettings, settings);
    }
});

// same augmentation, but calls to this.inherited won't break:
Lightsaber.extend(weaponMixin);

注意使用lang.extend 或者declaredConstructor.extend有效修改构造器的原型会有问题,它会影响所有创建的示例。因此,将这些功能的使用限制在你确认合适的地方非常重要,不然就会引起不必要的副作用。尤其是,记住当创建自定义的out-of-the-box 组件时,推荐使用declare创建派生,而不是扩张已有的原型。

重要的是,注意所有的混入函数执行浅拷贝。就是说以下是正确的:
重要的是要注意我们引入的混入函数执行浅拷贝。例如:

var a = {
    name: "a",
    subObject: {
        foo: "bar"
    }
};
var b = lang.mixin({}, a);

b.name = "b";
b.subObject.foo = "baz";

console.log("a b, as expected:",
    a.name, b.name);
console.log("true - both subObjects reference the exact same object:",
    a.subObject === b.subObject);
console.log("baz baz - a change to one subObject affects both:",
    a.subObject.foo, b.subObject.foo);

在简单的例子中,这种行为不是问题,甚至在某些情况下很合适。然而在你不想要共享对象的地方,你可以使用一个lang.clone进行深拷贝。

var a = {
    name: "a",
    subObject: {
        foo: "bar"
    }
};
var b = lang.clone(a);

b.name = "b";
b.subObject.foo = "baz";

console.log("a b, same as before:",
    a.name, b.name);
console.log("false - the subObjects are different now:",
    a.subObject === b.subObject);
console.log("bar baz - a change to one subObject no longer affects all:",
    a.subObject.foo, b.subObject.foo);

View Demo

记住深拷贝明显要比浅拷贝慢,而且用在递归数据结构上会引起脚本挂起。深拷贝应该只在绝对必须的时候使用。

小结

Dojo简化了创建和扩张对象和类的过程。lang.mixindeclare.safeMixin方法为在一个对象上添加和瞎改属性提供了便捷的方法,lang.extend让修改对象原型变得更加容易。请记住,这些函数执行浅拷贝。

dojo/_base/lang资源

想了解 lang.mixinlang.extenddeclare.safeMixinlang.clone的更多细节?查看这些资源:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值