JavaScript — преимущества объектного литерала

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

Может кто-нибудь объяснить, в чем преимущества объектного литерала, на примерах, потому что я пока не понимаю.

Спасибо


person Jourkey    schedule 21.10.2009    source источник


Ответы (4)


Как сказал Расс Кэм, вы избегаете загрязнения глобального пространства имен, что очень важно в наши дни объединения сценариев из разных мест (TinyMCE и т. д.).

Как сказал Алекс Секстон, это также способствует хорошей организации кода.

Если вы используете эту технику, я бы предложил использовать шаблон модуля. Это по-прежнему использует литералы объектов, но в качестве возвращаемого значения из функции области видимости:

var MyThingy = (function() {

    function doSomethingCool() {
        ...
    }

    function internalSomething() {
        ....
    }

    function anotherNiftyThing() {
        // Note that within the scoping function, functions can
        // call each other direct.
        doSomethingCool();
        internalSomething();
    }

    return {
        doSomethingCool: doSomethingCool,
        anotherNiftyThing: anotherNiftyThing
    };
})();

Внешнее использование:

MyThingy.doSomethingCool();

Функция определения области охватывает все ваши функции, а затем вы немедленно вызываете ее и сохраняете возвращаемое значение. Преимущества:

  • Функции объявляются обычным образом и поэтому имеют имена. (В то время как в формате {name: function() { ... }} все ваши функции являются анонимными, даже если свойства, ссылающиеся на них, имеют имена.) Инструменты справки по именам помогают вам: от отображения стеков вызовов в отладчике до сообщения о том, какая функция вызвала исключение. (Обновление 2015 г.: последняя спецификация JavaScript, 6-е издание ECMAScript, определяет большое количество способов, которыми движок JavaScript должен выводить имя функции. Один из них — когда функция присваивается свойству, как в нашем {name: function() { ... }} пример. Так как двигатели реализуют ES6, эта причина исчезнет.)
  • Дает вам свободу использования частных функций, используемых только вашим модулем (например, мой internalSomething выше). Никакой другой код на странице не может вызывать эти функции; они действительно частные. Только те, которые вы экспортируете в конце, в операторе return, видны вне функции области видимости.
  • Упрощает возврат различных функций в зависимости от среды, если реализация полностью меняется (например, IE-vs-W3C или SVG vs. Canvas и т. д.).

Пример возврата различных функций:

var MyUtils = (function() {
    function hookViaAttach(element, eventName, handler) {
        element.attachEvent('on' + eventName, handler);
    }

    function hookViaListener(element, eventName, handler) {
        element.addEventListener(eventName, handler, false);
    }

    return {
        hook: window.attachEvent ? hookViaAttach : hookViaListener
    };
})();

MyUtils.hook(document.getElementById('foo'), 'click', /* handler goes here */);
person T.J. Crowder    schedule 21.10.2009
comment
Когда вы создаете функцию анонимно, вы все равно можете дать ей имя (var x = function x() { ... }). Когда вы это делаете, имя связывается таким образом, что оно доступно для рекурсивных ссылок внутри функции. - person Pointy; 21.10.2009
comment
@Pointy: вы не можете сделать это (использовать имя функции в назначении) в кросс-браузере, это не работает правильно ни в IE, ни в Safari; подробности: yura.thinkweb2.com/named-function-expressions Если этого не требуется, собственное имя функции (foo в function foo) находится в области видимости во всей области, где она объявлена, в том числе внутри самой функции, поэтому foo может вызывать себя через символ foo, нет необходимости присваивать ссылку на функцию ничего (на тот момент). - person T.J. Crowder; 21.10.2009
comment
(продолжение) Конечно, было бы хорошо иметь возможность одновременно использовать и присваивание, и собственное имя, потому что это облегчило бы экспорт функций из функции определения области видимости. Спецификация, безусловно, позволяет это, но, к сожалению, в нее вмешиваются практические аспекты (ошибки реализации). - person T.J. Crowder; 21.10.2009

Использование объектного литерала (также известного как шаблон объектного литерала) не загрязняет глобальное пространство имен так сильно, как использование многих функций, объявленных глобально, а также помогает организовать код логическим образом.

Например, этот объектный литерал

var obj = {
              find : function(elem) { /* find code */ },
              doSomething: function() { /* doSomething code */ },
              doSomethingElse: function() { /* doSomethingElse code */ }
          }

в сравнении с

function find(elem) { /* find code */ },
function doSomething() { /* doSomething code */ },
function doSomethingElse() { /* doSomethingElse code */ }

создаст только одно свойство глобального объекта по сравнению с тремя. Затем вы можете легко использовать такие функции, как

obj.doSomething();
person Russ Cam    schedule 21.10.2009
comment
вы можете просто написать много функций в одной нормальной функции и не загрязнять свой код. объектный литерал не дает никакой добавленной стоимости. Я сам использую метод прототипа. - person vsync; 30.11.2009

Ребекка Мерфи выступила с докладом об объектных литералах на конференции jQuery в этом году. Одна из лучших причин их использования — просто хорошая организация кода.

Вот запись Ребекки о литеральном шаблоне объекта: >http://rmurfey.com/blog/2009/10/15/using-objects-to-organize-your-code/

person Alex Sexton    schedule 21.10.2009
comment
Еще одна замечательная статья о литералах объектов: wait-till-i.com/2006/02/16/show-love-to-the-object-literal - person Alex Sexton; 21.10.2009

Я всегда использовал литералы объектов, потому что они представляют собой простой способ организации кода. Вот почему я не люблю прототипы, это слишком грязно.

Функции не загрязняют пространство имен, как упоминалось выше, не больше, чем литералы объектов.

Вы могли бы легко написать буквально как

var obj = {}
var find = function(elem) { /* find code */ },
var doSomething = function() { /* doSomething code */ },
var doSomethingElse = function() { /* doSomethingElse code */ }

что загрязнит создание множества глобальных объектов, таких же, как и функции. аналогично вы могли бы сделать:

(function() {
function find(elem) { /* find code */ },
function doSomething() { /* doSomething code */ },
function doSomethingElse() { /* doSomethingElse code */ }
})();

который не будет создавать эти глобальные объекты (в JS все является объектом)

таким образом, вы все еще не создаете множество глобальных объектов.

На мой взгляд, объектные литералы имеют два преимущества. Во-первых, они используются многими плагинами, такими как jQuery, поэтому люди более знакомы и их легко читать. Облегчение передачи данных в плагин. Легко создавать как общедоступные, так и частные методы....

Они могут быть медленными, поскольку каждый раз, когда вы создаете экземпляр объекта, все его методы дублируются. Насколько я понимаю, это не относится к прототипу, поскольку у вас есть одна копия методов, а новые объекты просто ссылаются на прототип.

могу ошибаться конечно...

person monkey panther    schedule 09.11.2013
comment
Литералы объектов хороши для пространства имен и синглтонов. Когда вы создаете несколько экземпляров объекта с общим поведением, лучше использовать функции-конструкторы. Я не нашел варианта использования, при котором потреблялось бы больше процессора и памяти путем имитации приватных способов вместо использования _myPrivate для приватных, но был бы рад, если бы кто-нибудь мог предоставить мне один. Подробнее о прототипе, наследовании, миксах здесь: stackoverflow.com/a/16063711/1641941 - person HMR; 09.11.2013