Подтвердить что ты не робот

Зачем передавать пустой объект в метод расширения jQuery?

jQuery имеет очень аккуратный extend метод, который объединяет 2 объекта в один.

На странице jQuery Plugins authoring они показывают пример следующим образом:

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, даже если они не сохраняют значения по умолчанию в переменной?

Я что-то пропустил?

4b9b3361

Ответ 1

Возможные причины (для второго примера)...

  • Унаследованное невежество... (увидели, что это сделано, и скопировали практику)

  • Внутреннее незнание... (видно, что оно сделано правильно, как в вашем последнем блоке кода, но заменило кешированный объект на лету и не знал, что пустой объект должен быть удален)

  • Глобальное потепление.

  • Отсутствие внимания к деталям... (похоже на пункт 2, знает, что это не обязательно, но на самом деле не потрачено время на изучение кода)

  • Глобальное охлаждение.

  • Слишком защитное кодирование... (боюсь, что значения по умолчанию могут когда-нибудь быть переработаны в объект многократного использования и опасаются, что пустой объект не будет вставлен в это время)

  • jQuery разработчики всегда делают то, что говорят им голоса; -)

В целом, ты прав. Средний объект создается, копируется в пустой объект, затем отбрасывается. Это ненужная и расточительная практика.

Ответ 2

Расширение - очень полезная функция для копирования объектов.

Например, рассмотрим следующее:

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);, настройки будут идентичными, но здесь значения по умолчанию также будут изменены. Вот почему вам нужен первый аргумент {}.

Ответ 3

Другой способ поставить то, что сказал 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