Вызов функции из массива javascript

У меня есть этот код:

var foo = {
    x: 2,
    bar: function() {
        alert(this.x);
    }
};

Почему foo.bar() alert 2 в то время как [foo.bar][0]() предупреждает undefined?

Ответ 1

Итак, технически [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);

Ответ 2

когда вы выполняете [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.

Ответ 3

Это потому, что вы вызываете функцию в объекте массива. Ключевое слово "this" равно массиву.

[foo.bar][0](); 

В javascript контекст, в котором вызывается функция, может отличаться. Ключевое слово "this" может иметь разные значения в зависимости от того, как он был вызван. Если функция вызывает объект (включая массивы), язык сделает "this" равным объекту, на который он был вызван. С другой стороны, вы можете сохранить функцию другого объекта в другую переменную и вызвать ее. Как вы это сделали:

var test=[foo.bar][0];
test();`//here is alert "2" 

и контекст будет окном.

Изучите вызов и примените методы в javascript. Это откроет вам глаза на то, насколько гибким является ключевое слово "this". Это место много путаницы среди многих программистов, поступающих с других языков, но как только этот принцип понимается, есть много энергии, которая исходит от него. Например, JQuery использует "call" и "apply", чтобы иметь обратные вызовы событий, вызванных в контексте элемента, в котором было запущено событие.

Ответ 4

Это потому что, когда вы создаете массив [foo.bar], который вы изолируете его от основного объекта (foo), а в вашей функции вы предупреждаете this.x и во вновь созданном объекте [foo.bar] this есть undefined