ES6 声明变量的六种方法
Posted 水香木鱼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES6 声明变量的六种方法相关的知识,希望对你有一定的参考价值。
顶层对象的属性
顶层对象,在浏览器环境指的是window对象
,在 Node 指的是global对象
。ES5 之中,顶层对象的属性与全局变量是等价的。
window.a = 1;
a // 1
a = 2;
window.a // 2
上面代码中,顶层对象的属性赋值与全局变量的赋值,是同一件事。
顶层对象的属性与全局变量挂钩,被认为是 javascript 语言最大的设计败笔之一。
这样的设计带来了几个很大的问题
-
首先是没法在编译时就报出变量未声明的错误,只有运行时才能知道(因为全局变量可能是顶层对象的属性创造的,而属性的创造是动态的);
-
其次,程序员很容易不知不觉地就创建了全局变量(比如打字出错);
-
最后,顶层对象的属性是到处可以读写的,这非常不利于模块化编程。
另一方面,window对象有实体含义,指的是浏览器的窗口对象
,顶层对象是一个有实体含义的对象,也是不合适的。
ES6 为了改变这一点
一方面规定,为了保持兼容性,var命令和function命令声明的全局变量
,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性
。
也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。
var a = 1;
// 如果在 Node 的 REPL 环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1
let b = 1;
window.b // undefined
上面代码中,全局变量a由var命令声明,所以它是顶层对象的属性;全局变量b由let命令声明,所以它不是顶层对象的属性,返回undefined。
globalThis 对象
JavaScript 语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。
但是,顶层对象在各种实现里面是不统一的。
浏览器里面,顶层对象是window
,但 Node 和 Web Worker 没有window。
浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。
Node 里面,顶层对象是global,但其他环境都不支持。
同一段代码为了能够在各种环境,都能取到顶层对象,现在一般是使用this关键字,但是有局限性。
全局环境中,this会返回顶层对象。
但是,Node.js 模块中this返回的是当前模块,ES6 模块中this返回的是undefined。
函数里面的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');
;
ES2020 在语言标准的层面,引入globalThis作为顶层对象。
也就是说,任何环境下,globalThis都是存在的,都可以从它拿到顶层对象,指向全局环境下的this。
垫片库global-this模拟了这个提案,可以在所有环境拿到globalThis。
以上是关于ES6 声明变量的六种方法的主要内容,如果未能解决你的问题,请参考以下文章