命名函数优先于JavaScript中的匿名函数吗?

Bil*_*eal 51 javascript

可能重复:
JavaScript:var functionName = function(){} vs function functionName(){}

在Javascript中提取函数有两种可能的方法:

var foo = function() { ... }
Run Code Online (Sandbox Code Playgroud)

这有点人为; 另一个常见的模式是:

var foo = {
   baz: 43,
   doSomething: function() {
       // ...
   }
}
Run Code Online (Sandbox Code Playgroud)

function foo() { 
  // ... 
}
Run Code Online (Sandbox Code Playgroud)

是否有明确的理由偏好一个或另一个?

Tre*_*vor 78

这一切都归结为你声明你的功能的地方; 吊装.

函数声明和变量声明总是被JavaScript解释器无形地移动("提升")到其包含范围的顶部.显然,功能参数和语言定义的名称已经存在.这意味着代码如下:

function foo() {
    bar();
    var x = 1;
}
Run Code Online (Sandbox Code Playgroud)

实际上解释如下:

function foo() {
    var x;
    bar();
    x = 1;
}
Run Code Online (Sandbox Code Playgroud)

请注意,声明的赋值部分未被提升.只有名字被悬挂.函数声明不是这种情况,整个函数体也将被提升.

function test() {
    foo(); // TypeError "foo is not a function"
    bar(); // "this will run!"
    var foo = function () { // function expression assigned to local variable 'foo'
        alert("this won't run!");
    }
    function bar() { // function declaration, given the name 'bar'
        alert("this will run!");
    }
}
test();
Run Code Online (Sandbox Code Playgroud)

在这种情况下,只有函数声明将其主体提升到顶部.名称'foo'被悬挂,但身体被遗忘,在执行期间被分配.

您可以为函数表达式中定义的函数指定名称,其语法类似于函数声明.这不会使它成为一个函数声明,并且名称不会被带入范围,也不会被提升.

foo(); // TypeError "foo is not a function"
bar(); // valid
baz(); // TypeError "baz is not a function"
bin(); // ReferenceError "bin is not defined"

var foo = function () {}; // anonymous function expression ('foo' gets hoisted)
function bar() {}; // function declaration ('bar' and the function body get hoisted)
var baz = function bin() {}; // named function expression (only 'baz' gets hoisted)

foo(); // valid
bar(); // valid
baz(); // valid
bin(); // ReferenceError "bin is not defined"
Run Code Online (Sandbox Code Playgroud)

因此,如果您希望将功能提升到顶部,请使用function declaration其他方式expression.我更喜欢后者,因为我通常使用方法构建对象文字function expressions.

function expressions抛出错误时,命名可以很方便.控制台会告诉你该函数是不是说明什么anonymous又名堆栈跟踪.

  • 请记住,块中的函数声明[技术上无效](http://stackoverflow.com/questions/4071292/may-function-declarations-appear-inside-statements-in-javascript),因此可能首选使用函数表达式然后. (4认同)
  • 这是一个经常被遗忘的重要区别:“命名函数表达式在引发错误时会很方便。控制台会告诉您该函数是什么,而不是声明匿名(又名堆栈跟踪)。” (2认同)

rtp*_*tpg 11

你在这里遇到了几件不同的事情,但我会先尝试解决你的主要问题.

一般来说....

function() { ... }是一个函数表达式.语法上,这与2or 处于同一级别[4,5].这代表一个价值.这样做var foo=function(){ ... }每次都会按计划进行.

function foo() { ... } 是一个函数声明.这可能看起来像做同样的事情var foo=function(){...},但有一个小警告.作为一个声明,它的工作方式类似于JS中的变量提升概念(基本上,所有变量声明都是在计算任何表达式之前完成的).

一个很好的例子来自这里:

function test() {
    foo(); // TypeError "foo is not a function"
    bar(); // "this will run!"
    var foo = function () { // function expression assigned to local variable 'foo'
        alert("this won't run!");
    }
    function bar() { // function declaration, given the name 'bar'
        alert("this will run!");
    }
}
test();
Run Code Online (Sandbox Code Playgroud)

基本上可变的提升使得价值达到顶峰,因此这段代码(理论上)与以下内容相同:

function test() {
    var foo;//foo hoisted to top
    var bar=function(){//this as well
        alert("this will run!");
    }

    foo(); // TypeError "foo is not a function"
    bar(); // "this will run!"
    var foo = function () { // function expression assigned to local variable 'foo'
        alert("this won't run!");
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:我想利用这个位置说JS解释器很难遵循理论,因此不建议相信他们有些不确定的行为.在这里你会发现一个很好的例子,在理论和实践最终不起作用的部分的末尾(关于表达式与声明的主题还有一些更多的细节).

有趣的事实:function foo() {...}用括号括起来将它从一个声明转换为一个表达式,这可能会导致一些奇怪的代码

(function foo() { return 1; })();// 1
foo; //ReferenceError: foo is not defined
Run Code Online (Sandbox Code Playgroud)

如果你没有理由请不要这样做.


总结 var foo=function(){ ... }是*sorta有点*与函数相同,foo(){ ... }除了前者做你认为它应该在你认为应该做的事情,而后者做奇怪的东西,除非你把它包在parens中,但这会弄乱范围,JS解释器允许你做一些在规范中被认为是语法错误的事情,这样你就会被认为错误的事情实际上是对的,等等....

请使用函数表达式(var f=function(){...}).没有真正的理由不这样做,特别是考虑到你在使用点语法时有点被迫这样做.


到了你触及的第二件事.....

我真的不知道该说些什么,这是有点八九不离十完全从一切有关此不同.

var foo = {
    baz: 43,
    doSomething:function() {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这称为对象文字语法.基于这种语法的JSON是一种非常简洁的数据格式化方法,JS中的这种语法通常用于声明新对象,例如单例对象(避免声明函数和使用new的所有混乱) .它也可以像使用XML一样使用,并且是所有酷孩子的首选......

无论如何,基本上对象文字语法的工作原理如下:

{ name1: val1, .... namek:valk }
Run Code Online (Sandbox Code Playgroud)

此表达式是一个在其上初始化某些值的对象.这样做var obj={ name1: val1, .... namek:valk }意味着:

obj.name1==val1;
obj['name1']==val1;// x['y'] is the same thing as x.y 
...
obj.namek==valk;
Run Code Online (Sandbox Code Playgroud)

那么这与我们的例子有什么关系呢?基本上,您的表达式通常用于声明单例对象.但是它也可以用来声明一个对象原型,所以有人以后可以做var newObj = Object.create(foo),而newObj将foo作为原型.

如果你想真正了解它的实用性,请详细研究原型继承.道格拉斯Crockford的关于它在会谈中详细一个他的许多谈判).


归档时间:

查看次数:

27346 次

最近记录:

6 年,8 月 前