老生常谈的问题了,来做个自我检测吧,看看自己是否还记得这些八股文。
作用域(scope)
- 浅显的理解:作用域就是变量的可用范围(scope)。
- 为什么要有作用域:目的就是防止不同范围的变量之间互相干扰。
js
var x = 1; // 全局作用域
function f(){ // 函数级作用域
var y = 2
function g() {
var z = 3
}
}
如上述例子:
-
全局作用域:
- 不属于任何函数的外部范围称为全局作用域。
- 保存在全局作用域的变量称为全局变量。 优点:可反复使用。 缺点:全局污染--开发时禁止使用。
-
函数作用域:
- 一个函数内的范围称为函数作用域,保存在函数作用域内的变量称为局部变量,注意并不是所有 {} 扩起来的就是函数作用域局部变量。如下:
js
if(true){
var b = '小王'
}
console.log(b) // 小王
// {} 外也可访问到 b 变量,记着之前面试被问到过和我说{}括起来的就是局部变量,大家可以抓住机会反驳。
// 对象的{}也不是作用域,里边的属性也不是局部变量。
// 除函数{}之外其余的{},都不是作用域。
-
特例:形参变量也是函数内的局部变量。
-
局部变量的特点:优点:不会被污染,缺点:无法反复使用。
作用域链(scopes/scope chain)
- 在每个函数定义时,就已经规划好了自己专属的一个查找变量的路线图,称为作用域链。
- 一个函数可用的所有作用域串联起来,就形成了当前函数的作用域链。
- 当执行到某条语句时,JS引擎会自动延函数的作用域链查找要用的变量,查找路径如下:
如果最后找不到报错ReferenceError x is not defined
作用域本质
JS 中,作用域和作用域链都是对象结构。
- 全局作用域:其实是一个名为window的对象所有全局变量和全局函数都是window对象成员。
- 函数作用域:其实是js殷勤在调用函数时才临时创建的一个作用域对象。其中保存函数的局部变量,而函数调用完,函数作用域对象就释放了。
什么是闭包
- 既重用变量又保护变量不被污染的一种编程方法。
- 闭包就是每次调用外层函数时,临时创建的函数作用域对象。
- 为什么外层函数作用域对象能留下来,因为被内层函数对象的作用域链引用,无法释放。
- 只要希望给一个函数,保存一个即可反复使用,又不会被外界污染的专属局部变量时,就用闭包。
如何使用闭包
- 用外层函数包裹,要保护的变量和使用变量的内层函数。
- 在外层函数内部返回内层函数对象。
- 调用外层函数,用变量接住返回的内层函数对象。
js
//第 1 步 : 用外层函数包裹要保护的变量和内层函数
function fn() {
var total=1000
// 第2步:返回内层函数对象
return function pay(num) {
total-=num
console.log(total,num)
}
}
// 第3步:调用外层函数,用变量接住内层函数对象。
var pay = fn()
// pay 接住的就是fn()返回出来的内层函数对象。
一句话概括闭包: 外层函数调用后,外层函数的作用域对象,被返回的内层函数的作用域链引用着,无法释放,就形成了闭包对象。
闭包缺点: 容易造成内存泄漏,所以及时释放不用的闭包,将保存内层函数对象的变量赋值为null,导致函数名变量与内层函数对象分开。
点赞收藏支持、手留余香、与有荣焉,动动你发财的小手哟,感谢各位大佬能留下您的足迹。
往期热门精彩推荐
浏览器相关热门推荐
面试相关热门推荐
实战开发相关推荐
移动端相关推荐
Git 相关推荐
更多精彩详见:个人主页