什么是作用域
这不是 js 中独有的概念,而是编程领域中通用的一个概念,就真个编程领域而言,作用域又分为静态作用域和动态作用域
静态作用域
JS 就是静态作用域
var x = 1;
function foo(){
//console.log("3" + x);
}
function bar(){
var x = 2;
//console.log("2" + x);
foo();
}
//console.log("1" + x)
bar();// 打印出来的是1
在上述例子中,bar函数 中调用 函数foo,用的不是 bar函数 中定义的 x,而是 foo函数 的 x。
简单来说函数在定义的时候就决定好了作用域。也就是当我们在调用一个函数的时候,如果这个函数的变量没有在函数中定义,就去定义该函数的地方寻找,这种查找关系在我们写函数代码的时候就已经确定了。
变量提升
很久之前申明变量使用的都是 var ,使用 var 申明的变量都是函数作用域(还有个块级作用域),且当局部变量与全局变量同名事,局部变量会覆盖全局变量
变脸申明提升
var x = 1;
function f(){
console.log(x);//这个地方输出的是undefinde
var x = 2;
}
//等同于下边的代码
var x = 1;
function f() {
var x;
console.log(x);//定义了但是没有赋值
x = 2;
}
函数申明提升
function f() {
x();
function x() {
console.log(1);
}
}
f();//输出的是1
//其实就是相当于函数的定义写在前边
//函数的调用写在后边
但是如果事函数表达式的写法,就会不一样。
function f() {
x();
var x = function() {
console.log(x);
}
}
f();//会出现一个报错
//Uncaught TypeError: x is not a function
//x不是一个函数但是我们却对其进行了函数的调用
其实这就如同我们之前所说的变量提前是类似的 x 的值为 undefined,所以这时候将其当作函数的调用肯定就是 TypeError。
块级作用域
块级作用域是由 let 和 const 进行申明,let申明变量,const申明常量。
function f() {
let y = 1;
for(let i = 0; i <= 1; i++){
y++;
}
if(true){
let fine = 2;
console.log(fine);//2
}
console.log(fine);//报错
console.log(i);//报错
console.log(y);//1
}
f();
块级作用域就是指在指定的代码块中才能访问,就是一对括号中(包括{},())。