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

最近一直在看 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 框架,尝试着去做点东西,顺便膜拜尤雨溪大神(尤大)



喜欢这篇文章?为什么不打赏一下呢?

爱发电

3 条评论

 

昵称
  1. 凌丶

    站长大佬带带我

  2. 凌丶

    愣是没看出到底啥区别,少了个new吗。。。

    1. John

      感觉匿名函数是把函数当做一个“类”,然后用 new 进行实例化了。并且像一个变量一样存储。这个函数其实是没有名字的,所以叫“匿名函数”。函数字面量是在那种只会在一个地方调用一次函数的情境下使用的。比如 ajax 的 success 回调,这个函数也没有名字,也没有被赋值给什么变量。