Что происходит с переменными "var" внутри JavaScript-конструктора?

Пример:

function Foo() {
    this.bla = 1;
    var blabla = 10;
    blablabla = 100;
    this.getBlabla = function () { 
        return blabla; // exposes blabla outside
    }
}

foo = new Foo();

оригинальный вопрос:

Я знаю, что bla будет назначаться каждому экземпляру Foo. Что будет с blabla?

новый вопрос:

что я понимаю сейчас:

this.bla = 1;     // will become an attribute of every instance of FOO.
var blabla = 10;  // will become a local variable of Foo(**not** an attribute of every    instance of FOO), which could be accessed by any instance of FOO only if there a method like "this.getBlabla".
blablabla = 100;  // will define a **new** (or change if exist) global(window) variable.

                     Did i understand correctly?

Ответ 1

Любые внутренние методы, которые вы передаете this - то есть: this.method = function () {}; , в то время как внутри вашей функции конструктора Foo, все будут иметь ссылку на blahblah, который уникален для каждого экземпляра объекта Foo.

function Wallet () {
    var balance = 0;
    this.checkBalance = function () { return balance; };
    this.depositAmount = function (amount) { balance += amount; };
}


var wallet = new Wallet();
wallet.checkBalance();   // 0
wallet.depositAmount(3);
wallet.checkBalance();   // 3

Но он полностью защищен от доступа за пределами кошелька, если вы не вернете его кому-либо из привилегированной функции.

wallet.balance; // undefined;

(добавленный бит интереса - если balance является string, a number или boolean, даже если вы его вернете, это не даст людям прав на редактирование или даже постоянный просмотр access - скалярные переменные передаются по значению, поэтому вы просто передаете значение баланса в момент - если, однако, баланс был object, a function или array, у них будет постоянный доступ, чтобы изменить дерьмо из вашей внутренней работы)

Примечание. Для работы в конструкторе для конструктора должно быть назначено HAVE. Прототипы не могут получить доступ к внутренним переменным. Добавление методов позже не даст им доступа к внутренним переменным.

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

Ответ 2

В вашем примере blabla - это локальная переменная, поэтому она исчезнет при завершении функции конструктора.

Если вы объявляете функцию внутри конструктора, которая использует переменную, то эта переменная будет частью замыкания для этой функции и сохраняется до тех пор, пока функция (т.е. обычно до тех пор, пока объект):

function Foo() {
  this.bla = 1;
  var blabla = 10;

  this.getBlabla = function() {
    alert(blabla); // still here
  }
}

Ответ 3

Он станет локальной (подумайте о 'private') переменной в Foo(). Это означает, что вы не можете получить доступ к нему за пределами Foo().

function Foo() {
  this.bla = 1; // this becomes an extension of Foo()
  var blabla = 10; // this becomes a "Local" (sort of like a 'private') variable
}

Вы можете открыть его (путем его возврата) с помощью метода Foo.

function Foo() {
    var blabla = 10; // local

    this.getBlabla = function () { 
        return blabla; // exposes blabla outside
    }
}

Теперь вне Foo():

var FooBar = new Foo();

var what_is_blabla = FooBar.getBlabla(); //what_is_blabla will be 10

демонстрация jsFiddle

Ответ 4

Эта переменная является локальной для конструктора и не будет доступна за пределами этой области (будь то через this или иначе), если только она не будет захвачена закрытием.

Ответ 5

Переменные, объявленные с помощью var внутри функции, используемой в качестве конструктора, будут, как и все другие переменные, объявленные с помощью var внутри любой функции, видны только во время выполнения этой функции (если значение не будет закрыто с использованием закрытий).

Другими словами, blabla эффективно невидимо вне функции:

var foo = new Foo();
console.log(foo.bla);     // 1
console.log(foo.blabla);  // throws NameError

Определяя функции, которые закрываются над этими переменными, они становятся наиболее близкими к тем, что JavaScript должен иметь переменные "private":

function Foo() {
    this.bla = 1;
    var private = 1;

    this.increment = function() {
        ++private;
    }

    this.getPrivateValue = function() {
        return private;
    }
}

foo = new Foo();
console.log(foo.bla);                // 1
foo.bla = 6;                         // legal
console.log(foo.bla);                // 6
console.log(foo.getPrivateValue());  // 1
// console.log(foo.private);         // would throw an error
foo.increment();                     // legal
console.log(foo.getPrivateValue());  // 2
// foo.getPrivateValue() = 5;        // syntax error. Still can't reassign to private no matter what you try!

Ответ 6

Если вы не используете ключевое слово var, "blabla" становится глобальной переменной. В других точках кода, если вы также используете blabla без var, он также будет глобальным, и вы можете случайно изменить другие экземпляры blabla и ввести непреднамеренные ошибки в вашем коде. "var" помещает переменную в текущую область действия, поэтому в приведенном выше случае она доступна только для Foo.

Ответ 7

blabla можно почти считать частным членом Foo.

См. эту статью от Дугласа Крокфорда.