全局对象self与window的区别

3,248 阅读2分钟

引子

在平时写代码的时候,window对象使用是比较频繁的,而我在看框架源码的时候发现了有这种写法:

var root = typeof self == 'object' && self.self === self && self ||
     typeof global == 'object' && global.global === global && global || this;

以上代码中,我们没有看到 window 对象的引用,而选择使用了self ,self 保存当前 window 对象的引用。

为什么使用self而不是使用window呢?而且”JS中还拥有self这个全局对象“有些小伙伴可能都不知道,那就让我们看看下面的内容:

在H5之前的window与self

在web页面环境下,默认下面这几种方案是等同的:

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

看到以上的情况后,window 与 self在多种情况下是相等的,那分开出现的意义是什么呢? 而真实情况其实是在H5之前,self的出场一般都是在当前页面有iframe嵌入的情况下,这样验证:

// true 表示作为iframe嵌入页面中,false 表示被iframe嵌入
parent  === self 

也可以这种理解:

在iframe内 self === parent // false,而主页面上是 self === parent // true

除此之外,在实际项目中基本没有什么出现的机会。

当然,这是在我们的HTML5新时代来临之前。而随着H5的新特性的到来,咱们的self对象摩拳擦掌、热泪盈眶,终于有了俺的用武之处。

self的春天:Web Worker、Service Worker

”众所周知的“,我们的Javascript脚本是单线程的,通俗一点就是可以叫做“窗体线程”。

主要是为了跟我们的浏览器窗口打交道。简单来说就是操作浏览器内的元素进行交互,所以我们可以使用window对象来获取想要的全局对象。

而Web Worker与Service Worker其实本质上是开启了另外的线程,而我们的Workers开启的新线程并没有所谓”窗体“这个概念。

这是浏览器”背着“我们悄咪咪的运行的线程,没有”窗体“意味着没有我们熟悉window对象,而这个时候:

我们的self就可以一脚踹开window, I can I up !

这时候在我们的Worker的上下文运行坏境中:self对象就变成了唯我独尊,window.self对象与window对象变成了局外人(不能使用),Web Worker栗子:

// 主线程
var worker = new Worker('work.js');
worker.postMessage('Hello World');

// Worker线程
self.addEventListener('message', function (e) {
  self.postMessage('You said: ' + e.data);
}, false);
  • 划重点:相比window,self 还能用于一些不具有窗口的上下文环境中,比如我们的双 Workers。所以,为了服务于更多场景,推荐使用更加通用的 self 对象。

  • 新人写作,轻喷,欢迎指正。 Love and Peace .