文章目录
- 什么是作用域?
- 编译原理(作用域里是怎么有东西的?)
- 作用域是如何产生的?
- 作用域查找变量流程
- 总结
什么是作用域?
- 一句话概括:JS用来存储变量的地方
- 为了给大家更官方更准确的解释这里我们引用《你不知道的JS(上)》里面的解释:
几乎所有编程语言最基本的功能之一,就是能够存储变量当中的值,并且能够在之后对这个值进行访问和修改,事实上,正是这种存储和访问变量值的能力将状态带给了程序。
若没有了状态这个概念,程序虽然也能够执行一些简单的任务,但他会受到高度限制,做不到非常有趣。
但是将变量引入程序会引起几个很有意思的问题:这些变量存储在哪里,或者说“程序在执行时通过什么找到它?”
这些问题说明这需要一套设计良好的规则来存储变量,并且之后可以方便的找到这些变量,这套规则即被称为作用域
编译原理(作用域里是怎么有东西的?)
-
当我们定义一个变量并给他赋值时
var a = 1;
其实JS引擎分开了两步来执行:1.var a
声明这个变量,并将它放到当前作用域中去 2.a = 1
在作用域中找到变量a然后将其赋值1 -
函数亦是如此:当我们声明一个函数时
function fn(){}
JS引擎同样将其分开了两步来执行:1.function fn()
function相当于var,将fn加入到当前作用域中,并且值为函数体
**注:**函数声明分两种:1.function fn(){}
这种叫函数声明,当将fn加入到作用域中时它的值就直接是函数体了不经过undefined 2.var fn = function (){}
这种叫函数表达式,它的执行过程是先在作用域中添加fn变量此时的值为初始值undefined,然后当执行到这一行时才将函数体赋值给fn
具体变量是如何加进入作用域的请看我的预编译文档(记得点个小关注)
作用域是如何产生的?
- 当我们执行一个函数时会产生一个AO(函数作用域)
- 默认有一个GO(全局作用域)
作用域查找变量流程
根据上图我们模拟以下程序:
var name = 'luopo';
var age = 18;
function fn(){
var name = 'daniu';
console.log(name, age);
}
fn()
函数fn外面的变量的作用域就是我们的全局作用域
函数里面的变量的作用域就是我们的函数作用域
接下来我们看代码:
在全局作用域中我们拥有两个变量和值分别是:
name : ‘luopo’
age : 18
在函数fn的函数作用域中我们拥有一个变量和值分别是:
name : ‘daniu’
执行到console.log(name, age)
时:
我们的JS引擎就会找到作用域哥们们,首先找自己这个函数的作用域哥们,
-
问他:“我的函数作用域哥们你有看到name这个变量吗?我想要它的值”
-
fn函数作用域哥们回答:“有哒,它的值是’daniu’来给你把JS引擎好兄弟”!
于是我们的JS引擎就拿到了name的值为’daniu’
- 接下来JS引擎又问:“我的函数作用域哥们你那看看有没有age这个变量啊?我想要它的值”
- fn函数作用域老哥:“对不起这东西我这里没有呢,很抱歉没能帮到您,要不您去问问GO(全局作用域)爸爸吧!”
- 于是JS引擎屁颠屁颠的就跑来问全局作用域了:“爸爸你这里有没有age这个变量呀,我想要它的值”
- 全局作用域:“啊,爸发现啦,来儿子它的值为18,给你拿去吧!”
于是我们JS引擎就拿到了age的值为18
所以程序的执行结果为:'daniu'18
总结
函数作用域相当于全局作用域的儿子,儿子可以拿爸爸的东西,而爸爸不能拿儿子的东西,如果爸爸也都没有的话在“非严格模式”下会让爸爸添加一个这个新变量值为初始值undefined,如果在“严格模式”下则会抛出异常ReferenceError: xx变量 is not defined
,爸爸没有的话则直接抛出这个异常。
写的有很多不好的或者描述模糊的地方可以评论区多多指点,如果有写的错误的地方也希望大家能在评论区指点出来,谢谢大家,希望能帮到大家更好的学习前端,一起加油!!!