对JavaScript中的作用域的理解
在你不知道的JavaScript里面说过:作用域就是一套规则,用于确定在何处以及如何查找变量(标识符)的规则
害,就是能找变量的地方呗.
原文链接:https://www.jianshu.com/p/60ca27e185ec 这里写的是对原文的一些理解~
理解作用域
先看两段很简单的代码:
function foo(){
var a='haha';
console.log(a) //输出haha
}
foo()
在函数执行的时候,首先声明a,然后把a挂到foo函数的作用域上.等到需要读取a的值的时候(也就是console.log(a)执行的时候),就会从那个作用域把a读取出来.
下一段代码:
var b='xixi'
function foo(){
console.log(b) //输出xixi
}
foo()
声明b变量的时候,把b变量挂到了全局的作用域上.等待读取.由于foo函数的作用域上找不到b变量,于是沿着作用域链向上寻找.最后在全局作用域中找到了这个变量并且输出.
所以笼统一点说,在什么地方声明的变量,这个变量就会被挂到什么作用域上.在函数中找到的变量,可以说是在这个函数作用域找到的变量.在全局中找到的变量可以说是在全局作用域中找到的变量.
作用域的嵌套
在es6之前,只有全局作用域和函数作用域.函数作用域嵌套在全局作用域里面,函数作用域又可以嵌套新的函数作用域…听起来可能有点懵,看一张图马上就懂啦
查找变量的时候也是从里往外查找的~
作用域中变量的查找规则
先看一段代码
console.log(name) //输出undefined
var name = 'haha'
为什么会这样呢.因为var name = 'haha’这一段代码其实是分为两步走的.第一步发生在预编译的时候,把声明的变量a放到执行器上下文中,默认未赋值的属性为undefined.第二步发生在函数执行的时候,殷勤在作用域中查找这个a,找到a之后为它赋值.
由于在函数执行的时候,明显先执行console.log.再执行赋值.所以输出的就是undefined了.
上面的代码包含两种查找类型.输出变量的值的时候查找类型是RHS,赋值的查找类型是LHS.
为了输出变量的值,在作用域中查找变量是RHS,查找规则是从当前作用域开始找,如果找不到就一层一层往上级作用域查找.如果在全局作用域中还找不到就报错ReferenceError
为变量赋值的时候查找变量都是通过LHS,也会从当前作用域往上查找.但是如果变量未经声明直接赋值,在非严格模式下会直接把变量放到全局作用域中,造成污染.
词法作用域
官方说法是:词法作用域就是作用域的一种工作模型.(我jio得他的意思就是作用域按工作的方式分为两种类型,词法作用域就是其中一种类型)
作用域的工作模型有两种:
- 词法作用域
- 动态作用域
在JS中,作用域是由代码写在哪里决定的.而词法作用域就是由你在写代码时将变量和块作用域写在哪里所决定的,因此当词法分析器处理代码时会保持作用域不变.所以JS的作用域的类型就是词法作用域.
词法作用域的工作方式是:
- 在编译阶段就能知道变量在哪里,如何声明的.
- 能预测在执行代码的时候如何查找标识符.
- 由你在写代码时将变量和块作用域写在哪里所决定的,因此当词法分析器处理代码时会保持作用域不变.
关于eval with 和块级作用域的坑之后再补…