2015-04-13 2 views
1

Что такое пример/сценарий того, как ключевое слово this может потерять свою явную привязку и быть переплетено с привязкой по умолчанию? Вот пример фрагмента кода, который явно связывает ключевое слово this с объектом с помощью метода call. Какие теоретические дополнения к этому коду могут изменить значение this? Какие конкретные проблемы мы защищаем наш код, когда жестко привязываем ключевое слово this?Потеря явного связывания ключевого слова `this`

function foo(){ 
    console.log(this.bar); // outputs: 9 
} 

var obj = { 
    bar: 9 
}; 

foo.call(obj); 
+1

Значение 'this' зависит от * как * функция * называется *. Существует несколько способов вызова функции и, следовательно, несколько способов, как «это» получает свое значение. Все это хорошо объяснено в документации MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this. Функция может быть явно привязана через '.bind()', и в этом случае значение 'this' больше не может быть изменено. –

+0

@FelixKling благодарит, но не совсем то, что я просил. – shmuli

+1

Тогда, я думаю, я не понимаю, о чем вы спрашиваете. –

ответ

2

В целом нет "явного" связывание this. Значение определяется всякий раз, когда функция вызывается в зависимости от характера вызова. Это не имеет никакого отношения к обстоятельствам «рождения» функции.

Когда функция вызывается после того, как его ссылка обнаружен с помощью поиска свойства объекта, например:

obj.someFunction(); 

то ссылка на объект участвует (obj, выше) будет значение this в этом конкретном вызове функции. Однако ссылка функции легко могут быть скопированы на другой объект:

var otherObj = { someFunction: obj.someFunction }; 
otherObj.someFunction(); 

Теперь значение this (в этом конкретном вызове) будет ссылка на otherObj, а не obj.

Если ссылка на функции копируется в обычной переменной:

var func = obj.someFunction; 

func(); 

значение this в , что вызов будет ссылка на window или undefined если код случается в «строгий» контекст.

Через все это, заметим, что тот факт, что функция, возможно, первоначально был объявлен как значение свойства в объекте буквального не имеет ничего к тому, что заканчивает тем, что значение this в вызове.

способ создать явный «привязку», чтобы воспользоваться встроенным в .call() или .apply() методов, доступных для каждого экземпляра функции:

function whatever() { /* ... */ } 

var objWhatever = function() { 
    whatever.call(obj); 
}; 

Это установка явно вынуждает ссылку obj использоваться как значение this в вызове функции whatever(). Вы также можете использовать встроенный (в современных условиях) .bind() функцию, чтобы создать «связанную» функцию такой:

var objWhatever = whatever.bind(obj); 

лично я постеснялся бы назвать это «связанной» функции, потому что под одеялом, это просто явный вызов через .call(), но терминология не то, о чем я беспокоюсь о тоже много. :)

+0

«В общем, нет« явного »связывания этого». Можете ли вы подробнее рассказать об этом? Что вы имеете в виду? – shmuli

+1

@shmuli именно это - в отличие от языков, таких как Java, C++ или C#, нет никакого внутреннего отношения между какой-либо конкретной функцией и любым конкретным объектом. – Pointy

+0

Я предполагаю, что вы говорите, что на самом деле это не «явный», если эти отношения могут быть потеряны. Да? – shmuli

0

As Pointy упомянул значение this, или контекст зависит от того, как эта функция вызывается, эта статья Understanding Scope and Context in Javascript неплохо объясняет, как это работает.

0

Добавление этого кода переопределяет «явное» привязку, а теперь ключевое слово this возвращает 8, что является результатом «неявной» привязки, созданной объектом otherObj. Функция вызывается в пространстве этого объекта.

var otherObj = { 
    foo: foo, 
    bar: 8 
}; 
otherObj.foo(); 

Далее добавьте этот код, и поскольку функция вызывается в глобальном пространстве без каких-либо украшений, то «неявное» связывание переопределяется «по умолчанию» связывания, который возвращает глобальную bar переменную, в результате чего с 7.

var secondObj = otherObj.foo; 
var bar = 7; 
secondObj(); 

Добавление этого кода до того, как функция вызывается с помощью метода call, приведет к блокировке с this ключевое слово на secondObj объекта - и в результате с выходом 6.

var thirdObj = { 
    bar: 6 
}; 

var foo = foo.bind(thirdObj); 
Смежные вопросы