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

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

在jQuery Plugins创作页面上,他们展示了一个示例如下:

 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 ,即使他们没有将默认值存储在变量中?

我错过了什么吗?

可能的原因(第二个例子) ……

  • inheritance无知…… (看到它这样做,并复制了练习)

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

  • 全球暖化。

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

  • 全球降温。

  • 过于防御性的编码…… (担心有一天默认值会被重写为可重用的对象,并担心当时不会插入空对象)

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

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

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); 。 如果你把它改成settings = $.extend(defaults, options); ,设置将相同,但此处的默认值也将更改。 这就是为什么你需要第一个参数是{}

把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