防止未定义的参数

时间:2011-09-16 23:04:34

标签: javascript

所以我正在使用一个对象传递我的可选变量,如下所示:

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风格编写一系列具有此模式的函数?

3 个答案:

答案 0 :(得分:6)

首先,您不需要将options参数重新分配给var。其次,对于某些值要小心:

var foo = function (options) {
            options = options || {};
            var bar = options.bar || 42;
            var baz = options.baz || 'fubar';
          };
foo({ bar: 0, baz: "" });

内部foobar == 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)