最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why pass an empty object to jQuery's extend method? - Stack Overflow

programmeradmin11浏览0评论

jQuery has a very neat extend method, which merges 2 objects into one.

On the jQuery Plugins authoring page they show an example as follows:

var settings = $.extend({
    'location'         : 'top',
    'background-color' : 'blue'
}, options);

However, I've seen many plugins pass an empty object as the first parameter, like so:

var settings = $.extend({}, {
    'location'         : 'top',
    'background-color' : 'blue'
}, options);

As far as I can tell, these two do the exact same thing. The only difference would be if the defaults would have been stored in its own variable:

var defaults = {
    'location'         : 'top',
    'background-color' : 'blue'
},
settings = $.extend({}, defaults, options);

This way, you can always access your defaults without them being overridden by the options.


Here's the question: Why do so many plugin authors opt to pass an empty object to extend, even when they don't store the defaults in a variable?

Am I missing something?

jQuery has a very neat extend method, which merges 2 objects into one.

On the jQuery Plugins authoring page they show an example as follows:

var settings = $.extend({
    'location'         : 'top',
    'background-color' : 'blue'
}, options);

However, I've seen many plugins pass an empty object as the first parameter, like so:

var settings = $.extend({}, {
    'location'         : 'top',
    'background-color' : 'blue'
}, options);

As far as I can tell, these two do the exact same thing. The only difference would be if the defaults would have been stored in its own variable:

var defaults = {
    'location'         : 'top',
    'background-color' : 'blue'
},
settings = $.extend({}, defaults, options);

This way, you can always access your defaults without them being overridden by the options.


Here's the question: Why do so many plugin authors opt to pass an empty object to extend, even when they don't store the defaults in a variable?

Am I missing something?

Share Improve this question edited Jan 1, 2013 at 18:15 Joseph Silber asked Mar 11, 2012 at 20:16 Joseph SilberJoseph Silber 220k59 gold badges368 silver badges293 bronze badges 6
  • 1 Seems pointless to me. It's making a populated one, copying it into an empty one, and discarding it. Your third example shows a valid reason. I'm guessing people do it because they don't think about what they're doing. – user1106925 Commented Mar 11, 2012 at 20:20
  • @amnotiam That's exactly what I'm thinking, but I've seen so many plugins do this. Clearly I'm missing something... – Joseph Silber Commented Mar 11, 2012 at 20:21
  • No, I think the trouble is that you're getting something. – user1106925 Commented Mar 11, 2012 at 20:21
  • 2 Could be defensive coding I suppose. The "what if someday I decide to store it in a variable and I forget..." type of thing. If so, seems overly cautious to me. – user1106925 Commented Mar 11, 2012 at 20:23
  • 1 Theory: somebody had the third form, realized they didn't need the variable and then "optimized" it into the second form. Other plugins acquired the code because they used the "copy and modify" programming style. Others saw it and just assumed there was a good reason for doing it that way. – Bryan Larsen Commented Mar 11, 2012 at 20:52
 |  Show 1 more ment

3 Answers 3

Reset to default 10

Extend is a very useful function to copy objects.

For example consider this:

foo = {'foo':'a'}
f = foo
f.foo = 'hello'
console.log(f)
    Object {foo="hello"}
console.log(foo)
    Object {foo="hello"}

f = $.extend({},foo)
f.foo = 'hello world'
console.log(f)
    Object {foo="hello world"}
console.log(foo)
    Object {foo="hello"}

So as you can see $.extend actually copied the object.

EDIT

The reason why the first parameter has to be an empty object is because of how extend works. Here is how jQuery defines extend:

jQuery.extend( target [, object1] [, objectN] )
   target    An object that will receive the new properties
             if additional objects are passed in or that will
             extend the jQuery namespace if it is the sole argument.
   object1   An object containing additional properties to merge in.
   objectN   Additional objects containing properties to merge in.

And additionally this phrase is important:

Keep in mind that the target object (first argument) will be modified, and will also be returned from $.extend().

So by passing the {} as first parameter, that empty object is extended and then returned.

Getting back to your example of settings = $.extend({}, defaults, options);. If you would change it to settings = $.extend(defaults, options);, the settings will be identical however here the defaults will also be changed. Thats why you need the first argument to be {}.

Possible reasons (for the second example)...

  • Inherited ignorance... (saw it done that way, and copied the practice)

  • Intrinsic ignorance... (saw it done properly as in your last code block, but replaced the cached object with an on-the-fly object and didn't know that the empty object should be removed)

  • Global warming.

  • Lack of attention to detail... (similar to point 2, knows it isn't necessary but never really took the time to examine the code)

  • Global cooling.

  • Overly defensive coding... (afraid that the defaults may someday be reworked into a reusable object, and is afraid that the empty object won't be inserted at that time)

  • jQuery developers always do what the voices tell them ;-)

Overall, you're right. The middle object is created, copied to an empty object, then discarded. It's an unnecessary and wasteful practice.

Another way of putting what miki said:

var defaults = {
  one: 'foo',
  two: 'bar'
};

var options = {
  two: 'apples',
  three: 'bananas'
};

// The safe way to extend
var settings = $.extend({}, defaults, options);

console.log( settings ); // {one: 'foo', two: 'apples', three: 'bananas'}
console.log( defaults ); // {one: 'foo', two: 'bar'}
console.log( options ); // {two: 'apples', three: 'bananas'}
console.log( settings === defaults ); // false

// Careless way to extend
var settings = $.extend(defaults, options);

console.log( settings ); // {one: 'foo', two: 'apples', three: 'bananas'}
console.log( defaults ); // {one: 'foo', two: 'apples', three: 'bananas'}
console.log( options ); // {two: 'apples', three: 'bananas'}
console.log( settings === defaults ); // true
发布评论

评论列表(0)

  1. 暂无评论