Являются ли переменные статически или динамически "скопированы" в javascript?

Или более конкретным для того, что мне нужно:

Если я вызову функцию из другой функции, она собирается вытащить переменную из вызывающей функции или с уровня выше? Пример:

myVar=0;

function runMe(){
    myVar = 10;
    callMe();
}

function callMe(){
   addMe = myVar+10;
}

Что делает myVar в том случае, если callMe() вызывается через runMe()?

Ответ 1

Джефф прав. Обратите внимание, что на самом деле это не хороший тест статического охвата (который имеет JS). Лучше было бы:

myVar=0;

function runMe(){
    var myVar = 10;
    callMe();
}

function callMe(){
   addMe = myVar+10;
}

runMe();
alert(addMe);
alert(myVar);

На языке с статической областью (например, JS), который оповещает 10 и 0. var myVar (локальная переменная) в runMe затемняет глобальную myVar в этой функции. Однако это не влияет на callMe, поэтому callMe использует глобальный myVar, который все еще находится в 0.

На языке с динамическим охватом (в отличие от JS) callMe наследует область действия от runMe, поэтому addMe станет 20. Обратите внимание, что myVar все равно будет 0 в оповещении, потому что предупреждение не наследует область видимости от любой функции.

Ответ 2

если ваша следующая строка callMe();, то addMe будет равно 10, а myVar будет 0.

если ваша следующая строка runMe();, то addMe будет равно 20, а myVar будет равно 10.

Простите меня за вопрос - что это связано со статическим/динамическим связыванием? Разве myVar не является глобальной переменной и не будет обрабатывать процедурный код (разворачивать все в стек вызовов)?

Ответ 3

Переменные статически привязаны к JavaScript (динамическое масштабирование - действительно довольно грязный бизнес: вы можете больше узнать об этом на Wikipedia).

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

Эта страница объясняет, как объявлять глобальные и локальные переменные в JavaScript, если вы не слишком хорошо знакомы с ней. Это отличается от того, как это делают большинство языков сценариев. (Вкратце: ключевое слово "var" делает переменную local, если она объявлена ​​внутри функции, иначе переменная глобальна.)

Ответ 4

Если вы не используете ключевое слово var для определения своих переменных, все становится свойством объекта window. Таким образом, ваш код будет эквивалентен следующему:

window.myVar=0;

function runMe(){
    window.myVar = 10;
    window.callMe();
}

function callMe(){
   window.addMe = window.myVar+10;
}

Если вы помните об этом, всегда должно быть ясно, что происходит.

Ответ 5

Насколько я понимаю, любая переменная без ключевого слова var рассматривается глобально, с ее локальным областью, поэтому:

// This is a local scoped variable.
var local_var = "something"; 

// This is a global scoped variable.
global_var = "something_else";

Как хорошая практика JS, рекомендуется ВСЕГДА добавить ключевое слово var.

Ответ 6

Я хотел бы добавить, что лямбда-выражения также статически охвачены местоположением, в котором определено выражение. Например,

var myVar = 0;

function foo() {
    var myVar = 10;
    return { bar: function() { addMe = myVar + 10; }}
}

var myObj = foo();

var addMe = 6;
alert(addMe);

myVar = 42;
myObj.bar();

alert(addMe);

Это отобразит 6 и 20.

Ответ 7

myVar=0;

function runMe(){
    myVar = 10;
    callMe();
}

function callMe(){
   addMe = myVar+10;
}

Что касается вывода, то myVar и addMe будут в этом случае глобальными переменными, как в javascript, если вы не объявляете переменную с var, то она неявно объявляет ее глобально, когда вы вызываете runMe(), тогда myVar будет иметь значение 10, а addMe - 20.