2015-05-30 2 views
2

С красноречивый Javascript по Marijn HaverbekeПочему определение функции внутри if - это плохая идея?

Различные платформы JavaScript в разных браузерах есть традиционно сделали разные вещи в этой ситуации, и последний стандарт фактически запрещает.

но почему это плохо?

function example() { 
    function a() {} // Okay 
    if (something) { 
     function b() {} // Danger ! 
    } 
} 
+0

Не все браузеры обрабатывают, что точно так же ... –

+0

Не могли бы вы поделиться с нами * как * браузеры отличаются от этого, и, возможно, ссылку на любое конкретное утверждение из стандарта ECMAScript, которое препятствует этому? – Sampson

+0

Я думаю, что его также в значительной степени бессмысленно из-за подъема, функция просто перемещается в начало своей родительской функции и существует независимо от оператора if. Вероятно, это то, что он имеет в виду, когда браузеры обрабатывают его по-разному. http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html –

ответ

3

Это считается «плохим», потому что его поведение непоследовательно и иногда не делает то, что ожидало бы большинство людей. Рассмотрим следующий фрагмент кода:

if (true) { 
    function f() { return "t"; } 
} else { 
    function f() { return "f"; } 
} 

Что бы призывающую f() возвращение? В IE и Firefox он вернет "t", но в Chrome и Safari он вернет "f". Зачем? Сочетание правил подъема и JavaScript. Информацию о том, как это работает, см. В разделе this question on JavaScript scoping and hoisting.

Фактически это означает, что в некоторых браузерах ветвь полностью игнорируется, когда дело доходит до определения функций с использованием формы function name() { ... }. Если вам действительно нужно сделать что-то подобное (и вы, вероятно, этого не сделаете, так как это будет очень плохой стиль), используйте форму name = function() { ... }, так как это не будет поднято, поэтому поведение будет четко определено и будет не должны быть непоследовательными на разных платформах.

+0

Вы уверены, что вернется 'f' ...? –

+0

@ MatíasFidemraizer Он будет на любой платформе JavaScript, которую я видел. Если вы можете указать контрпример, где у него будет другое поведение, я бы, конечно, был бы заинтересован в этом. –

+0

Итак, теперь проверьте, что на jsFiddle ... скопируйте-вставьте код и попробуйте его –

0

Короткий ответ уже дан вам, а именно: такая практика отрицательно влияет на переносимость/совместимость решения между различными браузерами. Что еще хуже: это приводит к добавленной двусмысленности относительно локальных переменных, а именно: какие переменные будут «видимыми» для вложенных функций. Хотя это можно считать допустимой техникой, но это не означает, что такой метод является хорошей практикой. «Код для ясности» - совершенно важная парадигма программирования, поэтому всегда старайтесь избегать практик, которые добавляют к двусмысленности. С уважением,

0

Это стандартизован в ES6 и действителен для объявления функции внутри внутри блоков. Вот specBlock-Level-Function-Declarations

Вы можете попробовать последние браузера со строгом режимом. И причины, почему такое поведение присутствует в старых условиях смотрите здесь: Functions

Смежные вопросы