2010-05-24 3 views
6

Я вижу примеры, где JavaScript код, включая JQuery и JSLint использовать ниже обозначение:Зачем писать глобальный код внутри пары определения функции?

(function(){ 
    // do something 
})(); 

вместо:

// do something 

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

Что мне здесь не хватает?

ответ

8

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

(function($) { 

    var localVarOnly = "local"; 

    $.fn.myCoolFunction = function() { // in the case of jquery, make this publicly available 
    otherCoolFunction(); //alerts hi 
    alert(localVarOnly); // alerts local 
    }; 

    function otherCoolFunction() { // scoped to this anonymous function only 
    alert('hi'); 
    }; 

})(jQuery); 

otherCoolFunction(); // undefined 
alert(localVarOnly); // undefined 
+0

Вам пришлось бросить jQuery, не так ли :) –

+0

Ха-ха, ну это _is_ мой любимый;) –

1

Это предназначено для создания области, содержащей все объявленные переменные. Это делается для того, чтобы избежать загрязнения глобальной области и избежать переопределения уже существующих переменных.

Возьмем такой пример

(function() { 
    var foo = "bar"; 
    var undefined = true; 
    var bar = true; 

    alert(foo); //bar 
    if (bar == undefined) { 
     alert("bar is undefined.. not!"); //will show even though we know that bar is not 'undefined' 
    } 

})(); 

var bar = true; 
alert(foo) //undefined 
if (bar == undefined) { 
    alert("bar is undefined"); // will not be called 
} 

Когда дело доходит до картины, (function(){/*....*/})(); в настоящее время дискуссия продолжается в comp.lang.javascript о том, как назвать эту конструкцию, и кто должен получить кредит на это :)

+2

Это одна из причин, и я уже понял это (см. Мой вопрос :). –

+0

Его ** только ** причина. –

+1

Вы говорите, что нет смысла помещать блок кода в функцию, если вы не используете какие-либо локальные переменные? Потому что, если вы видите мой вопрос, я видел примеры, в которых эти обозначения используются без каких-либо переменных. –

3

Основная цель этого шаблона (Crockford's) (есть и другие - в некоторых случаях более эффективные) - это избежать загрязнения глобальной области с помощью названных функций/идентификаторов. Делая вещи в этом анонимном закрытии, вы можете написать свой код так же, как и в глобальной области, за исключением того, что все, что было объявлено внутри, остается локальным и, следовательно, невозможно получить доступ/ссылку извне. Служебные случаи, когда локальные переменные/функции не используются или не экспортируются (назначены именованному идентификатору из одной из внешних областей), могут существовать, но необязательно должны быть вложены в анонимную функциональность.

3

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

var foo = function(){ 
    // local code 
}; 
foo(); 

Но если это все, что вы делаете, и Foo не имеет никакой другой полезности за называя его один раз, то анонимный, прямоприменяемый синтаксисом просто экономит вам дополнительную декларацию Var:

(function(){ 
    // local code 
})(); 

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

4

Как все говорили, это в значительной степени связано с созданием локальной области. Другим преимуществом является то, что вы можете использовать его для (без лучшего слова) переименования переменных. Возьмем, к примеру, как несколько фреймворков javascript используют $ в качестве сокращенной для их основной функции библиотеки.Если вы создаете замыкание, как в вашем примере, это не имеет значения, что $ является вне, вы можете использовать его в качестве параметра и внутри него может быть все, что вы хотите:

// out here $ might be Prototype, something else, or even undefined 
(function($) { 
    // in here, $ is jQuery 
})(jQuery); 

Другой небольшой совет для влачат дополнительная пара миллисекунд вашего скрипта должна использовать эту же технику для создания неопределенной переменной. Большинство людей думают, что undefined - специальное ключевое слово в javascript, но на самом деле это просто рассматривается как обычная переменная, которую вы, надеюсь, никто не определит. Несколько стандартная практика проверки для неопределенной переменной:

if (x == undefined) 

... на самом деле довольно расточительно, так как он проверяет всю цепочку области для переменной с именем «неопределенным». Для быстрого доступа этого, вы можете использовать этот метод:

(function($, undefined) { 
    // code here 
})(jQuery); // note that there's just one parameter passed 

Теперь, когда undefined на самом деле в объеме (с неопределенным значением), проверяя в цепочку области может остановиться в этой точке. Микро-оптимизация, да, но это не больно знать.

+0

Что касается оптимизации переменной 'undefined': не все еще быстрее проверять строку' 'undefined '' вместо сравнения с переменной (с «совпадением» с тем же именем)? –

+0

@Marcel - Я только что проверил (1 000 000 итераций обоих методов). Использование 'typeof x ==" undefined "' принимало ~ 2050 мс. Использование 'x == undefined' занимает ~ 34 мс. – nickf

+0

Как вы это протестировали? Например, если я использую [этот тестовый пример] (http://pastie.org/999172) в Firefox, между ними нет никакой разницы, но в Chromium 'typeof x ==" undefined "' значительно быстрее, чем 'typeof x == undefined'. Тестирование для 'x == undefined' работает только тогда, когда определено' x' (в противном случае возникает ошибка); тайминги практически не отличаются в Firefox, и в Chromium он даже немного медленнее, чем тестирование 'typeof x ==" undefined "', когда определяется 'x'. –

Смежные вопросы