JavaScript作用域学习笔记
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript作用域学习笔记相关的知识,希望对你有一定的参考价值。
1、局部变量与全局变量;
-
全局变量
首先要知道一点,全局变量的执行环境是全局作用域;全局作用域是最外围的一个执行环境,可以在代码的任何地方访问到。在浏览器中,我们的全局作用域就是
window
。因此在浏览器中,所有的全局变量和函数都是作为window
对象的属性和方法创建的。
var name = "1"; function doSomething(){ var anotherName = "2"; function showName(){ console.log(name) console.log(anotherName) } showName(); } console.log(name);//1 console.log(anotherName);//出错 doSomething();//1、2 showName();//出错
这里可以看到出全局变量的话,在那个位置都可以访问到;
注意:1、但是我们又在函数内部创建了变量anotherName
与函数showName()
,通过代码中的调用情况可以发现,我们在外部调用它时提示【出错】,因为他们处于局部作用域内(稍后讲),而 外部环境不能访问内部环境(函数内部)的任何变量与函数。-这就涉及到局部变量和作用域;
2、如果在函数内部的变量没有用 var 声明的话,也会变成全局变量;这个可以说的js的设计问题吧;
3、还有一种添加全局变量的方法就是直接给window对象添加一个属性。window.name=1;那么 name就变成了全局变量;
- 局部变量
局部作用域和全局作用域正好相反,局部作用域一般只在固定的代码片段内可访问到,最常见的就是函数内部,所以在很多地方就会有人把它称为函数作用域。(记住let(ES6)
之前无块级作用域)
function doSomething(){ var anotherName = "2"; function showName(){ console.log(anotherName) } showName(); } showName();//出错
原因是函数 showName()
,拥有局部作用域(即只能在函数内部访问)。因此它不能被外部所访问;
2、作用域链
了解下定义:
当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)。作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问。 作用域链包含了在环境栈中的每个执行环境对应的变量对象。通过作用域链,可以决定变量的访问和标识符的解析。 注意,全局执行环境的变量对象始终都是作用域链的最后一个对象。
var name = "test1"; function doSomething(){ var anotherName = "test2"; function showName(){ var author ="test3"; console(name) console(anotherName) // 在这里可以访问到 name 、anotherName 、author } showName(); // 在这里可以访问到 name anotherName ,不能访问到 author } doSomething(); // 在这里只能访问到 name
简单来说的话就是只能从“里”查询到“外”;而不能从“外”到“里”;
在 javascript 中,每个函数都有着自己的作用域,在每次调用一个函数的时候 ,就会进入一个函数内的作用域,而当函数执行返回以后,就返回调用前的作用域。
当代码在一个作用域内执行时,就会根据其上下文创建一个作用域链,该作用域链的用途就是控制当前作用域对于内所有的变量与函数的有序访问。作用域链的最前端,始终都是当前执行代码所在的作用域的变量对象。
在doSomething()中,这个函数是处于全局作用域下,它的作用域链包含着包含两个对象:1.它本身的变量对象(函数都会包含arguments
对象),2.全局环境对象。
之所以能在函数内部访问到变量name
,就是因为在它的作用域中,能找到它。
当然,正如上面所说的;它的作用域链:{它本身的变量对象,全局对象},沿着作用域链一级一级的查找搜索的过程,从作用域链的最前端(自己本身的变量)开始直到全局环境,最终没有查找到时将报错。
如果找到了 就返回这时候的变量
var name = "test1"; function doSomething(){ var anotherName = "test2"; function showName(){ var author ="test3"; var name="test4" console.log(name) console.log(anotherName) } showName();
} doSomething();//name 显示为“test4”;
栗子:运行doSomething(),进入到doSomething()的作用域,然后运行showName(),进入到showName()作用域;在里面运行console.log(name),然后这时候就往寻找变量name,直接在当前作用域找到,就返回了;
那么也可以看作是“后面的、离运行的函数最近变量对象”覆盖了“最外面了变量对象”,也符合我们前面的说法了;
其实只要记住权威指南里面的一句很关键的话,那就是:JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里;
var name = ‘test1‘; function showName() { console.log(name); } function show() { var name = ‘test2‘; showName(); } show();
看个栗子;按照我们前面的说法,
运行show();进入到show()作用域里面,然后运行showName();到了showName()作用域里面,此时运行console.log,
这时候寻找变量name,因为showName在当前作用域没找到,那就往上一级的作用域;记住:
JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里;
变量Name不是往show()里面寻找,而是在定义在showName()地方往上寻找,因此name=“test1”了;
不过这些都还是的作用域的初步了解。对于一些难点的话,还需要继续的学习才行;
以上是关于JavaScript作用域学习笔记的主要内容,如果未能解决你的问题,请参考以下文章