Что происходит в фоновом режиме с этим JavaScript? - PullRequest
1 голос
/ 20 января 2010

Я просматривал некоторые сегодня, когда столкнулся со следующим соглашением:

TestParam(1);

function TestParam(p){
    var p = p + 1;
    alert(p);   // alerts '2'
}

Теперь, очевидно, разработчик не имел в виду delcare 'p' внутри функции, вместо этого возможно имел в виду:

    p = p + 1;

Но код все еще работал, то есть значение, о котором сообщалось, было «2». Так что это заставило меня задуматься. Что произойдет в следующем сценарии:

var a = 1;
TestParam(a);
alert(a);  // alerts "1"

function TestParam(p){
    var p = p + 1;
    alert(p);   // alerts '2'
}

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

var a = { b: 1 };
TestParam(a);
alert(a.b);  //alerts 1

function TestParam(p) {
    var p = {b:p.b + 1};
    alert(p.b); //alerts 2
}

Таким образом, в этом случае JavaScript «запомнил» переменную a, даже если она передается в TestParam как p, p повторно объявлено.

Теперь, если бы я сделал следующее в рамках функции, тогда оба оповещения были бы "2"

    p.b++;
    //var p = {b:p.b + 1};

т.е. это изменило бы член b исходного объекта. Я понял это. Это предыдущий сценарий, который ставит меня в тупик!

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

Есть мысли?

Ответы [ 3 ]

5 голосов
/ 20 января 2010

Переменные ограничены функцией включения в JavaScript.И вы можете объявлять их столько раз, сколько захотите.

Объекты не связаны с переменными;многие переменные могут ссылаться на один и тот же объект.(Это иногда называется aliasing .) Это то, что происходит в вашем последнем примере.JavaScript не «запомнил» переменную a;скорее, p и a относятся к одному и тому же объекту, поэтому, когда он изменяется с помощью p, вы можете увидеть эти изменения с помощью a.

Вот пример, который может иметь больше смысла длявы.Иногда у человека несколько идентичностей.

var Clark = new Person;
var Superman = Clark;  // Maybe not everybody needs to know these two are
                       // the same person, but they are.
Clark.eyes = "brown";
alert(Superman.eyes);  // should be brown, right?

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

1 голос
/ 20 января 2010

Я полагаю, что в вашем коде есть опечатка.Я думаю, вы имеете в виду:

function TestParam(p) {
    var p = {b:p.b + 1}; // p.b, not p.a (p.a == undefined)
    alert(p.b);
}

В вашем примере:

var a = { b: 1 }; // "a" is defined in the global scope
TestParam(a);
alert(a.b);  // alerts 1

function TestParam(p) {
    var p = {b:p.a + 1}; // "p" is defined in TestParam()'s scope
    /* But not until after the expression on the right side of the assignment
       has completed--that's why you can use p.a 
    alert(p.a); //alerts 2
}

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

var a = { b: 1 };
alert(a.b); // Alerts 1
TestParam(a);
alert(a.b); // Alerts 2
TestParam(a);
alert(a.b); // Alerts 3

function TestParam(p) {
    p.b++;
}
1 голос
/ 20 января 2010

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

...