开发者

Guarding against undefined parameters

开发者 https://www.devze.com 2023-04-05 06:00 出处:网络
So I\'m using an object to pass in my optional variables like so: var foo = function (options) { var options = options || {}; //provide a default, so that

So I'm using an object to pass in my optional variables like so:

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 complains t开发者_如何学JAVAhat I'm overwriting options, which is what I want if it's falsy. Actually, I should probably check if it's an Object and elsewise throw an error to let the user know what's up. So - on that note - what would be good form here? Anybody know a good read on this? Additionally, how would I go about writing a bunch of functions with this pattern in a DRY style?


First, you need to not reassign the options argument to a var. Second, be careful with this for certain values:

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

Inside foo, bar == 42 & baz == 'fubar' because 0 and "" are falsy. It's probably better to be more verbose so as to be more precise:

var foo = function (options) {
            options = options || {};
            var bar = typeof options.bar == 'undefined' ? 42 : options.bar;
            var baz = typeof options.baz == 'undefined' ? 'fubar' : options.baz;
          };

But, to be DRY, you can create a defaults object and just extend both objects to a settings object:

// 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);
};

Since you won't be using defaults any more in this invocation it doesn't matter that it gets mutated. Using this method:

foo();                    // -> settings = { bar: 42, baz: 'fubar' }
foo({ bar: 0 });          // -> settings = { bar: 0, baz: 'fubar' }
foo({ bar: 0, baz: "" }); // -> settings = { bar: 0, baz: '' }


Remove the var from the options line and JSLint will stop complaining.

It's because you have a parameter called options, and then you are trying to declare a local variable called options. You can still set the default value if it's falsey

options = options || {};

To be honest, the null coalescing in JavaScript is pretty fine on it's own.

You can remember that you can be a bit 'exotic' with it, if you really want. So, for your example, if you just wanted options.bar or 42:

(options || {})["bar"] || 42

(remembering that you can access JavaScript properties by dot notation or array style)

It's not pretty - but it's just one example. Alternatively, you could do something like:

(options || {"bar":42})["bar"]

If you had a default set of options, you can do:

(options || defaults)["bar"]

Note : As mentioned in a different answer, you should be careful before certain values are falsely that you might not realise (i.e. an empty string). Of course, sometimes this is exactly what you want but it's just something to remember :)


JSLint is only complaining because you are using the var keyword, but options has already been defined. You can just remove the var and it won't complain.

To test if options is an object you can use typeof options === 'object', but note that arrays and null are also objects, so you may want to test something like:

typeof options === 'object' && options !== null && !(options instanceof Array) 
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号