zoukankan      html  css  js  c++  java
  • JavaScript当中的eval函数

    eval函数

      eval函数接收一个由JavaScript语句组成的字符串,并且返回字符串中最后一条语句的返回值,如果最后一条语句没有返回值,那么eval函数返回undefined。如果传递给eval函数的不是字符串,那么传递什么,eval就返回什么。

    调用eval函数的三种情况

      当调用eval函数时,JavaScript会创建新的执行环境,总共有三种情形:

      1 直接调用

      直接调用时,eval函数相关的执行环境属性ThisBinding,LexicalEnvironment,VariableEnvironment的值如下:

      a) ThisBinding是调用eval函数时,调用方执行环境的ThisBinding

      b) LexicalEnvironment是调用eval函数时,调用方执行环境的LexicalEnvironment

      c) VariableEnvironemnt是调用eval函数时,调用方执行环境的VariableEnvironment

      假设有如下JavaScript代码(f在全局环境下被调用):

    function f() {
        var i = 1;
        
        eval("var y = 2; i = 3");
      
      alert(y);
    } f();

    当eval函数被调用时,执行环境栈如下图所示:

      需要注意的是,当新建一个执行环境时要进行标识符绑定,绑定的标识符放到执行环境VariableEnvironment指向的Lexical Environment中。由于eval函数的VariableEnvironment与调用方(即调用eval的函数f)的VariableEnvironment指向同一个Lexical Environment,因此,在eval中声明的局部变量y被绑定到调用方的Lexical Environment中,这导致当eval函数调用结束,与eval相关的执行环境被弹出栈顶,而在eval中声明的局部变量y在函数f中仍然可以访问得到。因此,上面代码中alert会显示2,而不是报错。

      2 间接调用

      所谓间接调用,即将eval赋值给另一个变量后在调用,如下面代码所示:

    var g = eval;
    g("var y = 1;");

      间接调用也会创建新的执行环境,不同之处在于新执行环境的ThisBinding,LexicalEnvironment,VariableEnvironment的值不同:

      a) ThisBinding为全局对象

      b) LexicalEnvironment为全局执行环境的的LexicalEnvironment

      c) VariableEnvironment为全局执行环境的VariableEnvironment

      假如有下面的代码:

    function f() {
        var i = 1;
        
        var gEval = eval;
        gEval("var y = 2; i = 3");
      
      alert(y);
    
    }
    
    f();

    当调用gEval时,执行环境栈如下图所示:

      可以看到,在gEval当中声明的变量都绑定到了全局执行环境当中,需要注意的是,gEval当中的变量i并不是引用的函数f的变量i,因为从gEval的作用域链访问不到函数f的局部变量i,此时gEval中的变量i就等价于没有使用关键字var声明了一个全局变量。函数f的alert语句仍然显示2,只是此时访问的y是全局环境中的变量y。

      3 严格模式下的eval

      在严格模式下,eval的LexicalEnvironment,VariableEnvironment指向属于eval自己的Lexcial Environment,而不是调用方的Lexical Environment,但是ThisBinding还是调用方的ThisBinding。同时,在严格模式下如果eval直接调用,那么eval的Lexical Environment的outer指针指向调用方的Lexical Environment,否则,如果是间接调用,那么eval的Lexical Environment的outer指针指向全局环境的Lexical Environment。

      假如有如下代码:

    "use strict"; //使用严格模式
    
    function f() {
        var i = 1;
        
        eval("var y = 2; i = 3");
      
      alert(y);
    
    }
    
    f();

    当调用eval时,执行环境栈如下图所示:

      从图可以看到,eval中声明的局部变量y被绑定到自己的Lexical Environment中,eval中的i访问的是函数f声明的局部变量i。由于变量y被绑定在eval自己的Lexical Environment中,因此当eval运行结束,相关的执行环境被弹出栈顶之后,函数f是访问不到变量y的,因此alert要报错。

    IE中的eval

      IE9之前,无论eval是直接调用还是间接调用,eval都当成直接调用处理,如果需要有间接调用的效果,可以使用IE提供的execScript函数。

    参考资料:

    JavaScript权威指南

    ECMA-262

  • 相关阅读:
    Java Object类
    Java StringBuffer类
    Java String 类
    vuex的使用总结
    vue 周期函数
    vue-cli keep-alive用法以及activated,deactivated
    vue-cli 跳转方式
    vue-cli watch/timer
    vue-cli 使用better-scroll
    vue-cli less使用
  • 原文地址:https://www.cnblogs.com/chaoguo1234/p/5384745.html
Copyright © 2011-2022 走看看