我的情况下函数声明和函数表达式之间的区别

时间:2018-11-14 15:59:48

标签: javascript function ecmascript-6

有人请解释这里发生的事情。

 var y = 1;
 if (function f(){return 'some text';}) {
     y += typeof f;
 }
 console.log(y);// "1undefined"

如果我将其更改为函数表达式

 var y = 1;
 if (a = function f(){return 'some text';}) {
     y += typeof a;
 }
 console.log(y);// "1function"

4 个答案:

答案 0 :(得分:4)

if语句的条件始终是一个表达式。在第二种情况下,它是一个将全局(!)变量a设置为函数的赋值表达式,在第一种情况下,它只是一个函数表达式,该函数无处可去(不存储在任何地方)。 f只是函数本身内部 函数的名称(用于递归)。因此,f不在其外部定义。

答案 1 :(得分:2)

函数声明会在当前作用域中创建一个具有相同名称的变量。

function a() {
    function b() {
    }
}

在上面的示例中,在b范围内创建了变量a


函数表达式会在自己的作用域中创建一个具有相同名称的变量。

function a() {
    (function b() {
    })
}

在上面的示例中,在b范围内创建了变量b,但没有在a范围内创建。


在您的第一个示例(一个以命名的函数表达式)中,f在函数外部不存在,因此它是undefined

在第二个示例(也是一个以命名的函数express )中,您正在将函数显式分配给a(隐式全局),以便对其进行定义。

尽管有您的问题标题,但您的示例均未提供函数声明。将function关键字放在if ()条件内,使其成为表达式,就像将其放在=的RHS上一样。

答案 2 :(得分:0)

区别在于,第一个示例展示了函数表达式作为if语句的条件表达式。根据{{​​3}}(粗体强调类),函数表达式在封闭范围内不产生命名实体:

  

注意2

     可以从 FunctionExpression FunctionBody 内部引用 FunctionExpression 中的 BindingIdentifier 递归地调用自己。 但是;与 FunctionDeclaration 中的不同, FunctionExpression 中的 BindingIdentifier 不能被引用,并且不会影响包围 FunctionExpression 。

之所以将其解释为 FunctionExpression 而不是 FunctionDeclaration 的原因是,它是根据if语句的条件表达式给出的,如ECMA-262 [2015] §14.1.20

  

运行时语义:评估

     

IfStatement :如果( Expression Statement else < / strong> 声明

您的第二个示例之所以有效,是因为if条件表达式是赋值表达式,其求值将function expression(即函数对象)的结果赋给变量a已经在封闭范围中声明了。

此处提供的参考文献是ECMAScript 2015,但在规范的早期版本中给出了几乎相同的规定。

答案 3 :(得分:0)

看下面的例子:

// function declaration
function A() { return 'AAAA'; }
console.log('A: ', typeof A); // A: function

// mixing function declaration and expression - wrong way 
b = function B() { return 'BBBB'; };
console.log('b: ', typeof b); // b: function
console.log('B: ', typeof B); // B: undefined
// Why?
// 'B' is declared inside an expression and 'dies' after the expression
// ends, i.e. after b get assigned the right side of '='
// 'b', on the other side, got the function assigned and lives
// further on the scope.

// function declaration - right way
b2 = function() { return 'BBBB'; };
console.log('b2: ', typeof b2); // b2: function

// declaring the function inside the 'if' expression... same as with B
if(function C() { return 'C';}) {
	console.log('C (in): ', typeof C); // undefined
}
console.log('C: (out)', typeof C); // undefined
// ... it's the same as in here:
x = (function D() { return 'D';});
console.log('x: ', typeof x); // function
console.log('D: ', typeof D); // undefined

// assigning a variable (same as with 'B' example)
if(z = function Z() { return 'Z'; }) {
	console.log('z: ', typeof z); // function
  console.log('Z: ', typeof Z); // undefined
}
// ... and the same as with Z
y = (z2 = function Z2() { return 'Z2'; });
console.log('y: ', typeof y); // function
console.log('z2: ', typeof z2); // function
console.log('Z2: ', typeof Z2); // undefined