本帖最后由 l676331991 于 2014-03-18 01:32:45 编辑

解决方案 »

  1.   

    我觉得按ES5标准来解析,正确值为3/6======================================================void function f0(){
        if(test=="right")score++;
    }()
     
    void function(){
        if(test=="wrong")score++;
    }()函数表达式分两种,常用的匿名函数表达式(Anonymous Function Expression AFE)和命名函数表达式(Named Function Expression NFE)。他们的共同点是,都是函数表达式,和函数声明有本质区别。唯一不同的是,命名函数表达式内部可以通过函数名来访问函数自身(arguments.callee被废除),而这个函数名却不对外渗透。参见js版置顶帖【你自认为理解javascript?】第二题。ES对这个特性的规定是使用类似"new Object()"的形式创建一个特殊对象,这个对象只有一个属性,命名函数表达式的名字,指向这个函数的引用,并将这个特殊对象压入匿名函数表达式的作用域链顶端。这就解释了本例中,命名函数表达式查找test得到继承自Object的("right"),而匿名函数表达式查找test得到的是window下的("wrong")。然而新版本已经更正了此问题,特殊对象已经不再继承自Object,因此,本例中匿名函数和命名函数内部的test都应该是window.test。测试chrome版本 33.0.1750.149 ,发现情况根本不是这样。分析得,从开发者工具F12粘贴入代码,代码是通过eval运行的,并且,使用了with(commandLineAPI){  // your code} 进行包裹。这个commandLineAPI对象提供了命令行可以直接访问的诸多API,而它是继承自Object的,因此代码从作用域链顶端的withBlock Scope找到test值。新建html粘贴入代码则此二例子test值皆为"wrong",表现正常。======================================================var e="right";
    try{
        throw new Error;
    } catch(e) {
        e="wrong";
        if(test=="right")score++;
    }
    if(e=="right")score++;catch块中的代码执行的时候,作用域链顶端会插入catchBlock Scope,这个异常e就是在这里声明的。按出题者所述,这个catchBlock Scope也是控制作用域的特殊对象,因此test值在这个特殊对象中找到,值为“right”。然而现在的浏览器对控制作用域的这种内部特殊对象都做了修正,他们不再继承自Object(同命名函数表达式)。至于变量e,catch内部的e来自catchBlock scope,因此catch内部修改e对外部没有影响。这个解释通了。相同的还有finally块。======================================================var f;
    void function f(){
    }
    if(typeof f=="undefined")score++;这个很好解释,命名函数表达式,f值只对函数表达式内部有效,不会渗透到外部作用域。因此f还是undefined。chrome解析正确。
    ======================================================var err;
    function a(){
        var m="right";
        var n;
        return function(){
            var err;
            return arguments[0].call(this,arguments[1]);
        }
    }
    try{
    var b=a();
    if(b(eval,"m")=="right")score++;
    } catch(err) {
    }
    这个涉及到js引擎对eval的处理。按题意,m值应该可以正确获取,但是现代浏览器对eval的处理更多的想一个保留字,eval使用不当会影响js的优化。因此现在的处理方式是,如果直接使用eval,则eval会引用当前EC的scope chain,如果间接使用eval,则scope chain中只有global。因此这个m应该是获取不到的。换成这样便可:var err;
    function a(){
        var m="right";
        var n;
        return function(){
            var err;
            return eval(arguments[0]);
        }
    }
    try{
    var b=a();
    if(b("m")=="right")score++;
    } catch(err) {
    }
      

  2.   

    是想说
    window.test = "wrong"  这个观点吗?
      

  3.   


    不是的,不是这么简单。你在chrome的开发工具的console下粘贴以下代码,就知道了://先粘贴这一段
    var test = "wrong"; 
    Object.prototype.test = "right"
    console.log(test);  //wrong对不对?//接着第二次再粘贴这段代码
    console.log(test);//right了?灵异了?
      

  4.   


    修正一下,问题不是这么重现的,应该是这样:Object.prototype.test = "right";
    console.log(test); //right
    test = "wrong";
    console.log(test); //怎么还是right?
      

  5.   

    window.console  不存在,所以console不属于window.至于chrome debug中console  跟window 是什么关系,为什么会读到window 上的属性与方法。
      

  6.   

    window 的实例化,比Object.prototype.test = "right";早。var $A1 = new Object();
    var $t1 = $A1.test;
    Object.prototype.test = "right";
    var $B1 = new Object();
    var $t2 = $B1.test;
      

  7.   


    我的例子里是直接用变量test,不是对象的属性。且看这个test为什么修改不了。Object.prototype.test = "right";
    console.log(test); //right
    test = "wrong";
    console.log(test); //怎么还是right?
      

  8.   


    Object.prototype.test = "right";
    console.log(test); //right
    test = "wrong";
    console.log(test); //怎么还是right?这个例子是我在chrome的console下手动一行一行敲的,和一起复制粘贴不是一回事,每一次敲回车是一次执行,而每次执行是在不同的with块中,因此就会出现这个怪异的问题。with块的临时作用域在上文有解释,即with(commandLineAPI){//code }。
      

  9.   

    1window 在页面开始时 通过  window = new Window()  生成了。
    你这Object.prototype.test = "right";在他生成后才设值的。
    2window.console  这方法不存在,    所以console 不属于window.
    3.搞不好  console是这样写的
    window.test = 'wrong';
    Object.prototype.test = "right";
    function wrapConsole(){
    var global={};
    for(var i in Object.prototype){
    global[i] = Object.prototype[i];
    }
    return function (key){
     
    // test  在 说不好是Object函数 的一个closure层里面的值;
    //  先找Object 中的 test,找不到window中的test.
    alert(global[key] || window[key]);
    }
    }
    myConsole = wrapConsole();
    myConsole('test');
      

  10.   

    貌似不对的。你一直在申明window是在设置原型的test属性之前就创建的,这能说明什么呢?       var $A1 = new Object();
            var $t1 = $A1.test;         //在设置原型的test值之前就取值,那自然
            Object.prototype.test = "right";
            var $B1 = new Object();
            var $t2 = $B1.test;
           var $t11 = $A1.test;     //敢问这里不是能取到right么?
    window.console明明是存在的。console是怎么实现的我已经在上文提出来了,我是来探讨的,交流的,不是来提问的。chrome的console的实现是这样:
    eval("with(commandLineAPI){"+code+"}");   //一个eval套一个with块
      

  11.   

    哦是存在。
    你这样看看。
    test = 'gss';
    Object.prototype.test = "right";
    var $c = window.console.log(test);
      

  12.   

    !!!,原来是这样的,上面的有一些观点是错的,不理了
    function MyConsole(obj){
    this.global = obj;
    }
    MyConsole.prototype.log = function(key){
    alert(this.global[key]);

    function myWindow(){
    this.test = 'wrong';
    this.console = new MyConsole(this);
    }
    myWindow = new myWindow();
    myWindow.console.log('test');Object.prototype.test = "right";var console = new MyConsole({});
    console.log('test');
      

  13.   

    该过来
    function MyConsole(obj){
    this.global = obj;
    }
    MyConsole.prototype.log = function(key){
    alert(this.global[key]);

    function myWindow(){

    this.console = new MyConsole(this);
    }
    win = new myWindow();
    win.test = 'wrong';
    win.console.log('test');Object.prototype.test = "right"; 
    var console = new MyConsole(new myWindow());
    console.log('test');
      

  14.   

    越说越乱。
    不过我注意到了一点。
    test = 'gss';
    ///放断点. 在console中看.Object.prototype.test = "right";///放断点. 在console中看.
      

  15.   

    不理了,霸王硬上弓。
    function MyConsole(obj){
    var top={};
    for(var i in Object.prototype){
    top[i]=Object.prototype[i];
    }
    var low = {};
    for(var i in obj){
    low[i]=obj[i];
    }
    function merge(o,d){
    for(var i in d){
    o[i]=d[i];
    }
    }
    merge(low,top);

        this.global = low;
    }
    MyConsole.prototype.log = function(key){
        alert(this.global[key]);

    function myWindow(){
        this.test = 'wrong';
        this.console = new MyConsole(this);
    }
    win = new myWindow();
    win.console.log('test');
     
    Object.prototype.test = "right";
     
    var console = new MyConsole(win);
    console.log('test');