Что происходит с переменными "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
.
См. эту статью от Дугласа Крокфорда.