javascript中为何在匿名function函数后面还外加

2020-05-20 22:29:05

参考地址 javascript中为何在匿名function函数后面还外加

  对于很多初学者来说,遇到它们经常会产生一系列问号:这是编程吗,用它做什么,怎么我没在其他语言里见过呢?

    接下来我就详细地解释一下:

    它可以解释成为“匿名函数自调用”,也就是说,定义一个匿名函数,然后马上调用它(因为它是匿名的,如果不立即调用就获取不到该函数的引用了)。通常它被应用在一些大型的JS框架中(如上面所说的),因为这个匿名函数的函数体相当于提供一个匿名的名字空间,这样就不会再与用户自定义的JS函数、变量、对象发生冲突了。尽管JS没有显示地提供命名空间的定义和使用机制,但这种匿名方式却不失为是一种很好的解决命名空间问题的方法。

    所以说,(function(){代码})()就等于执行了一个函数,只不过它是匿名的而已。如果在这个匿名函数内部想再次调用这个函数,就需要调用constructor属性了(这是Object中定义的,JS的继承机制如同Java一样保证了了所有对象都继承Object类)。

    明白了它是什么了,下面我们就要学习该怎样使用它了,以下这些问题是我们会经常遇到的,不如提前做好理论只是准备以备后期能顺利地实现开发。请看下面问题:

1、下列哪些正确?(B、C

A.function(){

       alert("Here!");

    }();

B.(function(){

       alert("Here!");

    })();

C.(function(){

       alert("Here!");

    }());

2、下列哪个结果是正确的?(A、B、C、D

A.(function(a1,a2){

       alert("Here!"+(a1+a2));

    })(1,2);

B.(function(a1,a2){

       alert("Here!" +(a1+a2));

    }(1,2));

C.void function(a1,a2){

       alert("Here!" +(a1+a2));

    }(1,2);

D.var f = function(a1,a2){

       alert("Here!" +(a1+a2));

    }(1,2)

    注:A 、B、C与D四种格式都正确,前两者属于同种情况的不同写法,后两种是将函数对象的返回值赋给其他变量,C是忽略函数返回值,而D正相反!

    具体举个例子:

function test(){

          return (function(p1,p2){

                            return p1+p2;

          })(1,2);

};

(function(){

          alert(test());

}());

    下面我们就深入研究一下这种匿名函数:

1、

function Foo() { 

    var a = 123; 

    this.a = 456; 

    (function() {

       alert(a); // 123

       alert(this.a); // undefined 

    })(); 

};

var f = new Foo();

② 

function Foo() { 

    var a = 123; 

    this.a = 456; 

    (function(_this) {

       alert(a); // 123

       alert(_this.a); // 456 

    })(this); 

};

var f = new Foo();

以上两个对比,说明:

(1)匿名函数可以直接访问到外层署名函数(Foo)中的变量(使用关键字var定义的),但不能访问外层署名函数的属性(使用关键字this定义的);

(2)匿名函数中的this指向的是匿名函数对象的地址,它与外层署名函数(Foo)对象的this指向的地址不同;

(3)匿名函数若要访问外层署名函数(Foo)中的属性,可以通过参数传递的方式实现。 

2、

① 

function Foo() { 

    var a = 123; 

    this.a = 456; 

    (function(b) {

       alert(a); // 123

       alert(b); // 456 

    })(this.a); 

};

var f = new Foo();

(function() { 

    var a = 123; 

    this.a = 456; 

    (function() {

       alert(a); // 123

       alert(this.a); // 456 

    })();

})();

以上两个对比,说明:

(1) 匿名函数既可以直接访问外层匿名函数中的变量,又直接可以访问外层匿名函数中的属性,而匿名函数却不可以直接访问外层已命名函数中的属性;

2)以上两种方式可以实现相同的功能。

3、

(function() { 

    var a = 123; 

    this.a = 456; 

    (function() { 

       alert(a); // 123 

       alert(this.a); // 456 

       this.b = 789; 

    })(); 

    (function() { 

       alert(this.b); // 789 

    })(); 

})();

(function() {

    alert(this.a); // 456

    alert(this.b); // 789 

})();

function Foo() { 

    var a = 123; 

    this.a = 456;

    (function() { 

       alert(a); // 123 

       alert(this.a); // undefined 

       this.b = 789; 

    })(); 

    (function() { 

       alert(this.b); // 789 

    })(); 

};

var f = new Foo(); 

(function() {

    alert(this.a); // undefined

    alert(this.b); // 789 

})();

以上两个对比,说明:

(1)匿名函数(即用两个小括号括起来的部分)位于一个执行上下文,不论这些代码放在哪个位置上。

4、

function Foo() {

(function() {

this.b = 789;

})();

(function() {

alert(this.b); // 789

alert(b); // 789

var a = 0;

alert(a); // 0

})();

}

var f = new Foo();

(function() {

alert(this.b); // 789

alert(b); // 789

})();

function Foo() {

(function() {

this.b = 789;

})();

(function() {

alert(this.b); // 789

alert(b); // undefined

var b = 0;

alert(b); // 0

})();

}

var f = new Foo();

(function() {

alert(this.b); // 789

alert(b); // 789

})();

以上两个对比,说明:

1)没有加 this取值时,如果当前 {} 中不存在同名的局部变量,则等同于加 this 处理;如果当前 {} 中存在同名的局部变量,则按常规处理。 

以上只是鄙人的粗浅见解,内容还不够完整,还会不断完善删改,如其中有什么错误之处还望读者谅解,真诚希望能留下您的宝贵建议,以图修改!这里欢迎每一位爱好JS的读者,真心希望能和你们交流心得!


  • 2019-12-04 10:46:26

    nuxt.js项目中全局捕获异常并生成错误日志全过程

     需求:客户在使用过程中页面报错时,可以生成错误记录传回服务器,以便改进。   步骤:     一.全局捕获异常,     二.发送到服务端,     三.生成错误日志。   一.全局捕获异常 如图,vue提供了errorHandle这个方法来处理全局异常,更多详细内容参见官网。

  • 2019-12-04 10:47:59

    nuxt.js项目中全局捕获异常并生成错误日志全过程

     需求:客户在使用过程中页面报错时,可以生成错误记录传回服务器,以便改进。   步骤:     一.全局捕获异常,     二.发送到服务端,     三.生成错误日志。   一.全局捕获异常 如图,vue提供了errorHandle这个方法来处理全局异常,更多详细内容参见官网。

  • 2019-12-04 10:48:18

    vue 项目资源文件 static 和 assets 不说区别直接使用?

    assets中资源会webpack构建压缩到你代码中,而static文件直接引用。 static 中长存放类包、插件等第三方的文件,assets里放属资源文件比如自己资源图片、css文件、js文件。 引入资源的方式static文件夹可以使用~/static/方式引入, assets文件夹可以使用 ~@/assets 方式引入

  • 2019-12-05 17:01:36

    Vue 结合 Axios 接口超时统一处理

    当网路慢的时候。又或者公司服务器不在内地的时候,接口数据请求不回来超时报错的情况相信大家肯定遇到过的,这里我把我公司项目请求超时的处理方法分享下,希望看过后有帮助。

  • 2019-12-05 17:13:40

    JS模板工具lodash.template的简单用法

    lodash是从underscore分支的一个项目,之前我写了一篇JS模板工具underscore.template的简单用法,lodash跟underscore很相似,这也简单介绍一下lodash的template方法。 先把underscore的文章中用过的代码贴过来,把underscore的js文件换成lodash的js,其他一字不改,然后我们试试:

  • 2019-12-06 10:47:29

    date-fns日期工具的使用方法详解

    isToday() 判断传入日期是否为今天 isYesterday() 判断传入日期是否为昨天 isTomorrow() 判断传入日期是否为 format() 日期格式化 addDays() 获得当前日期之后的日期 addHours() 获得当前时间n小时之后的时间点 addMinutes() 获得当前时间n分钟之后的时间 addMonths() 获得当前月之后n个月的月份 subDays() 获得当前时间之前n天的时间 subHours() 获得当前时间之前n小时的时间 subMinutes() 获得当前时间之前n分钟的时间 subMonths() 获得当前时间之前n个月的时间 differenceInYears() 获得两个时间相差的年份 differenceInWeeks() 获得两个时间相差的周数 differenceInDays() 获得两个时间相差的天数 differenceInHours() 获得两个时间相差的小时数 differenceInMinutes() 获得两个时间相差的分钟数