2015-01-20 5 views
4

Я новичок в мире JavaScript. Сегодня во время работы с JavaScript я нашел следующий фрагмент кода:Как работают вложенные функции JavaScript?

function sum (a) { 
    var sum = a; 

    function f (b) { 
     sum += b; 

     return f; 
    } 

    f.toString = function() { 
     return sum; 
    } 

    return f 
} 

//Calling the function 
console.log(sum(4)(5)); 

Можете ли вы помочь мне понять, когда f.toString выполняется?

+6

Здесь: 'console.log (сумма (4) (5));'. 'console.log' вызывает метод' toString' для функций, по крайней мере, в Chrome. –

+0

Отступы помогут. –

+1

В вашем примере код f.toString() - это функция, которая никогда не выполняется. – bhspencer

ответ

4

Когда вы передаете объект в console.log(), он вызывает .toString(), чтобы распечатать значение.

Таким образом,

sum(4) 

возвращает функцию. Последующий вызов этой функции

sum(4)(5) 

также возвращает функцию. Затем, передаваемая в console.log(), и результат в консоли

9 

Следует отметить, что console API является довольно шатким квази-стандарт, и потому, что он разработан в целях отладки помощи существуют некоторые виды поведения, которые могут быть запутанным. В этом случае, однако, кажется, просто назовите .toString() без каких-либо других «полезных» смешных дел. Если, однако, вы просто передать простой пустой объект console.log(), как этот

console.log({}) 

вы получите (по крайней мере, с Firebug в Firefox) полезный интерфейс для навигации объекта. Это здорово, если вы что-то отлаживаете, но если вы пытаетесь понять, как работает язык, это поведение может ввести в заблуждение.

В заключительной ноте, трюк в публикуемом коде может быть расширен таким образом, что функция может разгласить числовой результат тоже, добавив .valueOf() метод:

function sum (a) { 
    var sum = a; 

    function f (b) { 
     sum += b; 

     return f; 
    } 

    f.toString = function() { 
     return sum; 
    }; 
    f.valueOf = function() { 
     return sum; 
    }; 

    return f; 
} 

Если вы сделаете это, то вы получите Правильный ответ от

console.log(2 * sum(4)(5)) 
+1

Если это так, 'console.log ({})' будет печатать '" [object Object] "'. –

+1

@FelixKling нет, потому что возвращенная функция явно указала метод '.toString()' в отправленном коде. * Редактировать * О, извините; как я отметил в поправке к ответу, вы не можете доверять 'console.log()', чтобы сделать что-то простое. – Pointy

+0

Итак, здесь функция 'toString' заменяется пользовательской функцией. И 'console.log' вызывает эту настраиваемую функцию, поскольку она внутренне подключена для вызова функции' toString'? Это верно? – surajck

3

Когда sum(4)(5) выполняется, sum(4) выполняется первым, который возвращает функцию f.

Эта функция имеет доступ к переменной sum (из-за свойства закрытия функций JavaScript [1]). Эта функция суммирует и снова возвращает функцию f.

На этот раз console.log пытается напечатать функцию f и, следовательно, мы явно определяем, как следует печатать функцию, определяя f.toString для печати суммы.

Edit: Если вам интересно, зачем так много боли, чтобы просто добавить два числа, то попробуйте следующее:

add(2)(1)(45)(22) 

Это работает, потому что теперь f рекурсивно вызывается и sum обновляется, снова из-за свойство закрытия.

1: Внутренние функции имеют доступ к переменной родительской функции даже после того, как родительская функция вышла из области видимости.