2015-02-19 4 views
2

Я просто читал книгу «Вы не знаете JS» от kyle simpson и наткнулся на следующий грех-код кода, который несколько смутил меня. в основном я читал тему по ключевому слову this. Ниже приводится фрагмент кода:Косвенные ссылки на функции в javascript

function foo() { 
    console.log(this.a); 
} 

var a = 2; 
var o = { a: 3, foo: foo }; 
var p = { a: 4 }; 
o.foo(); // 3 
(p.foo = o.foo)(); // 2 

До сих пор читает книгу, я понимаю, как это работает, но для меня его трудно понять, Что на самом деле происходит на последней строке сниппета.

Если я проанализирую его по самой последней строке, это iffe, выполняющийся в глобальной области видимости, и если в iffe выполняется fuction() fuction, this.a в функции foo() будет указывать на a в глобальной объем, который действительно равен 2.

Но почему-то я не чувствую, что полностью понимаю, что происходит на последней строке, может кто-то сломать его для меня?

спасибо.

Alexander.

+0

Что именно отсутствует? Значение выражения присваивания - это назначенное значение. –

+3

Кстати, это похоже на * разработанный *, чтобы запутать больше, чем преподавать ... –

+0

Возвращаемое значение присваивания всегда является самим значением. Поэтому два шага выполняются в одной строке. 1. 'p.foo = o.foo;' 2. 'foo();' – Simon

ответ

5

Последняя строка проходит по ссылке на функцию foo, а затем выполняется в глобальной области действия, как вы видите. Это эквивалентно этому

var f = p.foo = o.foo; 
f(); 
+0

, когда я говорю' (p.foo = o.foo)(); // в этом случае p.foo принимает значение o.foo(), и поскольку это iffe, p.foo() должен выполняться в глобальной области и, следовательно, должен печатать 4, я думаю? –

+0

нет, функция не вызывается во время назначения. вы используете функцию как переменную. поэтому после этой операции p.foo и o.foo ссылаются на определенный метод foo() в глобальной области. Назначение фактически не вызывает метод. Присвоения возвращают присвоенное значение, так что вы можете сделать 'c = (a = b)', и все будет равно 'c'. Поскольку назначаемая вещь является функцией foo, это то, что вызывается в конце. –

+0

, если c представляет foo() в примере ur, где в этой строке. '(p.foo = o.foo)(); // Я вызываю foo явно. –

2

Возвращаемое значение присваивания всегда является значением. В этом примере возвращаемое значение является ссылкой на функцию foo. Поэтому два шага выполняются в одной строке.

  1. p.foo = o.foo;
  2. foo();
0

Это случается:

когда (p.foo = o.foo)(); называется, JS превращает его в

function foo() { 
    console.log(this.a); 
} 

и так var a = 2 устанавливается в глобальной scope, и ничего не передается функции, ваш результат равен 2

Итак, возникает вопрос, почему преобразование JS (p.foo = o.foo) в функцию foo()?

хорошо, если вы нарушите его вниз, у вас есть это:

p.foo = o.foo: это присвоение переменной справа налево. Так же, как var a = "something"; так это означает, что теперь, p.foo равно o.foo, а с o.foo равна foo, мы теперь говорят p.foo = foo, другими словами, это: (p.foo = o.foo)(); такое же, как (foo)(), который затем запускает функцию foo.

Для дальнейшего объяснения:

console.log(p.foo); //returns undefined because nothing was set to it 
console.log(o.foo); //returns foo, because it was assigned var o = {foo: foo}; 
p.foo = o.foo; // this assignes foo to p.foo 
console.log(p.foo); //returns foo, it is no longer undefined, because of our assignment 
(p.foo)(); // will run the function 

У меня были проблемы с получением undefined раньше, но это потому, что я бегу тестов на http://jsfiddle.net/, которые помешали мне доступ к моей функции правильно.