主要变量声明方式var、let、const
变量声明的方法
- ES5只有两种声明变量的方法:
var
和function
- ES6添加了常用的
let
和const
,还有import
和class
var let const区别
- let添加了块级作用域;var没有块级作用域
- let约束了变量提升;var可以变量提升
- let有暂时性死区:ES6规定如果块内存在let命令,那么这个块就会成为一个封闭的作用域,并要求let变量先声明才能使用,如果在声明之前就开始使用,它并不会引用外部的变量。
let禁止重复声明变量,否则会报错;var可以重复声明
let不会成为全局对象的属性,是独立存在的变量;var在全局范围内声明一个变量,自动称为全局对象的属性
var a = 3; console.log(window.a); // 3 let b = 5; console.log(window.b); // undefined
const声明的是常量,声明变量时必须初始化,在后面出现的代码中不能再修改该常量的值。
- 注意:const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动,
- 对于简单数据类型(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量
- 对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,
const
只能保证这个指针是固定的,而指针指向的数据解构是不是可变的,就完全不能控制了, 如果真的想将对象冻结,应该使用
Object.freeze()
方法const a = 3; a = 5; // Uncaught TypeError: Assignment to constant variable const b; // Uncaught SyntaxError: Missing initializer in const declaration const b = []; b.push(11); console.log(b) //[11] Object.freeze(b);//冻结之后,将不能被改变 b.push(22); console.log(b)//[11] const c = {}; c['aa'] = 'aaa'; console.log(c);//{aa:aaa} Object.freeze(c);//冻结之后,不会被改变 c['bb'] = 'bbb'; console.log(c);//{aa:aaa}
顶层对象的属性
顶层对象,在浏览器环境指的是window
对象,在Node指的是global
对象,ES5中顶层对象的属性与全局变量是等价的
var a = 1;
window.a //1
let b = 2;
window.b //undefined
ES6规定:
- 为了保持兼容性,
var
和function
命令声明的全局变量依旧是顶层对象的属性; - 而
let
命令、const
命令、class
命令声明的全局变量,不属于顶层对象的属性。
global 对象
ES5中的顶层对象,本身存在一个问题,因为它在各种实现里面是不统一的
- 浏览器里面,顶层对象就是
window
,但是Node和Web Worker没有window
- 浏览器和Web Worker里面,
self
也指向顶层对象,但是Node没有self
- Node里面,顶层对象是
global
,但其他环境都不支持
综上所述,找到一个方法,可以在所有情况下,都渠道顶层对象,下面两种分方法勉强可以使用
//方法一
(typeof window !== 'undefined'?window:(typeof process === 'object' && typeof require === 'function' && typeof global === 'object')?global:this);
//方法二
var getGlobal = function(){
if(typeof self !== 'undefined'){return self}
if(typeof window !== 'undefined'){return window}
if(typeof global !== 'undefined'){return global}
throw new Error('unable to locate global object')
}
提案声明,在语言标准的层面,引入global
作为顶层对象,也就是说在所有环境下,global
都是存在的,都可以从它拿到顶层对象
垫片库system.global
模拟了这个提案,可以在所有环境拿到global
//commonJs的写法
require('system.global/shim')();
//ES6 模块的写法
import shim from 'system.global/shim';shim();
上面代码可以保证各种环境里面,global
对象都是存在的
//commonJS 的写法
var global = require('system.global')();
//ES6 模块的写法
import getGlobal from 'system.global';
const global = getGlobal();