申明变量的方法:
es5: var 和 function 两种.
es6: var、 function、 let、 const、 import、 class 共6种
var 用来申明变量
function 用来申明函数
let 用来申明变量
const 用来申明常量
import 申明模块名
class 申明一个类
let命令
- 基础用法: 同var一样申明变量
{
var a = 1;
let b =10;
}
console.log(a); //1
console.log(b); //ReferenceError: b is not defined
这里的区别在于let申明的变量作用域只在所在区块内部有效,再看以下示例:
//示例一
for(let i = 0; i < 10; i ++){
}
console.log('let',i); //ReferenceError: i is not defined
for(var j = 0; j < 10; j ++){
}
console.log('var',j); // 10
- let不存在变量提升,所以一定要先申明再使用,否则报错
// 示例二
console.log(c); // ReferenceError: c is not defined
console.log(typeof(c)); // ReferenceError: c is not defined (万能的typeof现在也不安全了)
let c = 10;
console.log(d); // undefined。 (undefined表示变量已申明,但没有赋值)
console.log(typeof(d)); // undefined
var d = 23;
{
e = 23;
}
console.log(e); //23 (未申明的污染全局的变量)
console.log(typeof(e)); //number
观察以上三组表达式可以看出,var申明会提升变量,let申明不会提升变量
- 暂时性死区 : 只要块级作用域内部let申明了变量,该变量就绑定了这个作用域,不再受外部影响
// 示例三
var f = 233;
if(true){
console.log(f); // ReferenceError: f is not defined
f = 'abc'; // ReferenceError: f is not defined
let f;
console.log(f); //undefined
f = 'abc';
console.log(f); // abc
}
- 外层申明的变量f在有let申明的块级作用域内打印报错,说明不受外部申明影响
- 先赋值再申明报错,在块级作用域内,let申明前的这一部分就形成了let所申明的变量的死区
- 申明后可以正常赋值等操作
- 不允许重复申明
// 示例四
(function () {
var g = 1;
console.log(g); // 1
var g = 2;
console.log(g); // 2
}());
(function () {
var h = 1;
console.log(h); // 1
let h = 2;
console.log(h); // SyntaxError: Identifier 'h' has already been declared
}());
(function () {
let i = 1;
console.log(i); // SyntaxError: Identifier 'h' has already been declared
let i = 2;
console.log(i); // SyntaxError: Identifier 'h' has already been declared
}());
const 命令
- const 用来申明常量,一旦申明,它的值就不能变,所以需要在申明时完成赋值
const a = 123;
console.log(a); // 123
a = 'abc'; // TypeError: Assignment to constant variable.
- const 作用域与 let 相同
if(true){
const b = 5;
}
console.log(b); // ReferenceError: b is not defined
- const 也不能重复申明变量
const c = 132;
console.log(c); // 132
const c = 123; // SyntaxError: Identifier 'c' has already been declared
var c = 45; // SyntaxError: Identifier 'c' has already been declared
const 常量特殊的地方:
- const申明一个对象时,这个对象的地址是个常量,可以给对象添加东西进去,但不可以给这个对象重新赋值一个对象
const d = {};
d.k1 = 'v1';
d.k2 = 'v2';
console.log(d.k1,d.k2); // v1 v2
d = {'x':'y'} //TypeError: Assignment to constant variable.
- 同样的,数组也是需要占用地址的,因此const数组时,也可以对该数组进行数组元素操作
const e = [];
e.push('hello');
e.push('world');
e.push('!');
console.log(e.length); // 3
e = [1,2,3,4]; // TypeError: Assignment to constant variable.
- 申明冻结的对象,将不能对对象进行相关操作
const f = Object.freeze({});
f.prop = 123; // 不起任何效果
console.log(f.prop); //undefined
- 跨模块常量
const申明的常量只在当前代码块有效,如果想设置跨模块的常量,可用下面的写法:
- cons.js
export const A = 11111;
export const B = 22222;
export const C = 33333;
- test.js
// 第一种调用方法
import * as cons from './cons'
console.log(cons.A);
console.log(cons.B);
console.log(cons.C);
// 第二种调用方法
import {A,B,C} from './cons'
console.log(A,B,C);
全局对象的属性
- 全局对象是最顶层的对象,在浏览器环境指导是window对象,在node环境指的是global对象
- 在ES5中,全局对象的属性与全局变量是等价的:
// 在浏览器环境下
window.a = 1;
console.log(window.a); // 1
console.log(a); // 1
// 在node环境下
global.a = 1;
console.log(global.a); // 1
console.log(a); // 1
像在最顶层的 var a = 123; 这种申明不知不觉的就创造了全局对象的属性: window.a = 123; 这被认为是javascript的一大问题
- 在ES6中,为了改变这个现象,一方面规定var和function申明的全局变量依旧是全局对象的属性;另一方面规定let、const和class命令申明的全局变量不属于全局对象的属性:
function run() {
console.log('hello');
}
window.run(); // hello(浏览器环境)
global.b = 1;
console.log(window.b); // 1
console.log(b); // 1
let c = 3;
console.log(window.c); // undefined
console.log(global.c); // undefined
console.log(c); // 3