作用域
提起let和const两种声明变量方式,不得不先提起作用域。那么什么是作用域?
所有的编程语言中都可以在变量中存储值,并且可以修改和取出的能力。变量存储在哪?如何读取都是需要规则的,那么规则就是作用域。
常见的作用域分为几个类型:全局作用域、函数作用域、块作用域和动态作用域(this)
如果变量不在当前作用域,则js机制会顺着作用域链查找直至全局作用域。
全局作用域
函数外部(代码块外部)定义的变量(其实不尽然,代码块也可以声明全局变量,不推荐);
var a = 123;
function test(){
console.log(a);// 123
}
a = 123;
function test(){
console.log(a);// 123
}
两者之间的区别是使用var进行声明的变量是全局变量,不可以被删除;采用a=123的方式,定义的是全局变量window上的属性,可以被删除;
// 代码块中定义全局变量,不推荐使用
function test(){
a = 123;
}
函数作用域
函数内部定义的变量,就是局部作用域。函数作用域内,对外是封闭的,无法从外层的作用域直接访问
function test(){
var a = 123;
}
console.log(a);// a is not defined
如果想要获取函数内的变量,需要借助return或者闭包
function test(b){
var a =1;
var res = a+b;
function test1(){
return res
}
return test1()
}
console.log(test(2))
return是函数对外交流的出口,而return也可以返回的是函数,根据作用域链的规则,函数内部的子函数时可以获取函数作用域内的变量的
块作用域
ES6之前是没有块作用域的概念,因为用var定义的变量,由于变量提升,根据作用域链的规则,依旧可以获取变量。
function test(){
if(true){
var a = 1;
}
console.log(a) //1
}
function test(){
if(true){
let a = 1;
}
console.log(a) //a is not defined
}
动态作用域
俗称this指向问题;
独立函数,定时器的调用,this指向window
构造函数this的调用,this指向所调用的
不过需要额外注意箭头函数,this是在定义时就确定了
this的指向也会沿着作用域链查询
var a = 123
function test(){
console.log(this.a); // 123
}
test()
test.bind({a:666})();// 666
let和const
块作用域,let变量不会提升
{
let a = 123;
}
console.log(a); // a is not defined
var声明的变量是window上的属性,let不能通过window上的属性进行访问
var a = 1;
let b =2;
console.log(window.a);//1
console.log(window.b);//undefined
let不可以重复被定义
let a= 1;
let a=2;//报错
const用来声明常量
const a = 1;
a=2;//报错