Подтвердить что ты не робот

Доступ к открытой переменной 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?

Если частная функция не может получить доступ к общедоступной переменной, как я могу ее сделать?

Спасибо заранее!

4b9b3361

Ответ 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";
    }
}

И есть другой способ решить эту проблему, проверьте другие ответы:)