// var let const
// const => constant(常量,恒量)
{
var a=10;
let b=20;
const c=30;
}
console.log(a) //10
console.log(b) //报错, Uncaught ReferenceError: b is not defined
console.log(c) //报错, Uncaught ReferenceError: b is not defined
//A.var 没有块级作用域的概念,而let和const有
console.log(i);
var i=40; //console.log(i)不会报错,结果为undefined
let i=40; //console.log(i)报错,i is not defined
//B.var会进行变量提升,let不会进行变量提升
let d=40;
const e=50;
d=60;
console.log(d); //60
e=70;//报错,Uncaught TypeError: Assignment to constant variable
//C.const 是赋值一个常量,常量不可重复赋值
const实际上保证的,并不是变量的值不得改动,
而是变量指向的那个内存地址所保存的数据不得改动。
对于简单类型的数据(数值、字符串、布尔值),
值就保存在变量指向的那个内存地址,因此等同于常量。
但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,
保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的
(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,
就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
看两个例子:
//var
var a=[];
for(var i=0;i<10;i++){
a[i]=function(){
console.log(i);
}
}
a[6](); //10
//因为var没有块级作用域,所以for里面的i其实也是全局的i,当循环走完的时候,
i已经是10了,这时候我们再去走a[6](),其实走的是function(){console.log(i)}, 此时i为10,所以其实不管a[0],a[1],a[2]...a[9],最后的输出结果都是10.
//let
var b=[];
for(let k=0;k<10;k++){
b[k]=function(){
console.log(k);
}
}
b[6](); //6
//let会有自己的作用域,相当于循环10次会生成10个对应的作用域,
每个作用域的k值都会被保存,当执行b[6]()时,会找到对应作用域的k值,也就是6.
在 es5 中有两种声明变量的方式,分别是var 和 function,es6新增了四种,let、const、import和class。
JavaScript中有一个顶层对象的概念,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行,但是,顶层对象在各种实现里面是不统一的。
- 浏览器里面,顶层对象是window,但Node和web worker没有window
- 浏览器和web worker里面,self也指向顶层对象,但是node没有self
- Node里面,顶层对象是global,但其他环境都不支持
在浏览器指的是window对象,在node指的是global对象,在ES5中,顶层对象的属性与全局变量是等价的。ES6 为了改变这一点,一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。
var a=1;
window.a //1
let b=1;
window.b //undefined