var window = this || (0, eval)('this')

在avalon源码中有这么一行代码,var window = this很容易理解

这里复习一下Global Object:

Global Object代表一个全局对象,js中不允许存在独立的函数,变量和常量,它们都是Global Object 的属性和方法,包括内置的属性和方法
但是Global Object实际并不存在,它是由window充当这个角色,并且这个过程是在js首次加载时进行的

在一个页面中,首次载入js代码时会创建一个全局执行环境,这个全局执行环境的作用域链实际上只有一个对象,即全局对象(window),并用this来引用全局对象。

那么,(0, eval)(‘this’)是什么?有什么用呢?什么情况下会执行呢?

(0, eval)('this')
  • 先从语法上来解读:

这里用了逗号操作符,逗号操作符总会返回表达式中的最后一项,所以0在这里基本上没有什么用,换成其他任意数值均可
然后通过”()”来立即执行这个表达式,返回eval
为eval传入’this’字符串,然后被当做实际的ECMAScript语句来解析

  • 这个表达式的作用:

因为在严格模式下,匿名函数中的this为undefined

为了防止在严格模式下window变量被赋予undefined,使用(0, eval)(‘this’)就可以把this重新指向window对象

  • 原理??

(0, eval)??这个执行完以后是什么呢?
答案是eval
那么和eval(“this”)就没有区别了呀,那么

又怎么解释呢?

===========================================================

这里要提出一个间接eval调用和直接eval调用的概念

  • 间接eval调用:

    (1, eval)('...')
    (eval, eval)('...')
    (1 ? eval : 0)('...')
    (__ = eval)('...')
    var e = eval; e('...')
    (function(e) { e('...') })(eval)
    (function(e) { return e })(eval)('...')
    (function() { arguments[0]('...') })(eval)
    this.eval('...')
    this['eval']('...')
    [eval][0]('...')
    eval.call(this, '...')
    eval('eval')('...')
  • 直接eval调用:
      eval('...')
    (eval)('...')
    (((eval)))('...')
    (function() { return eval('...') })()
    eval('eval("...")')
    (function(eval) { return eval('...'); })(eval)
    with({ eval: eval }) eval('...')
    with(window) eval('...')

    看了以上这些例子就可以明白了,(0, eval)(‘this’)是间接的eval调用,那么直接和间接调用之后的区别是什么呢?

      eval(); // <-- 调用括号左边的表达式 — "eval" — 计算出一个引用
    (eval)(); // <-- 调用括号左边的表达式 — "(eval)" — 计算出一个引用
    (((eval)))(); // <-- 调用括号左边的表达式 — "(((eval)))" — 计算出一个引用
    (1,eval)(); // <-- 调用括号左边的表达式 — "(1, eval)" — 计算出一个值
    (eval = eval)(); // <-- 调用括号左边的表达式 — "(eval = eval)" — 计算出一个值

    可以看出,间接调用计算出来的是一个值,而不是引用

    如ECMAScript所说,这是因为两个操作符 - (例子(1,eval)里的)逗号操作符和(例子(eval=eval)里的)等号操作符-对它的操作数执行了GetValue。因此,(1,eval)和(eval = eval)计算出一个值,而eval 和 (eval)计算出的是一个引用。

    且间接调用是在全局范围内执行执行代码的。

    就像你所看到的,第一个调用,是一个直接调用,方法中的this值是obj的引用(返回"obj.foo"),第二个调用,通过逗号表达式对它的操作数执行了GetValue,让this的值指向了全局对象

    讲到这里,再回来看看(0, eval)('this'),是不是就不难理解,其实这里的this就是指向全局对象
    这样在es5的严格模式下,也能获得全局对象的引用,而不是undefined了

    更多EVAL的详细内容可以在这里找到:http://www.oschina.net/translate/global-eval-what-are-the-options

  • 这里补充一点:

   严格模式下,外部访问不到eval()中创建的任何变量或函数,为eval赋值也会导致错误
  

  • 参考文章:

global-eval-what-are-the-options
indirect-function-call-in-javascript

----------------------------------------------
原文的博客地址:http://vico.me/ 似乎作者正在对博客进行改版,很多文章都找不到了,幸好这篇文章我在半年前前看的时候存了下来。

【转载】(0, eval)(‘this’)的更多相关文章

  1. (0,eval)('this')与eval的区别

    看doT源码的时候,看到了这么一句代码: global = (function(){ return this || (0,eval)('this'); }()); global.doT = doT; ...

  2. Global eval. What are the options?

    David Flanagan最近写了一个关于全局eval的简单表达式,可以用一行式子表示: var geval = this.execScript || eval; 尽管看起来很简短,但是跨浏览器的兼 ...

  3. [Effective JavaScript 笔记]第17条:间接调用eval函数优于直接调用

    eval函数不仅仅是一个函数.大多数函数只访问定义它们所在的作用域,而不能访问除此之外的作用域(词法作用域).eval函数具有访问调用它时的整个作用域的能力.编译器编写者首次设法优化js时,eval函 ...

  4. C# eval()函数浅谈

    <%# Bind("Subject") %> //绑定字段 <%# Container.DataItemIndex + 1%> //实现自动编号<%# ...

  5. ASP.NET Eval四种绑定方式

    1.1.x中的数据绑定语法 <asp:Literal id="litEval2" runat="server" Text='<%#DataBinde ...

  6. [转载] FFmpeg API 变更记录

    最近一两年内FFmpeg项目发展的速度很快,本来是一件好事.但是随之而来的问题就是其API(接口函数)一直在发生变动.这么一来基于旧一点版本的FFmpeg的程序的代码在最新的类库上可能就跑不通了. 例 ...

  7. 网站商务通链接快速标识v1.0.js

    js代码为: function getSwt(keys){ try{ if(openZoosUrl&&typeof(openZoosUrl)=="function" ...

  8. 浅谈 js eval作用域

    原文:浅谈 js eval作用域 就简单聊下如何全局 eval 一个代码. var x = 1; (function () { eval('var x = 123;'); })(); console. ...

  9. 全局作用域 eval

    eval是在caller的作用域里运行传给它的代码: var x = 'outer';   (function() {     var x = 'inner';     eval('x'); // & ...

随机推荐

  1. java 提高效率的做法

    可供程序利用的资源(内存.CPU时间.网络带宽等)是有限的,优化的目的就是让程序用尽可能少的资源完成预定的任务.优化通常包含两方面的内容:减小代码的体积,提高代码的运行效率.本文讨论的主要是如何提高代 ...

  2. 正则表达式pattern的匹配格式

    0> 匹配 -------------------------------------------------------------------------------- (pattern)  ...

  3. ruby require

    require一般用来加载其它的类,如:  #Ruby代码  : require 'dbi'   require "rexml/document" 但是上面加载的是标准类库里面的文 ...

  4. javascript event事件兼容性处理

    ie 6-8支持event事件,ff浏览器不支持 获取鼠标点击位置的坐标 document.onclick = function(){ alert(event.clientX +"-&quo ...

  5. springboot如何使用外部tomcat容器

    一般情况spring-boot-starter-web是自带tomcat(即springboot内嵌tomcat),所以打包直接生成jar包,用java -jar命令就可以启动. 但,有时我们希望用w ...

  6. (linux)platform_driver_probe与platform_driver_register的区别

      [驱动注册]platform_driver_register()与platform_device_register()          设备与驱动的两种绑定方式:在设备注册时进行绑定及在驱动注册 ...

  7. ⭐驱动之module_init/module_exit与系统启动关系

    在前面helloworld的编写里面,我们使用了两个宏分别是module_init和module_exit,这里分析下为什么使用这两个宏. 在写模块的时候有两个特殊的函数,分别是init_module ...

  8. jQuery常用插件大全(9)ResponsiveSlides插件

    ResponsiveSlides.js是一个展示同一容器内图片的轻量级响应式jQuery幻灯片插件(tiny responsive slideshow jQuery plugin).它支持包括IE6在 ...

  9. 一步一步学Silverlight 2系列(13):数据与通信之WebRequest

    概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...

  10. [Selenium] close alert window

    public static boolean isAlertPresent(WebDriver driver) { try { driver.switchTo().alert(); return tru ...