• eval运行脚本时,变量的作用域


    先看例子:

    demo1:

    var globalVar =123;
    function testEval(){
    eval(
    " var globalVar = 'global' ");
    }
    testEval();
    alert(globalVar);
    //123,ie与ff一样

    demo2:

    var globalVar =123;
    function testEval(){
    execScript(
    " var globalVar = 'global' ");
    }
    testEval();
    alert(globalVar);
    //IE下globalVar = "global",ff下没有execScript方法

    问题来了,eval和execScript在运行的时候变量执作用域不同,execScript又只支持IE。

    解决方法:

    把“var ”去掉或换成“window.”,这样eval运行过程中声明的变量就在全局域下,但是如果代码来自外部怎么办?

    于是想到了

    var globalVar =123;
    function testEval(){
    eval.apply(window,[
    " var globalVar = 'global' "]);
    //eval.call(window," var globalVar = 'global' ");
    }
    //但是不知道为啥IE不能改变eval执行的环境
    testEval();
    alert(globalVar);

    仔细验证发现,eval中的this也是window,也就是说只是在用var声明变量的时候,处理变量默认作用域的方式不同。后发现不仅在声明变量,使用function关键字声明函数同样存在这个问题。例如:

    function testEval(){
    window.eval(
    " function GlobalFun(){ return 'globalFun();';} ");
    //window.execScript(" function GlobalFun(){ return 'globalFun();';} ");
    //IE可以使用上面的方法,输出globalFun();
    }
    testEval();
    alert(GlobalFun());

    使用变量声明函数,不使用var关键字,同样可以解决这个问题:

    function testEval(){
    window.eval(
    "GlobalFun = function(){ return 'globalFun();';} ");
    }
    testEval();
    alert(GlobalFun());

    上面var可以查找替换,function处理起来就比较难了,还要搞个复杂的正则去做转换么,可能是个方法,但不现实。在jQuery中倒是有个解决方案:

    // Evalulates a script in a global context
    globalEval: function( data ) {
    if ( data && rnotwhite.test(data) ) {
    // Inspired by code by Andrea Giammarchi
    // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
    var head = document.getElementsByTagName("head")[0] || document.documentElement,
    script
    = document.createElement("script");

    script.type
    = "text/javascript";

    if ( jQuery.support.scriptEval ) {
    script.appendChild( document.createTextNode( data ) );
    }
    else {
    script.text
    = data;
    }

    // Use insertBefore instead of appendChild to circumvent an IE6 bug.
    // This arises when a base node is used (#2709).
    head.insertBefore( script, head.firstChild );
    head.removeChild( script );
    }
    },

    同样,mootools的源码也有这样一段:

    var exec=function(text){
    if (!text) return text;
    if (window.execScript){
    window.execScript(text);
    }
    else {
    var script = document.createElement('script');
    script.setAttribute(
    'type', 'text/javascript');
    script.text
    = text;
    document.head.appendChild(script);
    document.head.removeChild(script);
    }
    return text;
    }

    动态插入一个script,并执行代码,然后删除。看来现在解决方法不止一个了,以后使用时多加注意就好了。

    至于有人说的“eval和window.eval是不同的”不知道从何说起,至少“window.eval===eval”是成立的;

    上面全部代码都在IE8中运行,其他没有注释多个浏览器结果的,就表示还没有详细测试。

  • 相关阅读:
    【js】replace()
    【js】indexOf()
    【js】sort()
    【js】typeof与instanceof
    【js】with 语句
    跳出框架iframe的操作语句
    Mongodb启动命令mongod参数说明
    ERROR: child process failed, exited with error number 100
    SELECT控件add方法 ie 类型不匹配
    Red hat linux ping: unknown host www.baidu.com
  • 原文地址:https://www.cnblogs.com/ShepherdIsland/p/2148921.html
Copyright © 2020-2023  润新知