JavaScript中的词法作用域(也叫 静态作用域)、动态作用域、函数作用域和块级作用域

静态作用域:

一段代码,在它执行之前就已经确定了它的作用域,

简单来说就是在执行之前就确定了其可以应用哪些地方的作用域(意指:该作用域下的变量)。

以下例子为《JavaScript权威指南》中经典的一个例子:

例一:

var scope = "global scope";

function checkScope() {
	var scope = "local scope";

	function fn() {
		return scope;
	}
	return fn();
}
checkScope(); // local scope

分析:

在函数checkScope中定义了函数fn,并将函数fn的返回值当作函数checkScope的返回值返回。
首先在函数fn的内部作用域中找变量scope,没找到变量,所以在函数fn当前所在的作用域下找变量scope,找到变量,直接返回,所以返回的结果是local scope。
 

例二:

var scope = "global scope";

function checkScope() {
	var scope = "local scope";

	function fn() {
		return scope;
	}
	return fn;
}
checkScope()(); // local scope

分析:

在函数checkScope中调用函数fn,函数fn同作用域下定义了变量scope,所以输出的是local scope。
在函数checkScope中定义了函数fn,并将函数fn当作函数checkScope的返回值返回,此时函数checkScope返回的是一个函数对象,不管这个返回的函数在哪里执行,当他定义时,他的作用域就已经确定了
所以首先在函数fn的内部作用域中找变量scope,没找到变量,所以在函数fn当前所在的作用域下找变量scope,找到变量,直接返回,所以返回的结果还是local scope。

 

修改词法作用域(不推荐)

      在代码书写时,作用域(词法作用域)就已经确定了,但是可不可以再修改呢?

      通过eval和with都可以用来修改词法作用域。

 

动态作用域:

函数的作用域是在函数调用的时候才决定的

调用某个变量,会从当前作用域逐级向上查找。
如果在当前作用域找到,就调用该变量,如果没找到,就继续向父级作用域查找,以此类推。
如果一直查找到最外层的全局作用域,都没有找到该变量,那么就表明没有该变量。

注意区别于作用域链函数定义时,不光确定了它内部的作用域,还确定了它外部的作用域,也就是作用域链。

// 父级作用域变量num1
var num1 = 1;

function fn() {
	// 当前作用域变量num2
	var num2 = 2;

	// 在当前作用域没有找到变量num1,向父级作用域查找,在父级作用域找到变量num1,直接调用
	console.log(num1); // 1
	// 在当前作用域找到变量num2,直接调用
	console.log(num2); // 2
	// 在当前作用域没有找到变量num3,向父级作用域查找,在父级全局作用域也没找到变量num3,证明该变量未定义
	console.log(num3); // ReferenceError: num3 is not defined
}
fn();

函数作用域

函数作用域的含义:属于这个函数的全部变量可以在整个函数的范围内使用及复用。

 

块级作用域

{

    let a = '块级作用域'

}
console.log(a);   //undefined

1.with

with也是块作用域的一个例子。

2.try/catch

try/catch的catch分句也会创建一个块作用域,其中声明的变量仅在catch内部有效。

3.let

let关键字可以将变量绑定到所在的任意作用域中,换句话说,let为其声明的变量隐式地劫持了所在的块作用域。

用let将变量附加在一个已经存在的块作用域的行为是隐式的。如果没有密切关注哪些块作用域中有绑定的变量,并且习惯性移动这些块或者包含在其他块中,就会导致代码混乱。

但是,用let进行的声明不会在块作用域中进行提升。声明的代码被运行之前,声明并不存在。

4.垃圾收集

5.let循环

for循环头部的let不仅将i绑定到for循环的块中,事实上它将重新绑定到了循环的每一个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值。

for(let i=0;i<10;i++){

console.log(i);

}

console.log(i);

6.const

ES6引入了const,同样可以用来创建块作用域变量,但是其值是固定的。之后试图修改值的操作都会引起错误。    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值