JS作用域

JS中作用域有:全局作用域函数作用域,以及ES6中新增的块级作用域

全局作用域

  • 在全局声明的变量拥有的作用域叫做全局作用域,在页面任意位置都能访问到。
  • 全局作用域在页面打开时被创建,关闭页面时才销毁。

p.s.全局作用域中有个全局对象window,代表一个浏览器窗口,由浏览器创建,可以直接访问。

例如:

var a = "cat";
//a的作用域就是全局,在函数内部也能使用
function myFunction(){
}

函数作用域

  • 在函数内声明的变量拥有的作用域叫做函数作用域。
  • 调用函数时,函数作用域才被创建,函数执行完毕时就被销毁。
  • 每一次调用函数时都会创建一个新的函数作用域,它们彼此间相互独立。
var a = "cat";
//a是全局作用域,b在函数外面不能使用,因为声明在函数内部,作用域是函数作用域
function myFunction(){
//函数内部才能使用b
   var b = "dog";
}

注意: 函数作用域可以访问到定义在函数外全局作用域的变量,反之不行。

块级作用域

  • 块级作用域由{ }包括,if语句和for语句里面的{ }都属于块级作用域
  • var定义的变量没有块级作用域概念,可以跨块级作用域访问
  • letconst定义的变量只能在块级作用域里访问
{
	var a = 1
	let b = 2
	const c = 3
}
console.log(a) // 1
console.log(b) // 报错(let和const只能在块级作用域中访问)
console.log(c) // 报错
for(var a = 0; a < 3; a++) {
  var d = 5
}
console.log(a) // 3
console.log(d) // 5

for(let a = 0; a < 3; a++) {
  var d = 5
}
console.log(a) // 报错(for语句属于块级作用域)
console.log(d) // 5

在循环时使用varlet定义变量,得到的结果会完全不相同:

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10
var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6

因为let是块级作用域才有效,因此每一次循环的变量都是独立的,而var没有块级概念,因此每一次循环其实更改的是同一个变量。

同理:

for (var i = 0; i < 2; i++) {
setTimeout(() => {
console.log(i);
})
}

他会一直输出2,而不是0,1,这是js中的异步问题。等 i 循环完毕后再执行setTimeout,由于 i 是由var声明的,此时的 i 已经是2了。

而我们使用let声明时

for(let i=0;i<5;i++){
setTimeout(function(){console.log(i)})
}

就会正常输出,因为每一次循环都是独立的,因此每一次执行setTimeout时的 i 都是不一样的。

注意:try…catch中的err不属于任何作用域,只能被catch访问

javascript 完全手 javascript的全局函数_javascript