У меня есть этот код:
var foo = {
x: 2,
bar: function() {
alert(this.x);
}
};
Почему foo.bar()
alert 2
в то время как [foo.bar][0]()
предупреждает undefined
?
У меня есть этот код:
var foo = {
x: 2,
bar: function() {
alert(this.x);
}
};
Почему foo.bar()
alert 2
в то время как [foo.bar][0]()
предупреждает undefined
?
Итак, технически [foo.bar][0]
эквивалентно foo.bar
, но в момент вызова функция bar
потеряла "лексическую привязку" с объектом foo
, поэтому, когда вы ее вызываете, JavaScript фактически выполняет следующее:
foo.bar.call([foo.bar]);
Как правило, это выражение:
XXX.yyy(args)
интерпретируется как:
XXX.yyy.call(XXX, args);
В этом случае XXX
есть [foo.bar]
, а .yyy
- [0]
.
Чтобы исправить это, вам нужно явно привязать foo
еще раз:
[foo.bar][0].call(foo);
когда вы выполняете [foo.bar][0]()
, this
в bar
есть [foo.bar]
, массив, но не объект foo
.
Простое изображение, что имя метода - это число 0
(хотя это неправильный синтаксис).
([foo.bar]).0(); // you see, `this` became the array object: [foo.bar]
И [foo.bar].x
- undefined
.
Это потому, что вы вызываете функцию в объекте массива. Ключевое слово "this" равно массиву.
[foo.bar][0]();
В javascript контекст, в котором вызывается функция, может отличаться. Ключевое слово "this" может иметь разные значения в зависимости от того, как он был вызван. Если функция вызывает объект (включая массивы), язык сделает "this" равным объекту, на который он был вызван. С другой стороны, вы можете сохранить функцию другого объекта в другую переменную и вызвать ее. Как вы это сделали:
var test=[foo.bar][0];
test();`//here is alert "2"
и контекст будет окном.
Изучите вызов и примените методы в javascript. Это откроет вам глаза на то, насколько гибким является ключевое слово "this". Это место много путаницы среди многих программистов, поступающих с других языков, но как только этот принцип понимается, есть много энергии, которая исходит от него. Например, JQuery использует "call" и "apply", чтобы иметь обратные вызовы событий, вызванных в контексте элемента, в котором было запущено событие.
Это потому что, когда вы создаете массив [foo.bar]
, который вы изолируете его от основного объекта (foo), а в вашей функции вы предупреждаете this.x
и во вновь созданном объекте [foo.bar] this
есть undefined