1、var和let、const命令
作用域:ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效 { let a = 10; var b = 1; } a // ReferenceError: a is not defined. b // 1变量提升:var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错 // var 的情况 console.log(foo); // 输出undefined var foo = 2; // let 的情况 console.log(bar); // 报错ReferenceError let bar = 2;
2、块级作用域 : es5只有全局作用域和函数作用域,并没有块级作用域
ES6: function f1() { let n = 5; if (true) { let n = 10; } console.log(n); // 5 }3、块级作用域和函数声明 :es5规定,函数只能在顶层作用域和函数作用域内声明,不能在块级作用域声明
// 情况一 es5非法 es6合法 if (true) { function f() {} } // 情况二 es5非法 es6合法 try { function f() {} } catch(e) { // ... }4、const命令 :const声明一个只读的常量,常量的值不能改变,并且只声明不赋值也会报错,其他的属性跟let类似
const PI = 3.1415; PI // 3.1415 PI = 3; // TypeError: Assignment to constant variable. const foo; // SyntaxError: Missing initializer in const declaration5、ES6声明变量有6种方法
ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令,另外两种声明变量的方法:import命令和class命令。所以,ES6 一共有 6 种声明变量的方法
6、globalThis 对象
JavaScript 语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。但是,顶层对象在各种实现里面是不统一的。
浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。Node 里面,顶层对象是global,但其他环境都不支持。同一段代码为了能够在各种环境,都能取到顶层对象,现在一般是使用this变量,但是有局限性。
全局环境中,this会返回顶层对象。但是,Node 模块和 ES6 模块中,this返回的是当前模块。函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。不管是严格模式,还是普通模式,new Function('return this')(),总是会返回全局对象。但是,如果浏览器用了 CSP(Content Security Policy,内容安全策略),那么eval、new Function这些方法都可能无法使用。综上所述,很难找到一种方法,可以在所有情况下,都取到顶层对象。下面是两种勉强可以使用的方法。
// 方法一 (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'); };
