1、作用域
- 简单地说,就是作用的范围,指它在函数在哪些范围内可以用,而在其他部分不可以,要用就得重新定义。
JavaScript中,变量的作用域有全局作用域和局部作用域两种。
1,全局作用域
不在任何函数内声明的变量(函数内省略var的也算全局)称作全局变量
就是在最外层定义的变量就被称为全局变量,全局都可以使用,所以是全局作用域。
2,局部作用域
在函数内声明的变量具有函数作用域,属于局部变量,就是在函数内部定义的变量,
只在函数内部有用,所以是局部作用域。
3,ES6的定义的块级作用域
声明变量的方法 有var let const
var 声明的变量可以变量提升 变量提升是将变量的声明提升至当前作用域的最顶部,而变量的赋值不会提升
let/const声明的变量让当前代码块变成一个暂时性的死区
内部变量不能在外部使用 他们声明的变量不存在变量提升
区别: const声明的变量必须给默认值 const声明的是常量不能重新赋值
const声明的变量的值如果是引用数据类型 则数据内部的数据可以修改
-
局部变量可以和全局变量重名,但是局部变量会屏蔽全局变量。
-
在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。
全局变量是使用相同的内存块在整个类中存储一个值.在整个函数中都适用。
作用域:
作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。可以说,变量和函数在什么时候可以用,什么时候被摧毁,这都与作用域有关。
1. 全局作用域(Global Scope)
在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域:
(1)最外层函数和在最外层函数外面定义的变量拥有全局作用域
(2)所有末定义直接赋值的变量自动声明为拥有全局作用域
(3)所有window对象的属性拥有全局作用域
一般情况下,window对象的内置属性都拥有全局作用域,例如window.name、window.location、window.top等等。
2. 局部作用域(Local Scope)
和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部,所有在一些地方也会看到有人把这种作用域称为函数作用域。
———————————————————————————————————
2、作用域链
作用域链:
当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain,不简称sc)来保证对执行环境有权访问的变量和函数的有序访问。 作用域第一个对象始终是当前执行代码所在环境的变量对象(VO)
function a(x,y){
var b=x+y;
return b;
}
在函数a创建的时候它的作用域链填入全局对象,全局对象中有所有全局变量
如果执行环境是函数,那么将其活动对象(activation object, AO)作为作用域链第一个对象,第二个对象是包含环境,下一个是包含环境的包含环境
function a(x,y){
var b=x+y;
return b;
}
var tatal=a(5,10);
这时候 var total=a(5,10);语句的作用域链如下
在函数运行过程中标识符的解析是沿着作用域链一级一级搜索的过程,从第一个对象开始,逐级向后回溯,直到找到同名标识符为止,找到后不再继续遍历,找不到就报错。
3、自由变量
假如在全局中定义了变量a,在函数中使用了这个a,这个a就是自由变量,可以这样理解,凡是跨了自己的作用域的变量都叫自由变量。
4、变量提升
变量提升,很简单,就是把变量提升提到函数的top的地方。我么需要说明的是,变量提升 只是提升变量的声明,并不会把赋值也提升上来。
比如:
我们定义三个变量:
复制代码代码如下:
(function(){
var a='One';
var b='Two';
var c='Three';
})()
实际上它是这样子的:
复制代码代码如下:
(function(){
var a,b,c;
a='One';
b='Two';
c='Three';
})()
这个时候就把变量提升了呀。
好,我们现在回到第一段code里面。为什么会报错呢?其实,根据我么根据上面变量提升原件以及js的作用域(块级作用域)的分析,得知 上面代码真正变成如下:
复制代码代码如下:
var v='Hello World';
(function(){
var v;
alert(v);
v='I love you';
})()
所以,才会提示说“undefined”。
从这里,我们也学习到,我们在写js code 的时候,我么需要把变量放在块级作用域的顶端,比如我在上面所举的例子:var a,b,c;。防止出现意外。