JavaScript 中的匿名函数、函数字面量、闭包函数

JavaScript 中的匿名函数、函数字面量、闭包函数

编程那点事 JavaScript 1387 字 / 3 分钟

最近一直在看 JavaScript,虽然很久以前接触过 ActionScript,语法与 JS 及其相似。但还是想从头来一遍,以免漏掉什么重点。 果然,我发现 JavaScript 的函数十分灵活,其声明与调用方法都很有意思。这种灵活性使我觉得我可以用她来做很多东西。 这篇文章就是谈谈我对几种函数类型的理解吧。

声明式函数

声明式函数就是我们最常见的那种类型。 一个很简单的例子:

function sayHi(toWhom){
	console.log('Hi' + toWhom);
}

就是这种十分常见的方式,我也就不再赘述了。 需要注意的一点是,JavaScript 函数的参数中,有了默认值的参数不一定要放在没有默认值的参数的前面。放在后面也是可以的。 调用函数的时候输入的值还是按照顺序传给每个参数,没有被赋值的参数值为 undefined

匿名函数

匿名函数是将函数 Function 当做一个对象来进行实例化。比较有意思的地方在于,函数的参数,以及函数内的语句都是可以以字符串形式传入的。

var showMyDevice = new Function("parm1", "parm2", "console.log('I have ' + parm1 + ' and ' + parm2);");
showMy('MacBook', 'iPhone');

new Function() 中的最后一个参数会被当做匿名函数的语句块,之前的都会被当做传入的参数。 并且传入的参数也可以带上默认值:

var showMyDevice = new Function("parm1=MacBook", "parm2", "console.log('I have ' + parm1 + ' and ' + parm2);");

有些比较老的书上好像会直接省略掉 new 之后的 Function,但是我尝试过后发现这样写会报错。

函数字面量

~其实我内心中所理解的匿名函数的概念更像函数字面量……~ 函数字面量在我们写 ajax 请求时经常会用到,返回的 success 我们会直接给一个函数,类似这样:

......
		success: function(data){
			console.log(data);
		}
......

这个就是函数字面量。名字好蠢啊 一般的使用方法是:

var sum = function (x, y){
	return x + y;
}
console.log(sum(1, 2));

闭包函数

PHP 中的函数闭包其实并不是很强大也不知道这个词用得对不对,也不是很常用。 但是函数的闭包在 JavaScript 里可是有点东西的。

上一个不是那么好理解例子:

function outerFunc(base){
	var punc = '!';
	
	return function (ext){
		return base + ext + punc;
	}
	
}

var baseString = outerFunc("Hello");

var newString = baseString("World");
var anotherString = baseString("John");

console.log(newString);
console.log(anotherString);

这里的输出结果是:

Hello World!
Hello John!

首先是调用了 outerFunc,然后将其赋值给了 baseString。需要注意的是,因为 outerFunc 函数的返回值是一个函数字面量,因此 baseString 现在是一个有一个名为 ext的参数的函数,而非字符串。 那么接下来 baseString 就是在调用这个函数字面量,这才 return 了一个字符串给 newString 变量。 闭包函数的妙处就在与——这段代码的后面,我们再一次调用了 baseString 函数,将其返回的字符串给了 anotherString。这里的两次调用,最初传给 outerFuncHello 参数一直的都是在的。

书上给的 JavaScript 中关于闭包的定义:

返回在其他函数中以内部对象形式创建的一个函数字面量,然后将其赋值给主调应用程序中的一个变量,就是 JavaScript 中的闭包。

通常,当函数终止时该作用域也就会释放,因为它已经不再需要了。但是,当一个内部函数是外部函数应用程序的返回值,并赋给一个外部变量时,内部函数的作用域就将附加到外部函数上,然后再附加到主调程序中,这样才能保证内部函数与外部函数参数和变量的完整性。

也就是说,一个函数 A 的内部函数 B 被外部变量所引用时,就形成了一个闭包。其中函数 A 在执行结束后并不会被 JavaScript 的垃圾回收机制所回收,因为函数 A 的内部函数 B 的执行需要依赖A中的变量。

闭包的用途:

  • 外部只能访问到函数 B,而函数 A 中的变量外界并不能访问到,只能间接通过函数 B 来进行。更加安全了。
  • 使用闭包后,因为函数 B 还依赖着函数 A,因此函数 A 并不会被回收,还会留在内存中。

关于闭包更深更透彻的概念,应该就是牵扯到 JavaScript 底层了。但是我才刚入门啊! 学完 JavaScript 后打算去尝试一下 Vue.js 框架,尝试着去做点东西,顺便膜拜尤雨溪大神(尤大)