闭包
定义
闭包是在一个作用域内创建一个封闭的词法环境,它通常会自动返回回来生成这个语法环境,这个环境由创建闭包时在作用域内的任何局部变量构成
作用
正常函数执行后,里面生成的变量会被垃圾回收处理掉,但是闭包可以让作用域内的变量在函数执行完后,依然没有被垃圾回收处理掉
实例
- 计时器
function add() {
var count = 0;
return function () {
count++;
console.log(count);
};
}
let countAdd = add();
countAdd(); //1
countAdd(); //2
在调用countAdd的时候,会返回一个函数,函数是可以创建自己的作用域的,但是count函数引用了add函数下的count参数,所以这个参数是不可以被销毁的。
所以接下来我们需要几个计数器,就创建几个函数就可以了,他们之间是相互不影响的
var fun1 = addCount();
fun1(); //1
fun1(); //2
var fun2 = addCount();
fun2(); //1
fun2(); //2
声明函数和表达式函数
// 声明函数
function hello() {
return "HELLO"
}
// 表达式函数
var h1 = function hello() {
return "HELLO"
}
声明提前
首先说一下变量声明提前
变量声明语句会被提前到函数/脚本的顶部,但是赋值的操作还在原来的位置执行,在赋值语句之前,变量的值为undefined 即
- 变量声明会提前到函数的顶部;
- 只是声明被提前,初始化不提前,初始化还在原来初始化的位置进行初始化;
- 在声明之前变量的值是undefined。
函数声明提前
funDeclaration("Declaration");//=> true
function funDeclaration(type){
return type==="Declaration";
}
funExpression("Expression");//=>error
var funExpression = function(type){
return type==="Expression";
}
由上面例子可知:使用声明函数定义的函数时,函数调用可以放在任何位置
即函数声明提前的时候,函数声明和函数体都提前了
函数声明是在预执行期执行的,就是说函数声明是在浏览器准备执行代码的时候执行的。因为函数声明在预执行期被执行,所以到了执行期,函数声明就不再执行(人家都执行过了自然就不再执行了)。
为什么表达式函数不能提前声明
上面对于var的声明提前,只是声明提前了,初始化没有提前,初始化还在原来的地方初始化
表达式函数就是把一个函数对象赋值给变量了,所以对于表达式函数来说赋值是不会提前的
实例分析
sayTruth();
if(1){
function sayTruth(){alert('myvin is handsome')};
}
else{
function sayTruth(){alert('myvin is ugly')};
}
//myvin is ugly
因为函数声明提前,所以函数声明会在代码执行前进行解析,执行顺序是这样的,先解析function sayTruth(){alert('myvin is handsome')},在解析function sayTruth(){alert('myvin is ugly')},覆盖了前面的函数声明,当我们调用sayTruth()函数的时候,也就是到了代码执行期间,声明会被忽略,所以自然会输出myvin is ugly
函数声明是在预执行期执行的,就是说函数声明是在浏览器准备执行代码的时候执行的。因为函数声明在预执行期被执行,所以到了执行期,函数声明就不再执行了(人家都执行过了自然就不再执行了)