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


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

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

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

4 12

4 ответа:

Итак, технически [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 не определен