一、作用域
我们平常用的作用域叫做词法作用域,词法作用域的内涵是,作用域在词法分析阶段就被确定了(写代码的时候就确定了),也就是说,变量在代码中所处的位置 (而不是运行时所处的位置),决定了作用域。下面介绍作用域分【全局作用域】、【函数作用域】、【块级作用域】、【作用域链】、【闭包】。
看张全景图:
二、全局作用域
全局变量有 全局作用域: 网页中所有脚本和函数均可使用。
var carName = " Volvo";
// 此处可调用 carName 变量
function myFunction() {
// 函数内可调用 carName 变量
}
上述代码中变量 myFunction 就是在函数外定义的,它是拥有全局作用域的。
// 此处可调用 carName 变量
function myFunction() {
carName = "Volvo";
// 此处可调用 carName 变量
}
上述代码:carName它将作为 global 或者 window 的属性存在,在函数或者代码块{}
内未定义的变量也是拥有全局作用域的,换句话说没有使用 var 定义的变量虽然拥有全局作用域,但是它是可以被 delete 的,而全局变量不可以(这种方式是不推荐)
三、函数作用域
在函数内部定义的变量,就是局部作用域。函数作用域内,对外是封闭的,从外层的作用域无法直接访问函数内部的作用域!
function bar() {
var testValue = 'inner';
}
console.log(testValue); // 报错:ReferenceError: testValue is not defined
如果想读取函数内的变量,必须借助 return 或者闭包。如下:
// return方式
function bar(value) {
var testValue = 'inner';
return testValue + value;
}
console.log(bar('fun'));// "innerfun"
// 闭包方式
function bar(value) {
var testValue = 'inner';
var rusult = testValue + value;
function innser() {
return rusult;
};
return innser();
}
console.log(bar('fun'));// "innerfun"
四、块级作用域
在 ES6 中,块状作用域得到普及,我们知道"{ }"就够了。
if(true){
let a = 1
console.log(a)
}
切记,块级作用域需要{}和let、const合并使用才会生成。
五、作用域链
通俗地讲,当声明一个函数时,局部作用域一级一级向上包起来,就是作用域链。
1.当执行函数时,总是先从函数内部找寻局部变量
2.如果内部找不到(函数的局部作用域没有),则会向创建函数的作用域(声明函数的作用域)寻找,依次向上。
上面renturn a+a1+a2+a3,其中a往全局作用域中找,a1往fn1()作用域中找,a2往fn2()作用域中找。
六、闭包
闭包:A函数里面嵌套B函数,B函数使用A函数的变量,那么B函数就是一个闭包。
使用方法:
1.函数里面嵌套函数。
2.函数作为返回值返回。
看例子:
let getPerson;
{
const id = 1;
getPerson = () => {
return getPersonById(id)
}
}
document.addEventListener('click', getPerson)
如果没有闭包,当 click 事件发生时,getPerson
就会调用失败。因为变量 id 被定义在块级作用域中, getPerson 在运行时是不可能拿到它的。
闭包的注意: 闭包是为了防止变量被垃圾回收机制收回,但是用的过多会产生内存泄漏!