摘要:第一种方法是上面已经说到的匿名函数表达式,即将匿名函数赋值给一个变量,然后通过变量名去调用。因为函数声明是不能被执行符号执行的,除非通过函数名调用,只有表达式才能被执行符号执行匿名函数又没有函数名,另外的办法就是把它变成表达式。
函数声明
function funcName(){ }; console.log(funcName); // 打印结果是funcName这个函数体。
声明一个函数funcName,funcName就是函数名,函数名是函数声明的必要组成部分,函数其实就是另一个类型的变量,函数名称相当于变量名,新声明的函数体会赋值给这个变量名,之后调用该函数的时候都需要通过该变量名进行调用。
函数表达式
// 命名函数表达式 var funcName = function abc() {}; console.log(funcName); // 打印函数体function abc(){} console.log(abc); // 报错(abc is not defined)
在这个函数表达式中,函数名称为abc,其实上,这个名称abc变成了函数内部的一个局部变量,并且指代函数对象本身,在abc函数内部打印abc的打印结果是abc函数体本身。
var funcName = function abc() { console.log(abc); // 打印结果是function abc() {console.log(abc)} };
所以,在全局console.log(abc);肯定会报错,因为abc是局部变量,全局是拿不到的,这个函数表达式会忽略函数的名称,调用的时候要通过变量名进行调用——funcName();
// 匿名函数表达式 var funcName = function () {};
匿名函数表达式顾名思义就是没有名字的函数表达式,一般情况下,我们所说函数表达式就指匿名函数表达式,因为函数表达式会忽略函数的名称,会变成匿名函数表达式,不如直接写成匿名函数表达式。
函数表达式与函数声明不同的是,函数声明只是声明了一个函数,在预编译的时候,函数声明的声明提升函数体也提升,所以不管你是在函数声明之前调用还是在之后调用,都能正常执行。
demo(); // 结果是"a" function demo(){ console.log("a"); }; demo(); // 结果是"a"
而函数表达式在预编译时,是变量名提升,只有当执行到函数表达式所在行的代码时,才将函数体赋值给该变量,所以在函数表达式之前调用该函数会报错,只能在之后调用。
demo(); // 报错 var demo = function (){ console.log("a") }; demo(); // 结果是"a"
匿名函数
匿名函数顾名思义就是没有名字的函数。(匿名函数有多种用途,写在文末)
function () {};
既然是没有名字的函数,那我们要怎样找到它调用它呢?这里要提到两种方法。
第一种方法是上面已经说到的匿名函数表达式,即将匿名函数赋值给一个变量,然后通过变量名去调用。
var abc = function (){}; abc();
第二种方法就是接下来要说的立即执行函数。
立即执行函数
立即执行函数有两种写法:
// 第一种 w3c标准建议使用这一种 (function (){})(); // 第二种 (function(){}());
这里有两个括号有点疑问,在解释两个括号的作用前,我们先明确几点:
1.只有表达式才能被执行符号执行,函数声明是不能被执行符号执行的。
2.能被执行符号执行的表达式,这个函数的名字就会被自动忽略(放弃名字)。
3.能被执行符号执行的表达式基本上就是立即执行函数。
因为函数声明是不能被执行符号执行的,除非通过函数名调用,只有表达式才能被执行符号执行(匿名函数又没有函数名,另外的办法就是把它变成表达式)。
function (){ console.log("a"); // 报语法错误,因为只有表达式才能被执行符号()执行 }();
(function (){})()
所以此处匿名函数两边的括号运算符,作用是把函数转换为表达式(至于怎样转换的,更深层的原理有兴趣的童鞋可以研究研究,后续我会进行补充的),后面的括号为执行符号,(function (){})()就相当于匿名函数表达式的执行。
(function (){})()和(function(){}())写法其实没多大区别,(function(){}())也是一直等价的表达式,但是w3c标准建议使用第一种。
将函数声明转化成表达式的方式有很多,例如把它赋值给一个变量,再例如在函数声明前放上+运算符,-运算符,!运算符等。
// 把它赋值给一个变量 var demo = function(a){ console.log(a); // 结果为1 }(1) // 使用+运算符 +function(a){ console.log(a); // 结果为1 }(1); // 使用-运算符 -function(a){ console.log(a); // 结果为1 }(1); // 使用!运算符 !function(a){ console.log(a); // 结果为1 }(1);
当表达式被执行,函数的名字就会被放弃,举两个栗子:
var demo = function(){}(); console.log(demo); // 结果会报错,因为函数名被放弃了。 +function demo(){}(); console.log(demo); // 结果会报错,因为函数名被放弃了。
匿名函数有很多作用,例如将匿名函数赋予一个变量来创建一个函数,例如赋予一个事件则成为事件处理程序,再例如用立即执行函数创建闭包防止污染全局变量等等
// 将匿名函数赋予一个变量来创建一个函数 var demo = function(){}; // 赋予一个事件则成为事件处理程序 $(selector).on("click",function(){}); // 用立即执行函数创建闭包 (function(window, undefined))(window);
本文只是简单分析以助自己理清思路,有错误之处请不吝赐教。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/109072.html
摘要:而且,如果你想跳过这里,你可以直接跳到立即调用函数表达式进行阅读,但是我建议你读完整篇文章。当圆括号包裹函数时,它会默认将函数作为表达式去解析,而不是函数声明。什么是呢它使一个被立即调用的函数表达式。一旦命名,函数将不再匿名。 原文:http://benalman.com/news/2010/11/immediately-invoked-function-expression/#iif...
摘要:另外,如果你想跳过这里,你可以直接跳到立即调用函数表达式进行阅读,但是我建议你读完整篇文章。当圆括号包裹函数时,它会默认将函数作为表达式去解析,而不是函数声明。 原文:Immediately-Invoked Function Expression (IIFE) by Ben Alman原译:立即执行函数 by Murphywuwu改增内容: by blanu 也许你没有注意到,我是一个...
摘要:前言最近在学前几天看到两道题刚开始看懵懵懂懂这几天通过各种查资料慢慢的理解顿悟了对匿名函数闭包立即执行函数的理解也更深了一点在此分享给大家我的理解与总结希望能帮助大家理解因为这篇文章是我用心总结的查阅了很多的资料所以总结的比较细篇幅较长如果 前言 最近在学JS,前几天看到两道题,刚开始看懵懵懂懂,这几天通过各种查资料,慢慢的理解,顿悟了,对匿名函数,闭包,立即执行函数的理解也更深了一点...
摘要:而闭包的神奇之处正是可以阻止事情的发生。拜所声明的位置所赐,它拥有涵盖内部作用域的闭包,使得该作用域能够一直存活,以供在之后任何时间进行引用。依然持有对该作用域的引用,而这个引用就叫闭包。 引子 先看一个问题,下面两个代码片段会输出什么? // Snippet 1 a = 2; var a; console.log(a); // Snippet 2 console.log(a); v...
摘要:匿名函数的好处在于可以减少局部变量,以免污染现有的运行环境。另外通过,这三个符号运行的匿名函数比运行的匿名函数可以减少一个字符的使用但是我们通常使用加因为其他的操作符可能会带来其他的影响更多可以参考 js中的立即执行函数 ( function(){…} )()和( function (){…} () )是两种javascript立即执行函数的常见写法 问题: 为什么会出现上面的两种不一...
阅读 1549·2023-04-26 02:29
阅读 3014·2021-10-11 10:58
阅读 2893·2021-10-08 10:16
阅读 3153·2021-09-24 09:47
阅读 1562·2019-08-29 16:56
阅读 2711·2019-08-29 11:03
阅读 1990·2019-08-26 13:35
阅读 3166·2019-08-26 13:34