注意:本文非原创,参考链接《JS中的匿名函数》,感谢原作者的分享。
本文的 pdf 版本链接: https://pan.baidu.com/s/1y2W3IWEnEAzaT-0Y4Y48Ow 提取码: xsc7
定义函数的方式有两种:
- 函数声明(function 语句)
- 函数表达式(匿名函数)
1. 函数声明(function 语句)
要使用一个函数,我们就得首先声明它的存在。最常用的方式就是使用 function 语句来定义一个函数,如:
function sayHello() {
console.log("hello world!");
}
当然,我们的函数是可以带参数,以及带返回值的:
function sub(x, y) {
return x - y;
}
但是,无论我们怎么定义我们的函数,JavaScript 解释器都会把它转换成一个 Function 对象。例如,我们在定义上面的其中一个例子的函数后,再输入如下代码:
console.log("typeof sub:", typeof sub); // typeof sub:function
log 输出的结果将会是 typeof sub:function
,提示我们 sub 是一个 Function 对象。那么 Function 对象究竟是什么呢?
1.1. Function 对象
Function 对象是 JavaScript 里面的固有对象,所有的函数实际上都是一个 Function 对象。那么,Function 对象能不能直接运用构造函数创建一个新的函数呢?答案是肯定的。例如:
var multi = new Function("x", "y", "return x*y;");
console.log(multi(2, 3)); // 输出 6
现在我们对如何声明一个函数应该是有所了解了。那么什么才是匿名函数呢?
2. 函数表达式(匿名函数)
顾名思义,匿名函数就是没有实际名字的函数。例如,我们把上面的例子中,函数的名字去掉,再判断一下他是不是一个函数:
console.log(typeof function(){}); // "function"
console.log(typeof function(x,y){return x+y;}); // "function"
console.log(typeof new Function("x","y","return x*y;")); // "function"
我们可以很容易地看到,它们全都是 Function 对象,换言之,他们都是函数,但是他们都有一个特点 —— 没有名字。所以我们把他们称作“匿名函数”。然而,正因为他们没有“名字”,我们也没有办法找到他们。这就引申了如何去调用一个匿名函数的问题了。
2.1. 匿名函数的调用
要调用一个函数,我们必须要有方法定位它,引用它。所以,我们会需要帮它找一个名字。例如:
var sub = function(x, y) {
return x - y;
}
console.log(sub(3,2)); // 1
上面的操作其实就等于换个方式去定义函数,这种用法是我们比较频繁遇到的。例如我们在设定一个 DOM 元素事件处理函数的时候,我们通常都不会为他们定名字,而是赋予它的对应事件引用一个匿名函数。
对匿名函数的调用其实还有一种做法,使用 ()
将匿名函数括起来,然后后面再加一对小括号(包含参数列表)。我们再看一下以下例子:
console.log((function(x,y){return x+y;})(2,3)); // 5
console.log((new Function("x","y","return x*y;"))(2,3)); // 6
为什么这种方法能成功调用呢?
小括号能把我们的表达式组合分块,并且每一块,也就是每一对小括号,都有一个返回值。这个返回值实际上也就是小括号中表达式的返回值。所以,当我们用一对小括号把匿名函数括起来的时候,小括号内返回的就是一个 Function 的匿名函数对象。因此,小括号加上匿名函数就如同有名字的函数般被我们取得它的引用位置了。之后,再在这个引用变量后面再加上参数列表,就会实现普通函数的调用形式。
下面的代码更方便我们的理解:
var sub = function(x, y) {
return x - y;
}
console.log((sub).constructor === (function(x,y){return x - y;}).constructor); // true
constructor
是指创建对象的函数。也就是函数对象所代表的函数体。
2.2. 如何执行匿名函数
下面是三种执行匿名函数的方式:
// method 0
var sayHello = function() {
console.log("hello world!");
} // 此处没有括号
sayHello();
// method 1
( function() {
console.log("hello world!");
})();
// method 2
var sayHello1 = function() {
console.log("hello world!");
}(); // 注意这个括号
网友评论