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. NEU 1681: The Singles

    题目描述 The Signals’ Day has passed for a few days. Numerous sales promotion campaigns on the shopping ...

  2. 用 nodejs 写一个命令行工具 :创建 react 组件的命令行工具

    用 nodejs 写一个命令行工具 :创建 react 组件的命令行工具 前言 上周,同事抱怨说 react 怎么不能像 angular 那样,使用命令行工具来生成一个组件.对呀,平时工作时,想要创建 ...

  3. hadoop2.x安装配置

    1.首先准备hadoop2.2.0的安装包,从官网获取,略. 2.加压安装包,进行配置.假设hadoop安装到/usr/hadoop-2.2.0目录,则进行如下配置: (1)/etc/profile配 ...

  4. 【Codeforces 776B】Sherlock and his girlfriend

    [题目链接] 点击打开链接 [算法] 将所有质数染成1,合数染成2即可 [代码] #include<bits/stdc++.h> using namespace std; #define ...

  5. 洛谷P1290 欧几里德的游戏

    题目:https://www.luogu.org/problemnew/show/P1290 只要出现n>=2*m,就可以每次把较大的数控制在较小的数的一倍与二倍之间,则控制了对方的走法: 每次 ...

  6. css3 appearance 改变元素外观

    h5 input标签的默认样式去除: 去掉date类型<input>框的叉叉: ::-webkit-clear-button { -webkit-appearance: none; } 去 ...

  7. 【旧文章搬运】PE重定位表学习手记

    原文发表于百度空间,2008-11-02========================================================================== 先定义一下 ...

  8. MyEclipse10.0的破解过程详细图解

    1 首先下载破解软件包:http://pan.baidu.com/s/1pLB6xEb 并解压: 2 按照百度经验操作即可http://jingyan.baidu.com/article/cbf0e5 ...

  9. View Controller Programming Guide for iOS---(八)---Using View Controllers in the Responder Chain

    Using View Controllers in the Responder Chain 响应链中使用视图控制器 View controllers are descendants of the UI ...

  10. 2.28 MapReduce在实际应用中常见的优化

    一.优化的点 Reduce Task Number Map Task输出压缩 Shuffle Phase 参数 map.reduce分配的虚拟CPU 二.Reduce Task Number Redu ...