作用域
1 定义:
作用域日常有很多叫法比如
- this绑定的值
- this绑定值定义的执行上下文
- 一个变量的“生命周期”、
- 变量的值解析方案或词法绑定
作用域通俗的讲就是一个变量多长时间内保持一定的值。
2 分类:
作用域从范围上划分可以分成全局作用域或局部作用域(常见的是函数内部,也叫函数作用域)。
作用域按照工作模式分为词法作用域(静态作用域)或动态作用域。
2.1 全局作用域
1.在全局声明的变量生命周期将跨越整个程序(尽力少些,并且不好维护)。
2.在JS中没有用var 关键字声明的变量都是全局变量,能被程序中任何函数或方法访问。
aVariable = '我是全局变量'
function aTest() {
console.log(aVariable)
}
aTest() // 我是全局变量
就是因为任何一段代码可以随便改变它们,会引起之后一些的麻烦,相当的危险。
2.2 词法作用域
先说说词法,词法的中文意思是特定文本内语词的构成和使用的法则。
在大部分编译器也有这类似步骤,对源代码进行字符检查,如果是有状态的解析过程,就会赋予单词语义。
词法作用域是指一个变量的可见性,及其文本表述的模拟值。(大概先记着有个印象)
上个代码:
aVar = 'One'
function aFun() {
let aVar = 'Two'
return [1, 2, 3].map(function (item) {
var aVar = 'three'
console.log([aVar, item].join(''))
})
}
aFun() //three1 three2 three3
分析
换句话说,词法作用域是由你写代码时将变量或块作用域写在哪里所决定的。
2.3 动态作用域
在编程中最容易被低估或过度滥用的概念就是动态作用域。
aVariable = '我是全局变量'
function aTest() {
var aVariable = "我是TEST作用域的变量"
function childFun() {
var childVar = "我是child的变量"
console.log(aVariable, childVar)
}
childFun()
}
aTest() // 我是TEST作用域的变量 我是child的变量
但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到第一个值,最如果一直没有会一层层直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。
aVariable = '我是全局变量'
function aTest() {
var aVariable = "我是TEST作用域的变量"
childFun()
}
function childFun() {
var childVar = "我是child的变量"
console.log(aVariable, childVar)
}
aTest() // 我是全局变量 我是child的变量
动态作用域的核心是维护一个命名绑定栈的全局映射。
缺点:任何给定的绑定的值,在确定调用其函数之前,都是不可知的
(JS中this引用是动态作用域,尤其是事件处理函数中,如果点击按钮得到的this没用,会破坏程序的正常运行,是危险的)
2.4 函数作用域
在任意代码片段外部添加包装函数,可以将内部的变量和函数定义“隐藏”起来,外部作用域无法访问包装函数内部的任何内容。
function testFun(n) {
for(var i=0;i<n;i++);
console.log(i)
}
testFun(100) // 100
搜索在JS中所有在函数体内的var声明都会隐式地移到函数的顶部,JS重新排列变量声明的动作成为吊装(hoisting)
上面的代码实际重新排列就成这样了
function testFun(n) {
var i;
for (i = 0; i < n; i++);
console.log(i)
}
testFun(100) // 100
举个例子:
i = 100
function testFun(n) {
console.log(i)
var i = 111;
}
testFun()
console.log(i)
原因分析:
i = 100 // 定义全局的 i
function testFun(n) {
var i; // JS吊装排列
console.log(i) // 此时还没有定义说undefined
i = 111; // 定义当前作用域的 i
}
testFun()
console.log(i) // 打印全局变量i
【ES6的let填坑了,会直接报错 Uncaught ReferenceError: Cannot access 'i' before initialization(初始化之前不能访问')】
Hositing的概念真的理解了么,再来个测试~~~ do it~
i = 100
function testFun(n) {
console.log(i)
i = 111;
}
testFun()
console.log(i)