JavaScript闭包
1.什么是闭包
定义一:闭包是一个有权访问另一个函数作用域中变量的函数,也就是说闭包是一个函数,当然这个一般是内部函数作用域访问外部函数作用域。
定义二:一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包,这个定义中闭包仍然被看成一个函数,只不过需要结合函数的词法环境才可以被称作闭包。
闭包应该符合如下几个特点:
- 闭包是一个函数
- 内部函数使用了外部函数的变量
下面的inner函数就是一个闭包:
function outer(){
var n=100
function inner(){
console.log(n);
}
}
2.闭包的作用
作用:延伸变量的作用范围
函数在执行时,会生成一个作用域,作用域中包含了函数内部定义或者使用的变量,函数执行完毕后,作用域消失,其中的变量自然无法使用
但由于闭包的存在,使得 outer 函数执行完毕后,其内部变量 n 仍然被保留
function outer(){
var n=100
function inner(){
console.log(n);
}
return inner
}
var fn=outer() // outer 函数执行完毕,其内部变量应该销毁,但由于 inner 函数使用了此变量给,所以此变量一直被保留
fn()
匿名函数示例
function makeAdder(x){
return function(y){
// console.log(x,y);
return x+y
}
}
var add5=makeAdder(5)
var add10=makeAdder(10)
add5(2)
add10(2)
上面代码中 函数 makeAdder 执行时返回了匿名函数,分别给 add5和add10,这两个函数就是闭包
3.闭包的案例
利用闭包的方式得到当前li的索引号
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
for (var i = 0; i < lis.length; i++) {
// 利用for循环创建了4个立即执行函数
// 立即执行函数也成为小闭包因为立即执行函数里面的任何一个函数都可以使用它的i这变量
(function(i) {
lis[i].onclick = function() {
console.log(i);
}
})(i);
}
</script>
使用let替代闭包
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
for (let i = 0; i < lis.length; i++) {
lis[i].onclick = function () {
console.log(i);
}
}
</script>
JavaScript递归
1.什么是递归
递归:如果一个函数在内部可以调用器本身,那么这个函数就是递归函数。简单理解:函数内部自己调用自己,这个函数就是递归函数。
注意:递归函数的作用和循环效果一样,由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件return。
利用递归求1~n的阶乘
//利用递归函数求1~n的阶乘 1 * 2 * 3 * 4 * ..n
function fn(n) {
if (n == 1) { //结束条件
return 1;
}
return n * fn(n - 1);
}
console.log(fn(3));
运行结果为:6