区别:
1.函数声明是用function后面有函数名,函数表达式是赋值形式给一个变量。
2.函数声明可以提升函数,而函数表达式不会提升
函数提升就是函数会被自动提升到最前方,以至于再调用函数后再声明函数也不会有错:
//例子://先调用运行sayName();//再声明函数function sayName(){ console.log('ry');}//运行结果'ry'
函数表达式就不会被提升:
//先调用sayBye();//函数表达式var sayBye = function(){ console.log('bye bye');}//运行报错
但是下面的写法很危险:因为存在函数声明的提升
//书上代码if(condition){ function sayHi(){ console.log('hi'); }}else{ function sayHi(){ console.log('yo'); }}
解说一下: 这段代码想表达在condition为true时声明sayHi,不然就另一函数sayHi,但是运行结果往往出乎意料,在当前chrome或firefox可能能做到,但是在IE10以下的浏览器(我测试过)往往不会遵循你的意愿,不管condition是true还是false都会输出yo。
这时函数表达式能派上用场了:
//换成函数表达式,没问题因为不会被提升,只有当执行时才赋值var sayHi = null;if(condition){ sayHi = function (){ console.log('hi'); }}else{ sayHi = function sayHi(){ console.log('yo'); }}
三、闭包
闭包的定义:有权访问另一个函数作用域中的变量的函数
有人觉得闭包很难理解,一开始我也是这样的,我认为那是对一些概念还不够了解。
定义中说明了什么是闭包,最常见的形式就是在函数中再声明一个函数。
重点理解这里:
1.闭包能访问外围函数的变量是因为其作用域链中有外围函数的活动对象(这个活动对象即使在外围函数执行完还会存在,不会被销毁,因为被闭包引用着)。
2.闭包是函数中的函数,也就是说其被调用时也创建执行上下文,对于执行上下文这部分可以看看这篇:深入理解js执行--创建执行上下文这篇博客。
理解了上面之后我们再来看闭包的例子:
function a(){ //a函数的变量 var val_a = "我是a函数里的变量"; //声明函数b,b能访问函数a的变量 function b(){ console.log(val_a); } //a函数将b返回 return b;}//全局变量fn,a执行返回了b给fnvar fn = a();//调用fn,能够在全局作用域访问a函数里的变量fn(); //我是a函数里的变量
这里fn能够访问到a的变量,因为b中引用着a的活动对象,所以即使a函数执行完了,a的活动对象还是不会被销毁的。这也说明过度使用闭包会导致内存泄漏。
再来个常见的例子(给多个li添加点击事件,返回对于li的下标):
<body> <ul id="list"> <li>red</li> <li>green</li> <li>yellow</li> <li>black</li> <li>blue</li> </ul></body>
//获得li标签组var li_group = document.getElementsByTagName('li');//错误例子:每个li都会跳出5function fn(){ //为每一个li添加点击事件 var i = 0; //使用for来给每个li添加事件 for(;i<li_group.length;i++){ //添加点击事件 li_group[i].addEventListener('click',function(){ // 输出对应得下标 console.log(i); });
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。