JS函数声明,函数表达式,匿名函数,具名函数全解 |
您所在的位置:网站首页 › js匿名函数和闭包函数区别 › JS函数声明,函数表达式,匿名函数,具名函数全解 |
函数
声明函数的方式函数声明(具名函数)和函数表达式区别匿名函数
声明函数的方式
在Javascript中有两种声明函数的方法 函数声明,也叫具名函数 function hello() {}函数表达式 var hi = function() {} // || let helo = () => {} 函数声明(具名函数)和函数表达式区别在JavaScript高级程序设计(第三版) 中讲到 而实际上,解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁。解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问);至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解析。 alert(sum(10, 10)); function sum(num1, num2) { return num1 + num2; }以上代码完全可以正常运行,因为在代码开始执行之前,解析器就已经通过一个名为函数声明提升(function declaration hoisting)的过程,读取并将函数声明添加到执行环境中。对代码求值时,JavaScript引擎在第一遍会声明函数并将它们放到源代码树的顶部。所以即使声明函数的代码在调用它的代码后面,JavaScript引擎也能把函数声明提升到顶部。 在es6之前,不管是变量还是函数,都存在提升的行为。 console.log(a); console.log(b); var a = 1; function b() { console.log(1); }运行结果 可以看到 变量a 和 函数b 在代码开始执行之前,进行了提升 如果把上面的函数声明换成等价的函数表达式,就会发生错误 alert(sum(10, 10)); var sum = function(num1, num2) { return num1 + num2; }运行结果 JavaScript高级程序设计(第三版) 原话解析 以上代码之所以会在运行期间产生错误,原因在于函数位于一个初始化语句中,而不是一个函数声明。换句话说,在执行到函数所在的语句之前,变量sum中不会保存有对函数的引用;而且,由于第一行代码就会导致“unexpected identifier”(意外标识符)错误,实际上也不会执行到下一行。 除了什么时候可以通过变量访问函数这一点区别之外,函数声明与函数表达式的语法其实是等价的 也就是说函数声明会在代码执行前进行提升,函数表达式就不会 console.log(a); /* function a() { console.log('a'); } */ console.log(b); // undefined function a() { console.log('a'); } var b = function() { console.log('b'); } 匿名函数 function() {}以上就是一个匿名函数,它没有名字的。和函数表达式的右手端(Right hand side)一样 用途 函数表达式 回调函数 模拟块级作用域 函数表达式 // 01 var fn = function() {} // 02 var fn = function fn() {}第二种方式同时使用函数声明和函数表达式也是可行的。 在Safari中会导致错误 因为家贫,未得macbook && iphone 也测试不了 回调函数 document.documentElement.addEvenListener('click', function() { console.log('hello world'); })块级作用域 先看下面一个例子 function t(count) { for (var i = 0; i for (var i = 0; i for (var i = 0; i // 这里块级作用域 })()以上代码定义并立即调用了一个匿名函数。将函数声明包含在一对圆括号中,表示它实际上是 函数表达式。而紧随其后的另一对因括号会立即调用这个函数。 如果有读者感觉这种语法不太好理解,可以再看看下面这个例子。 var count = 5; t(count);这里初始化了变量 count,将其值设置为5。 当然,这里的变量是没有必要的,因为可以把值直接传给函数。 为了让代码更简洁,我们在调用函数时用5来代替变量 count,如下所示。 t(5);这样做之所以可行,是因为变量只不过是值的另一种表现形式,因此用实际的值替换变量没有问题 再看下面一个例子 var somefn = function() { // 这里是块级作用域 } somefn();这个例子先定义了一个函数,然后立即调用了它。 定义函数的方式是创建一个匿名函数,并把匿名函数赋值给变量 somefn。而调用函数的方式是在函数名称后面添加一对圆括号。 即somefn()。通过前面的例子我们知道,可以使用实际的值来取代变量count。 那在这里是不是也可以用函数的值直接取代函数名呢?然而,下面的代码却会导致错误 function() { // 这里是块级作用域 }(); // 出错这段代码会导致语法错误,是因为 JavaScript将 function关键字当作一个函数声明的开始,而函 数声明后面不能跟圆括号。然而,函数表达式的后面可以跟圆括号。 要将函数声明转换成函数表达式,只要像下面这样给它加上一对圆括号即可。 (function() { // 这里是块级作用域 })();所以,无论在什么地方,只要临时需要一些变量,就可以使用私有作用域(块级作用域)。例如 function t(count) { (function() { for (var i = 0; i var now= new Date(); if (now. getMonth()== 0 && now getDate () == 1) { alert(.Happy new year !"); } })();把上面这段代码放在全局作用域中,可以用来确定哪一天是1月1日;如果到了这一天,就会向用 户显示一条祝贺新年的消息。 其中的变量now现在是匿名函数中的局部变量,而我们不必在全局作用域中创建它。 这种做法可以减少闭包占用的内存问题,因为没有指向量名函数的引用。只要函数执行完毕,就可以立即销毁其作用域链了 |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |