JavaScript теряет ссылку на объект this с закрытыми / открытыми свойствами - PullRequest
0 голосов
/ 24 июля 2010

У меня следующая ошибка при запуске страницы ниже:

"this.testpublic не является функцией"


test = function() {
        var testprivate = function() {
                this.testpublic();
        }

        this.testpublic = function() {
                console.log('test');
        }

        testprivate();
}
new test();

Очевидно, когда вызывается testprivate, «this» начинает указывать на «окно» вместо объекта.

Разве JavaScript не должен сохранять контекст "this" в том же объекте?

Ответы [ 4 ]

2 голосов
/ 24 июля 2010

Проблема в том, что this фактически никогда не имел в виду объект test для начала. Он всегда имел в виду ближайший вмещающий объект - в данном случае это window.

test = function() {
        var testprivate = function(say) {
                console.log('test', say);
        }

        this.testpublic = function(say) {
                testprivate('test', say);
        }

        testprivate();
}
x = new test();

Это работает, потому что, насколько я понимаю, this определяется в вызов времени - и оно заблокировано в ближайшем "вмещающем" объекте *, если call() или apply() б.

* Вероятно, есть намного лучшее слово для этого, но я не знаю его по макушке. Если кто-то знает, пожалуйста, просветите нас всех: -)

2 голосов
/ 24 июля 2010

Вам нужно манипулировать контекстом при вызове testprivate. Вы можете использовать function.call для переопределения области действия функции. Попробуйте это:

test = function() {
        var testprivate = function() {
                this.testpublic();
        }

        this.testpublic = function() {
                console.log('test');
        }

        testprivate.call(this);
}
new test();
1 голос
/ 24 июля 2010

Нет, не должно. Функция просто определяет область действия.

Когда вы звоните foo.bar(), тогда this (внутри bar()) равно foo. Поскольку в этом случае нет явного foo, по умолчанию это window.

(this обрабатывается по-разному, когда ключевое слово new находится в игре, но не для этого вызова)

0 голосов
/ 24 июля 2010

Это, как говорит Шон: вы на самом деле не создаете новую ссылку на объект (создаете контекст this ), потому что вы просто вызываете конструктор, а не используете конструктор для создания новогообъект.Если вы используете ключевое слово new , оно работает просто превосходно.

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

Используя ключевое слово new , вы выделяете новый объект в память и создаете новую область.

Например, попробуйте это в firebug:

var myFunction = function() {
    this.memberVariable = "foo";
    console.log(this);
}
myFunction();
console.log(window.memberVariable);
var myObject = new myFunction();
console.log(myObject.memberVariable);

Вы увидите этот результат:

Window stats
foo
Object { memberVariable="foo"}
foo

Базовый объект Function имеет метод call () , который, как обрисовал в общих чертах Крейг, позволяет вам явно указыватьв какой области должна запускаться функция:

var myFunction = function() {
    this.memberVariable = "foo";
}
myFunction.call(myFunction);
console.log(myFunction); // "Function()"
console.log(myFunction.memberVariable); // "foo"

Это, однако, не самый предпочтительный способ работы, так как вы на самом деле не создаете новый объект здесь, а typeof myFunction по-прежнему будет возвращать функцию"вместо" объект "- когда вы действительно просто хотели создать объект.

...