Javascript closures - поведение переопределенных функций из глобальной области видимости - PullRequest
2 голосов
/ 18 февраля 2012

Этот вопрос больше относится к принципу javascript.

function done(){ console.log('done defined with `function done(){ ...`'); }
var done = function(){ console.log('done defined with `var done = ...`'); }
done = function(){ console.log('without `var`, just `done = ...`'); }

Если они определены прямо внутри тегов <script>, будут ли они все делать то же самое, верно?

Но если я их разместув замыкании (function(){ здесь идет определение функции }()) переопределит ли любой из этих трех типов либо глобально определенную функцию done () , либо любую другую done () функции, которые определены внутри их соответствующих замыканий?

Если вопрос выше не имеет смысла, перефразируем;

  • должен ли следующий код делать то же самое в любой среде выполнения JS?
  • eval -ing-код где-нибудь выполняет этот конкретный код в контексте или глобальной области действия?
  • как можно настроить вызов setTimeout так, чтобы код между его "quotes "выполняется внутри области, где был вызван конкретный setTimeout (см. второй тайм-аут внутри for ниже)?Я имею в виду, есть ли другой способ, кроме определения функций window.blabla и указания им удалять себя после запуска?

    function done(d){ console.log('cha cha cha: '+d); }
    setTimeout( function(){ done(2); }, 3500 );
    
    for(i=0; i<10; i++){
        (function(){
            done = function(x){ console.log('done #'+i+' sais: '+x); }
            setTimeout(function(){ done(i*2); },2500);
            setTimeout(function(){ done(i*2); }.toString()+'(); ',2500);
        }());
    }
    

Ответы [ 3 ]

1 голос
/ 18 февраля 2012

Для первоначального вопроса об общем поведении:

  • var done = и function done делают одно и то же. Они будут скрывать внешнее определение во внутренней области, но не заменят его во внешней области.

  • done = установит соответствующую переменную done в области видимости или создаст глобальную переменную, если такой переменной не существует и программа не работает в строгом режиме.

  • На глобальном уровне вне любой функции var done = и done = должны работать одинаково, но они работают по-разному в IE, если вы пытаетесь использовать переменную в другом теге скрипта (придерживайтесь var = - все равно лучше).

Что касается очень злых вопросов setTimeout и eval:

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

  • eval запускает код в текущей области (для этого используется глубокая чёрная магия). Если вы хотите запустить код в глобальной области видимости, вы можете использовать new Function.

  • Чтобы установить время ожидания для запуска строки в текущей области, вы можете добавить eval самостоятельно:

    var done = function(d){ console.log('outer done', d); };
    
    (function(){
        var done = function(x){ console.log('inner done', x); };
    
        setTimeout(function(){ done(1); }, 200);           //inner done
        setTimeout('done(2)', 400);                        //outer done
        setTimeout(function(){ eval('done(3)'); }, 600);   //inner done
    }());
    
  • Еще раз, почему вы оцениваете вещи в setTimeouts? Все это звучит глубоко злым!

0 голосов
/ 18 февраля 2012

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

Например:

// this is valid
foo();
function foo(){ console.log("foo"); }

// this throws an error...
bar();
var bar = function (){ console.log("bar"); };

// ...and so does this...
baz();
var bat = function baz(){ console.log("bazbat"); };

// ...and this!
baz();
0 голосов
/ 18 февраля 2012

Существуют различия между var done и done, потому что последний подразумевает window.done и поэтому может быть delete d.

Оператор done = foobar; перезапишет следующую переменную "done"в цепочке области.Если есть локальный var, он меняет то, что, если есть глобальный, он перезаписывает этот, а если нет, то создает новый глобальный.Все это не повлияет на какие-либо частные переменные в других областях (замыканиях).

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