2012-06-10 1 views
4

Я пытаюсь создать класс без прототипов. Вот пример:`this` внутри функции, которая не является прототипом класса

test = (function() { 
    this.value = 1; 
    this.print = function() { 
    console.log(this.value); 
    }; 
    return this; 
})(); 

Это прекрасно работает по назначению. То, что я не понимаю, это this.value внутри функции this.print. Как this.print правильно знать, что любые ссылки на this ссылаются на test, а не window? Любая функция, определенная через this.___ = function(){}, автоматически добавит this в качестве контекста?

+1

[Частные члены в JavaScript] (http://javascript.crockford.com/private.html) - читайте это. – dirkgently

+1

для тех, кто использует coffeescript как я, вы можете «закрыть эту' переменную », как в http://stackoverflow.com/a/10965498/927092, используя' => 'вместо' -> 'в вашей функции –

ответ

11

thisвсегда оценивает на объект при котором функция-объект был вызван. Он будет оцениваться до window, если он был «вызван ничем» (или является собственностью window).

(Обратите внимание, что thisне переменной и, таким образом, не закрытыми над в затворе! Вот почему иногда закрытия необходимы, чтобы получить «правильный» this, который часто называют переменной self или that или _this)

. Например:

function f() { return this; } 
var a = {f: f} 
var b = {f: f} 
a.f() === a  // true 
b.f() === b  // true 
f() === window // true 

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

test = (function() { 
    var self = this // <-- variable, which is "closed over" 
    this.value = 1; // self === this 
    this.print = function() { 
    console.log(self.value); // <-- self "names" previous this object 
    }; 
    return this; 
})(); 

Это немного ложь. Функции Function.call и Function.apply позволяют указать контекст this и могут использоваться функциями «связывания контекста», такими как Function.bind, для устранения необходимости в явном «закрытии», как показано выше.

+0

Так что я написал это, если я сделал '_print = test.print; _print()', он все равно правильно напечатает '1', потому что я определил его внутри замыкания. Это правильно? –

+1

Нет, внутри * что '' _print' invocation 'this' оценивается как' window', поэтому он будет 'window.value'.' this' является * not * переменной и, таким образом, * не * закрыт в закрытии. Использование 'test. print() 'будет' '' '' '' 'оценивать' test' и, следовательно, использовать 'test.value', что и ожидалось. –

+0

Таким образом, нет никакой пользы для выполнения' test = (function() {...})() ; 'vs.' test = {значение: 1, print: ...} 'В любом случае мне придется префикс функции с помощью' test'. –

Смежные вопросы