要使用默认值初始化对象,我使用的是Underscore的default函数。根据文档,它的工作原理如下:
var foo = _.defaults(object, *defaults)
它被描述为:
使用默认对象中的值填充对象中的未定义属性,并返回该对象。一旦财产被填满,进一步的违约将无效。
虽然它基本上运作正常但有一件事我总是偶然发现:操纵原始物体的副作用。
如果我跑
var foo = { bar: 'baz' };
然后说
var bar = _.defaults(foo, { dummy: 23 });
不仅bar
有一个名为dummy
的属性,原始foo
对象也已更改。我目前的解决方法是:
var bar = _.defaults({}, foo, { dummy: 23 });
不幸的是,你很容易忘记这一点。我认为defaults
函数更改输入参数以及将结果作为返回值返回是一种非常奇怪的行为。它应该是或。
你如何应对这种情况?有没有更好的方法来解决这个问题?
答案 0 :(得分:4)
该功能完全按照记录的方式完成。修改传递给函数的对象并不罕见,返回它们并不罕见。返回是一种方便的事情,因此您可以编写与“解决方法”完全相同的代码。
您的“解决方法”是正确的方法。
另一种选择是使foo
成为新对象的原型:
var bar = _.defaults(Object.create(foo), { dummy: 23 });
...但我只知道通过查看Underscore的annotated source (该链接可能会腐烂,但它会在那附近),因为文档没有t指定在复制默认值时,它是否仅查找“自己的”属性。 (它没有,它使用in
。)
另请注意,Object.create
是ES5,可能需要在旧浏览器上使用填充程序。上面的用法是可调的(因为我没有使用Object.create
的第二个参数)。
我刚读完你的头衔:
Underscore.js的副作用免费版默认功能?
如果您不喜欢您的解决方法,可以很容易地创建无副作用的版本:
function myDefaults() {
var args = [{}];
args.push.apply(args, arguments);
return _.defaults.apply(_, args);
}
创建一个空白对象并将其放在参数的开头,然后链接到_.defaults
。
答案 1 :(得分:1)
在我看来,文档是正确的。
在构造函数中,您可以跳过使用返回值。类似的东西:
function(options) {
_.defaults(options, defaults);
// you can now continue to use options instead of a new object
}
如果那不是您想要的,那么我认为您的解决方法非常好。
答案 2 :(得分:1)
我只是为它编写一个包装函数:
function defs (template_obj, additions) {
return _.defaults({},template_obj,additions);
}
然后简单地使用它:
var bar = defs(foo, { dummy: 23 });
如果您愿意,甚至可以添加函数来强调自己(通过_.mixin)。