JS作用域精讲

什么是作用域?

  • 一句话概括:JS用来存储变量的地方
  • 为了给大家更官方更准确的解释这里我们引用《你不知道的JS(上)》里面的解释:
    几乎所有编程语言最基本的功能之一,就是能够存储变量当中的值,并且能够在之后对这个值进行访问和修改,事实上,正是这种存储和访问变量值的能力将状态带给了程序。
    若没有了状态这个概念,程序虽然也能够执行一些简单的任务,但他会受到高度限制,做不到非常有趣。
    但是将变量引入程序会引起几个很有意思的问题:这些变量存储在哪里,或者说“程序在执行时通过什么找到它?”
    这些问题说明这需要一套设计良好的规则来存储变量,并且之后可以方便的找到这些变量,这套规则即被称为作用域

编译原理(作用域里是怎么有东西的?)

  1. 当我们定义一个变量并给他赋值时var a = 1;其实JS引擎分开了两步来执行:1.var a声明这个变量,并将它放到当前作用域中去 2.a = 1在作用域中找到变量a然后将其赋值1

  2. 函数亦是如此:当我们声明一个函数时function fn(){}JS引擎同样将其分开了两步来执行:1.function fn()function相当于var,将fn加入到当前作用域中,并且值为函数体

**注:**函数声明分两种:1.function fn(){}这种叫函数声明,当将fn加入到作用域中时它的值就直接是函数体了不经过undefined 2.var fn = function (){}这种叫函数表达式,它的执行过程是先在作用域中添加fn变量此时的值为初始值undefined,然后当执行到这一行时才将函数体赋值给fn

具体变量是如何加进入作用域的请看我的预编译文档(记得点个小关注)

作用域是如何产生的?

  1. 当我们执行一个函数时会产生一个AO(函数作用域)
  2. 默认有一个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,爸爸没有的话则直接抛出这个异常。

写的有很多不好的或者描述模糊的地方可以评论区多多指点,如果有写的错误的地方也希望大家能在评论区指点出来,谢谢大家,希望能帮到大家更好的学习前端,一起加油!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章