2012-02-01 5 views
3

Посмотрите на этот фрагмент:Javascript: obj.fn() против х = obj.fn; х()

var obj = { 
    fn: function() {return this;} 
}; 
var x = obj.fn;  

obj.fn(); // returns obj 
x(); // returns window (in the browser) 

Мне интересно, почему obj.fn() отличается от x=obj.fn; x(). Есть ли специальный случай для поиска атрибутов, за которым следует вызов функции в пределах одного выражения - или происходит какое-то более сложное волшебство под капотом (например, с descriptor protocol в Python)?

ответ

6

Значение переменной this всегда зависит от того, как была вызвана функция.

obj.fn(); 

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

Непосредственно сохранением ссылки в x функция называется «так же, как, что» в глобальном масштабе, что означает, что он всегда будет ссылаться на global object в не в режиме среде ES5-строгим, и это будет в ES5 строгого режима undefined.

Итак, вы всегда должны быть осторожны при обращении к методам объектов в переменных. Если такой метод хочет получить доступ к некоторым данным из своего собственного объекта через this.someProp, он, очевидно, потерпит неудачу, если this привязан к другому объекту/контексту.


Отказ от ответственности: «всегда будет ссылаться на объект, содержащий» не совсем корректно. Если функция была привязана к другому объекту через Function.prototype.bind(), она будет всегда ссылается на связанный объект.

+0

Соответствующий раздел спецификации ES5: http://ecma262-5.com/ELS5_HTML.htm#Section_11.2.3 –

+0

@Tim Down: Спасибо, я сам этого не нашел. К сожалению, читаемость этой спецификации имеет ... ekhm .. сомнительное качество :) Во всяком случае, это позор, что состав поиска свойств и оператора вызова дает разные результаты, чем использование их отдельно. –