JavaScript基础(11.JS难点:作用域详解)

来源:互联网 发布:机器人及人工智能大赛 编辑:程序博客网 时间:2024/06/09 14:00

先来个其他语言的例子:


不用仔细考虑它是什么意思,注意一点即可:

在内层大括号里面定义了一个string型的name变量,却在大括号外面用它,因此会报错。

我们继续:

在Python中:


情况一可以运行,而情况二会出错。


到底是为什么呢?

这里用简单的一句话来解释就可以:

在其他语言中是作用域以块({})为单位的,在Python里面作用域是以函数作为单位的。、


因此,函数内部定义的变量可以在函数内部任意使用,但是在函数外部就不能用了。

如这里的func()可以成功执行,但是print(name)就会出错。


接下来我们来看JS:

1.它默认是以函数为作用域的!所以它和Python是一样的。


成功!

对了,在console里面要换行的话,按shift+回车,否则就直接执行了,当时写这里的时候还不知道。


2.函数的作用域在没有执行之前(即在没有被调用之前)就已经创建!


3.函数的作用域存在作用域链,并且也是在被调用之前创建!


一个函数套一个函数产生作用域链。

现在这个函数执行后输出tony,解释见下


当console.log(xo)执行时候,首先找当前函数下的xo变量,找到tony,如果注释掉tony,它就会找外一层函数里面的xo变量,找到eric,如果再注释掉它,就会找外部变量xo,找到alex。如果alex不存在,就会报错!


我们继续深入:



这里的func函数的返回值为inner函数,因此ret()就相当于是调用inner函数

然而并不会输出alex,输出的是eric

先执行ret = func()

作用域链里面的xo就是eric,然后返回了inner。

开始执行ret() ,先找最内侧没有xo,然后找外层xo就是eric


继续深入:


这时候会输出的是tony;

因为前一步的ret = func() 执行后,func作用域链里面的xo变量由eric变成tony,

ret()执行的时候,现在最内层找,找不到,然后外层找,外层的xo变成了tony,所以输出tony



4.JavaScript特有的:内部局部变量会提前声明:

当解释器解释函数的时候,生成作用域链,在生成的同时,还会有另外一个操作:

声明所有的变量,但是并没有定义。


这句话的意思就是,函数里边如果第一行要使用某个变量,但是在第n行定义了它。这在C++里面会报错的,但是在JS里面会会输出一个undefined。