函数的声明与执行
-
函数定义阶段
1.会在堆内存中开辟一个存储空间 把函数体放在这个空间里 函数中的所有变量不解析
2.把这个空间地址赋值给函数名 然后储存在栈内存中 -
函数调用阶段
1.根据函数名找到对应的函数存储空间
2.然后再堆内存中再开辟一个函数执行空间
3.在这个执行空间里面进行函数赋值 和与解析
4.这时函数储存空间的代码会复制到函数执行空间内 然后执行
5.执行完毕之后 执行空间销毁
函数每次执行都会开辟一个执行空间 执行完毕后 执行空间销毁 这个过程也就是所说的垃圾回收机制 -
函数执行的特殊情况
当函数返回的是一个复杂数据类型时 并且在函数的外部有变量接收这个复杂数据类型
只有这个外部变量不在引用函数内部返回值的时候 这个函数执行空间才会销毁
那么闭包就是利用函数的这个特性来实现的 接下来聊一聊js的闭包
闭包
-
理解闭包的含义
闭包形成的三要素:
1.在函数A内部直接或者间接返回一个函数B
2.B函数内有A函数的私有变量
3.A函数的外部有一个变量接收这返回的B函数 -
闭包空间
当A函数执行完毕后 销毁并且在A函数的内部有一个B函数的存储空间 这个空间就叫做闭包空间
- 形成闭包的代码结构
function fn(){
var num = 1;
return function b(){
console.log(num)
}
}
var f = fn();
f()//1
- 闭包的作用
1.可以做缓存
function version() {
var food = '';
var obj = {
eat : function(){
console.log('我正在吃'+food);
food = "";
},
abb : function (myFood){
food = myFood;
}
}
return obj;
}
var eater = version();
eater.abb('apple');
eater.eat();//我正在吃apple
2.实现公有变量
函数累加器
function add(){
varcount = 0;
function demo(){
count++;
console.log(count);
}
return demo;
}
var counter = add();
//每次调用一次就会在原有基础上加一;
counter();
counter();
counter();
3.模块化开发防止污染全局变量
function test(){
var arr = [];
for(var i = 0;i<10;i++){
(function(j){
arr[j]=function(){
console.log(j+",");
}
})(i)
}
return arr;
}
var myArr = test();
for (var j = 0 ; j < 10 ; j++){
myArr[j]();
}
//打印0,1,2,3,4,5,6,7,8,9
- 闭包的缺点
当内部函数被保存到外部时就会生成闭包 闭包会导致原有作用域链不释放 造成能存泄露
闭包的应用场景
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
<p>hello world</p>
<button>12</button>
<button>14</button>
<button>16</button>
<script>
document.querySelectorAll('button')[0].onclick = changeSize(12);
document.querySelectorAll('button')[1].onclick = changeSize(14);
document.querySelectorAll('button')[2].onclick = changeSize(16);
function changeSize(size) {
return function () {
document.body.style.fontSize = size + 'px';
};
}
//我们定义行为,然后把它关联到某个用户事件上(点击或者按键)。我们的代码通常会作为一个回调(事件触发时调用的函数)绑定到事件上
</script>
</body>
</html>
循环绑定事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<script>
var btns = document.querySelectorAll('button')
for (var i = 0; i < btns.length; i++) {
(function loop(num) {
btns[num].onclick = function () {
console.log(num)
}
})(i)
}
</script>
</body>
</html>