为什么要将空对象传递给jQuery的extend方法?

时间:2012-03-11 20:16:54

标签: javascript jquery object

jQuery有一个非常简洁的extend方法,它将2个对象合并为一个。

jQuery Plugins authoring page上,他们展示了如下示例:

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

但是,我看到很多插件都将一个空对象作为第一个参数传递,如下所示:

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

据我所知,这两个完全相同。唯一的区别是defaults是否会存储在自己的变量中:

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

这样,您始终可以访问默认设置,而不会被options覆盖。


以下是问题:为什么这么多插件作者选择将空对象传递给extend,即使他们没有将默认值存储在变量中?

我错过了什么吗?

3 个答案:

答案 0 :(得分:10)

Extend是一个非常有用的复制对象的函数。

例如,考虑一下:

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"}

因为你可以看到$ .extend实际上复制了该对象。

修改

第一个参数必须是空对象的原因是extend的工作原理。以下是jQuery如何定义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.

此外这句话很重要:

  

请记住,目标对象(第一个参数)将被修改,   并且还将从$ .extend()返回。

因此,通过将{}作为第一个参数传递,该空对象将被扩展,然后返回。

回到settings = $.extend({}, defaults, options);的示例。如果您将其更改为settings = $.extend(defaults, options);,则设置将相同,但此处的默认值也会更改。这就是为什么你需要第一个参数为{}

答案 1 :(得分:7)

可能的原因(对于第二个例子) ...

  • 继承无知...... (看到这样做,并复制了练习)

  • 内在的无知...... (看到它在你的上一个代码块中正确完成,但用一个即时对象替换了缓存的对象,并且不知道空对象应该是移除)

  • 全球变暖。

  • 缺乏对细节的关注...... (类似于第2点,知道没有必要,但从未真正花时间检查代码)

  • 全球降温。

  • 过度防御性编码...... (担心有一天默认值会被重写为可重用对象,并担心此时不会插入空对象) < / p>

  • jQuery开发人员总是做声音告诉他们的事情; - )

总的来说,你是对的。创建中间对象,将其复制到空对象,然后丢弃。这是一种不必要和浪费的做法。

答案 2 :(得分:4)

另一种表达miki所说的方式:

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