JavaScript函数声明

27

下面给出的JavaScript代码片段是函数声明吗?如果不是,是否可以有人概述一下它们是什么?

some_func = function(value) {
    // some code here
}

show:function(value){
   // some code here
}
8个回答

72

六种方法/上下文可以创建函数:

1)标准声明符号方法(对于具有 C 背景的人最为熟悉)

function foo() {}

其余的都是函数表达式:

2)作为对象字面量中的一个方法

var obj = {
    foo: function() {}
};

3)作为已实例化对象的方法(每次执行new时创建)

var Obj = function() {
    this.foo = function() {};
};

4) 作为原型的方法(只创建一次,无论执行多少次new

var Obj = function() {};
Obj.prototype.foo = function() {};

5) 作为带有引用的匿名函数(与#1具有相同的效果)*

var foo = function() {};

6) 作为立即执行的匿名函数(完全匿名)

(function() {})();

* 当我看到这个语句时,我考虑的是结果。因此,我不认为它们是匿名的,因为对于函数立即创建了一个引用,因此不再是匿名的。但对大多数人来说,这都是相同的。


有理由偏好#1还是#5吗?我在很多库中看到#5,偶尔也会看到#1。 - EsTeGe
6
没关系,我自己找到答案了,链接在这里:http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/ - EsTeGe
2
暗示#1和#5实际上是相同的是具有误导性的,它们非常不同。除了EsTeGe提供的链接外,还要检查这个SO问题的优秀答案,该答案很好地解释了差异:https://dev59.com/Pm865IYBdhLWcg3wTcpY - terraling

25
第一种方法是创建一个匿名函数并将其分配给变量some_func。因此,使用some_func()将调用该函数。
第二种方法应该是对象符号的一部分。
var obj = {
  show:function(value){
    // some code here
  }
};

因此,obj.show()将调用该函数

在这两种情况下,您都创建了一个匿名函数。但是在第一种情况下,您只是将其分配给变量。而在第二种情况下,您将其分配为对象的成员(可能是许多其他成员之一)。


obj 上的外层括号是多余的。 - Justin Johnson
1
哦!在 Stack Overflow 上回复我的一篇关于使用模块模式编写代码的帖子中说,如果没有那些括号,有时匿名函数可能会失败。我仍然没有得到为什么的解释。不确定它们是否仅适用于模块模式还是所有匿名函数。这就是为什么我添加了它们的原因。 - anon355079
我认为只有在像eval("({a:1})")这样评估一个对象时才会出现这种情况。 - YOU
我认为@S.Mark是正确的。我从未在其他帖子中看到过你描述的问题。除非它真正成为问题,否则不必担心它。开发人员1:“我们为什么要做abc?”开发人员2:“因为我们一直这样做……” - Justin Johnson
5
括号对于立即调用的函数是必需的,而不是对象字面量。函数声明和函数表达式不是同一件事,关键点在于函数声明不能立即调用。例如(function() {})()是一个自执行的函数表达式;括号()function(){}括起来以转换为函数表达式是必要的。否则它被视为函数声明,缺少标识符(或者如果提供标识符,则其后面的())将导致语法错误。 - NickFitz
因此,它被应用于模块模式,在声明后调用它。感谢您澄清这一点! :) - anon355079

4

首先是分配匿名函数的本地(或全局)变量。

var some_name = function(val) {};
some_name(42);

第二个是某些对象的属性(或带有标签的函数),其具有分配的匿名函数。
var obj = {
    show: function(val) {},
    // ...
};
obj.show(42);

在JavaScript中,函数是一等公民,因此您可以将它们分配给变量,并从变量调用这些函数。

您甚至可以使用与要分配给的函数不同的其他名称声明函数。当您想定义递归方法时,这非常方便。例如,不要写成这样:

var obj = {
    show: function(val) {
        if (val > 0) { this.show(val-1); }
        print(val);
    }
};

你可以写成:

你可以编写:

var obj = {
    show: function f(val) {
        if (val > 0) { f(val-1); }
        print(val);
    }
};

2
一种做法是这样的:
var some_func = function(value) {  
    // some code here
}

另一种方式:

function some_funct() {
}

另一种方法:

var some_object={};
some_object["some_func"] = function() {};

或者:

var some_object={};
some_object.some_func = function() {};

换句话说,在JS中,声明函数的方法有很多种。
你的第二个例子是不正确的。

使用 some_object["some_func"] = function() {}; 这种方式有些繁琐。使用点符号表示法更加简洁:some_object.some_func = function() {}; - Justin Johnson
@Justin:...又一种声明函数的方式! - jldupont
声明是相同的(RHS),只是访问符号不同(LHS);) - Justin Johnson
@Justin:非常感谢您对我的贡献进行精确的补充! - jldupont

1
第一个例子创建了一个全局变量(如果该名称的局部变量不存在),名为some_func,并将函数分配给它,以便可以调用some_func()
第二个例子是对象内的函数声明。它将一个函数分配为对象的show属性的值:
var myObj = {
    propString: "abc",
    propFunction: function() { alert('test'); }
};

myObj.propFunction();

哎呀,谢谢你注意到了。如果我本来就是想写那个的话,我就不会回答实际问题了 :D - David Hedlund

1
第一种是一个变量赋值的函数声明(至少应该是这样,尽管它缺少了首先变量类型声明),第二种可能与对象声明有关。

第二种形式有时用于对象字面量:some_obj = { init: function() {}, show: function() {} }; - MBO

1

0

第一个...

some_func = function(value) {  
    // some code here
}

声明一个变量并将匿名函数分配给它,相当于...

function some_func (value) {  
    // some code here
}

第二个应该长成这样...

obj = {
    show:function(value){
       // some code here
    }
}
// obj.show(value)

与...等效

//pseudo code
class MyClass {
    function show (value) {
        // some code here
    }
}
obj = new MyClass();    // obj.show(value)

干杯


你最后两个例子并不等价,因为你不能实例化对象文字(错误:“TypeError:obj不是构造函数”)。var Obj = function() { this.show = function() {}; } 等同于你的伪代码。 - Justin Johnson
@Justin Johnson - 哦!真的吗?那么,为什么这段代码能够完美运行呢?obj={show:function(value){alert("work");}} obj.show(); - Ei Maung
是的,我并没有说 obj.show() 不起作用,我是说你的例子不等价。 - Justin Johnson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接