Доступ к открытой переменной javascript
У меня есть этот класс:
function ctest() {
this.var1 = "haha";
this.func1 = function() {
alert(this.var1);
func2();
alert(this.var1);
}
var func2 = function() {
this.var1 = "huhu";
}
}
и назовите его:
var myobj = new ctest();
myobj.func1();
не предполагается, что второе предупреждение появится всплывающее окно "huhu"? func2 является закрытым, не может ли он получить доступ к переменной public var1?
Если частная функция не может получить доступ к общедоступной переменной, как я могу ее сделать?
Спасибо заранее!
Ответы
Ответ 1
Вам необходимо предоставить контекст для вызова func2
:
this.func1 = function() {
alert(this.var1);
func2.call(this);
alert(this.var1);
}
Без контекста вызов будет использовать глобальный объект (т.е. window
) - вы должны увидеть, когда вы запускаете свой текущий код, который создается window.var1
между двумя предупреждениями.
Ответ 2
Функции не привязаны к экземплярам, поэтому ваш вызов func2
заканчивается как вызов без this
, указывающий на ожидаемый экземпляр.
Вы можете либо исправить вызов, чтобы включить контекст:
function ctest() {
this.var1 = "haha";
this.func1 = function() {
alert(this.var1);
func2.call(this);
alert(this.var1);
}
var func2 = function() {
this.var1 = "huhu";
}
}
Или вы можете сохранить переменную с требуемой ссылкой на объект:
function ctest() {
var that = this;
this.var1 = "haha";
this.func1 = function() {
alert(this.var1);
func2();
alert(this.var1);
}
var func2 = function() {
that.var1 = "huhu";
}
}
Ответ 3
Другой вариант - использовать Function.bind
:
function ctest() {
this.var1 = "haha";
this.func1 = function() {
alert(this.var1);
func2();
alert(this.var1);
}
var func2 = function() {
this.var1 = "huhu";
}.bind(this);
}
Обратите внимание, что поддержка браузера для этого не идеальна.
Ответ 4
В JS нет такой вещи, как private, но вы можете играть с областями с помощью closures.
Скажем, например, что в вашем примере вам не нужно раскрывать var1
как общедоступное свойство. Вы можете легко переписать свой код следующим образом:
function ctest() {
var var1 = "haha";
this.func1 = function() {
alert(var1);
func2();
alert(var1);
}
var func2 = function() {
var1 = "huhu";
}
}
Поскольку оба func1
и func2
используют одну и ту же область видимости - они определены в одной и той же функции, ctest
- они могут обращаться к тем же переменным. Конечно, в этом случае у вас нет var1
, поэтому: myobj.var1
будет undefined
.
Если вы хотите, чтобы var1
отображался как свойство, то вам нужно bind func2
к экземпляру объекта, который вы созданный в конструкторе:
function ctest() {
this.var1 = "haha";
this.func1 = function() {
alert(this.var1);
func2();
alert(this.var1);
}
var func2 = function() {
this.var1 = "huhu";
}.bind(this);
}
В противном случае func2
будет иметь другой объект контекста (this
). Если браузер не поддерживает bind
, и вы не хотите использовать прокладку (как показано в ссылке выше), вы можете снова воспользоваться преимуществами закрытия:
function ctest() {
this.var1 = "haha";
this.func1 = function() {
alert(this.var1);
func2();
alert(this.var1);
}
var context = this;
var func2 = function() {
context.var1 = "huhu";
}
}
IMVHO менее изящный.
Ответ 5
function ctest() {
this.var1 = "haha";
this.func1 = function() {
alert(this.var1);
func2(this);
alert(this.var1);
}
var func2 = function(obj) {
obj.var1 = "huhu";
}
}
И есть другой способ решить эту проблему, проверьте другие ответы:)