所以我正在使用一个对象传递我的可选变量,如下所示:
var foo = function (options) {
var options = options || {}; //provide a default, so that
var bar = options.bar || 42; //this doesn't fail on 'foo();'
//do stuff
};
JSLint抱怨我正在覆盖选项,如果它是假的,这就是我想要的。实际上,我应该检查它是否是一个对象,否则抛出错误让用户知道是什么。所以 - 在那个注意事项 - 这里有什么好的形式?有人对此有一个很好的解读吗?另外,我将如何以DRY风格编写一系列具有此模式的函数?
答案 0 :(得分:6)
首先,您不需要将options
参数重新分配给var。其次,对于某些值要小心:
var foo = function (options) {
options = options || {};
var bar = options.bar || 42;
var baz = options.baz || 'fubar';
};
foo({ bar: 0, baz: "" });
内部foo
,bar == 42
& baz == 'fubar'
,因为0
和""
是假的。为了更加精确,更加冗长可能更好:
var foo = function (options) {
options = options || {};
var bar = typeof options.bar == 'undefined' ? 42 : options.bar;
var baz = typeof options.baz == 'undefined' ? 'fubar' : options.baz;
};
但是,要成为DRY,您可以创建一个defaults
对象,只需将两个对象扩展到settings
对象:
// generic shallow object extension, mutates obj1
var extend = function (obj1, obj2) {
for (var prop in obj2) {
if (obj2.hasOwnProperty(prop)) {
obj1[prop] = obj2[prop];
}
}
return obj1;
};
var foo = function (options) {
var defaults = {
bar: 42,
baz: 'fubar'
},
settings = extend(defaults, options);
};
由于您不会在此调用中再次使用defaults
,因此它会发生变异并不重要。使用此方法:
foo(); // -> settings = { bar: 42, baz: 'fubar' }
foo({ bar: 0 }); // -> settings = { bar: 0, baz: 'fubar' }
foo({ bar: 0, baz: "" }); // -> settings = { bar: 0, baz: '' }
答案 1 :(得分:0)
从选项行中删除var
,JSLint将停止抱怨。
这是因为你有一个名为options的参数,然后你试图声明一个名为options的局部变量。如果它是假的
,您仍然可以设置默认值options = options || {};
老实说,JavaScript中的空值合并本身就很好。
你可以记住,如果你真的想要的话,你可能有点“异国情调”。因此,对于您的示例,如果您只想要options.bar或42:
(options || {})["bar"] || 42
(记住您可以通过点表示法或数组样式访问JavaScript属性)
它不漂亮 - 但它只是一个例子。或者,您可以执行以下操作:
(options || {"bar":42})["bar"]
如果您有一组默认选项,则可以执行以下操作:
(options || defaults)["bar"]
注意:正如在不同的答案中所提到的,在某些值错误地表示您可能没有意识到之前(即空字符串),您应该小心。当然,有时这正是你想要的,但它只是要记住的东西:)
答案 2 :(得分:0)
JSLint只是抱怨,因为你使用的是var关键字,但是已经定义了选项。您只需删除var
,就不会抱怨。
要测试选项是否为对象,可以使用typeof options === 'object'
,但请注意,数组和null
也是对象,因此您可能需要测试类似的内容:
typeof options === 'object' && options !== null && !(options instanceof Array)