ES6学习--global 对象

在ES5 中,顶层对象的“本身”在各种实现里面是不统一的。比如:

  • 浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。

    大家都知道JavaScript 语言采用的是单线程模型,Web Worker 就是用来为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。除了window对象,Web Worker线程也无法使用document、parent这些对象。但是,Worker 线程可以使用navigator对象和location对象。
    更多Web Worker知识可参考:Web Worker 使用教程

  • 浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。

    我们在打开任何一个网页时,浏览器都会创建一个窗口,这个窗口就是一个window对象,也是我们在js里说的全局对象或全局作用域对象。self 也是指窗口本身,它返回的对象跟window对象是一样的,也就是当前 window 对象的引用,但是self 属性是只读的。self语法可以self或者window.self,所以window、self、window.self 是等价的:

    self === window // true
    self === window.self // true
    self.window === self // true
    self === window.self.self // true
    self === window.self.self.self // true
    self === window.self.window.self.window.self // true
    

    在Web Worker 里面self代表子线程自身,即子线程的全局对象。

  • Node 里面,顶层对象是global,但其他环境都不支持。

    node中global对象api如下:
    ES6学习--global 对象_第1张图片

同一段代码为了能够在各种环境,都能取到顶层对象,现在一般是使用this变量,但是也有一定的局限性:

  • 全局环境中,this会返回顶层对象。但是,Node 模块和 ES6 模块中,this返回的是当前模块。
  • 函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。

    如果时作为对象的方法运行,比如以下代码:

    var obj = {
        nameprintf:function(){
            console.log(this.name)
        }
    }
    obj.nameprintf();//返回{name: "obj", nameprintf: ƒ}
    

    如果作为函数运行,比如:

    var w = obj.nameprintf;
    w();//返回Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
    或者
    function w() 
    { 
        console.log(this); 
    } 
    w();// 返回Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
    

    但是,严格模式下,这时this会返回undefined:

    "use strict";
    function w() 
    { 
        console.log(this); 
    } 
    w();// 返回undefined
    
  • 不管是严格模式,还是普通模式,new Function(‘return this’)(),总是会返回全局对象。
    这里写图片描述
    但是,如果浏览器用了 CSP(Content Security Policy,内容安全策略),那么eval、new Function这些方法都可能无法使用。
    CSP定义了Content-Security-PolicyHTTP头来允许你创建一个可信来源的白名单,使得浏览器只执行和渲染来自这些来源的资源,而不是盲目信任服务器提供的所有内容。即使攻击者可以找到漏洞来注入脚本,但是因为来源不包含在白名单里,因此将不会被执行。
    有关CSP的更多详情可参考: HTML5安全:内容安全策略(CSP)简介、Content Security Policy 入门教程
    综上所述,很难找到一种方法,可以在所有情况下,都取到顶层对象。下面是两种勉强可以使用的方法:

    // 方法一
    (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');
    

    也可以利用system.global库,这个库引入了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();
    

    上面代码将顶层对象放入变量global。

你可能感兴趣的:(ES6,global,es6)