资讯专栏INFORMATION COLUMN

阮一峰老师微博上的关于js作用域的一道题

DTeam / 563人阅读

摘要:补充我弄明白了上面的问题,重点在于函数的作用域,函数中定义的变量之前我说没用,为什么没用是因为函数是定义在函数下的,所以的作用域链是这样的因为函数是这样定义的,所以函数定义了变量,所以中的赋值给了函数的参数。

在阮一峰老师的微博上看到这样一道题

javascriptfunction a(x, y) {
    y = function(){
        x = 2;
    };
    return function() {
        var x = 3;
        y();
        console.log(x);
    }.apply(this, arguments);
}

a();

问:输出是多少?为什么?

我想到了答案,并且验证正确,小兴奋,在这里写下解题思路:

这道题的迷惑很多

return其实没用,代码可以变成

javascriptfunction a(x, y) {
    y = function(){
        x = 2;
    };
    (function() {
        var x = 3;
        y();
        console.log(x);
    }).apply(this, arguments);
}

a();

执行a();其实是执行

javascriptfunction() {
    var x = 3;
    y();
    console.log(x);
}apply(this, arguments);

其中:1. this是跟作用域(浏览器环境下是window,node环境下是global),因为是在跟作用域下执行的a();。 2. arguments是空,因为a();没有参数。

y();没用。因为y定因为函数首先定义了var x = 3;,所以console.log(x)就是3。因为作用域优先级是从内向外由高到低的,所以在这里var x = 3;的优先级是最高的,y();中不管定义的什么,都不会影响到x。所以之前分析了那么多,其实都没用啊!做题时读代码,顺序要从内部到外部(仅限于做题)~

问题:这道题如果将输出改成console.log(this.x),答案会是什么? 我认为是2,可是结果确实undefined,这是为什么呢? 目前我还没搞明白,求解。

javascriptfunction a(x, y) {
    y = function(){
        x = 2;
    };
    return function() {
        var x = 3;
        y();
        console.log(this.x);
    }.apply(this, arguments);
}

a();
补充

我弄明白了上面的问题,重点在于:1. 函数y的作用域,2. 函数a中定义的变量

之前我说y();没用,为什么没用?是因为函数y是定义在函数a下的,所以y的作用域链是这样的:

  

window

    

a

      

y

因为函数a是这样定义的:function a(x, y),所以函数a定义了变量x,所以y中的x = 2;赋值给了函数ax参数。并没有赋值给window作用域下的xconsole.log(this.x);this指的是window,所以输出为undefined。

如果将函数a的参数去掉,题目变成:

javascriptfunction a() {
    y = function(){
        x = 2;
    };
    return function() {
        var x = 3;
        y();
        console.log(this.x);
    }.apply(this, arguments);
}

a();

这样函数a中就没有x这个变量了,所以函数y中的x = 2;就会赋值给跟作用域下的x,所以console.log(this.x);的输出就会变成2

再将题目改一下,如果将函数y()定义在return 的匿名函数里面,题目变为:

javascriptfunction a(x, y) {
    return function() {
        y = function(){
            x = 2;
        };
        var x = 3;
        y();
        console.log(x);
    }.apply(this, arguments);
}

a();

console.log(x)会输出什么? 答案是2,因为此时y的作用域链是这样的:

  

window

    

a

      

匿名函数

        

y

因为匿名函数中定义了var x = 3;,所以函数y中的x = 2;就会修改匿名函数中的x的值,所以console.log(x)输出变成了3,

弄明白这道题的每一处细节,对理解javascript语言的作用域很有帮助。虽然这道题对编程本身没有什么意义。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/91478.html

相关文章

  • javascript学习笔记(1)

    摘要:关于作用域实现的描述任何执行上下文时刻的作用域,都是由作用域链来实现的。在一个函数被定义的时候,会将它此时的作用域链链接到这个函数对象的属性。参考资料鸟哥作用域原理理解作用域和作用域链阮一峰老师微博上的关于作用域的一道题 javascript作用域原理学习   在每次调用一个函数的时候,就会进入一个函数内的作用域,当从函数返回 以后,就会返回调用前的作用域。   ECMA262关于作...

    Chaz 评论0 收藏0
  • 几道前端面试小记

    摘要:全局环境调用函数的对象实际为,所以函数内的指向构造函数通过构造函造函数生成了一个新对象,指向这个新对象。学习前端一个月,上一周面试了大概多家,收获的却是寥寥。为了效率,前端各方面的内容都有涉猎,深度却相当不足,面试时暴露各种问题。 最近面试了不少家,苦于前端经验薄弱,被各种血虐。做了不少家面试题,把各种不会的回来再做一遍,作为经验总结吧。 1.如何最优性能去重一个数组? 方法有好多,比...

    tulayang 评论0 收藏0
  • 几道前端面试小记

    摘要:全局环境调用函数的对象实际为,所以函数内的指向构造函数通过构造函造函数生成了一个新对象,指向这个新对象。学习前端一个月,上一周面试了大概多家,收获的却是寥寥。为了效率,前端各方面的内容都有涉猎,深度却相当不足,面试时暴露各种问题。 最近面试了不少家,苦于前端经验薄弱,被各种血虐。做了不少家面试题,把各种不会的回来再做一遍,作为经验总结吧。 1.如何最优性能去重一个数组? 方法有好多,比...

    yhaolpz 评论0 收藏0
  • 几道前端面试小记

    摘要:全局环境调用函数的对象实际为,所以函数内的指向构造函数通过构造函造函数生成了一个新对象,指向这个新对象。学习前端一个月,上一周面试了大概多家,收获的却是寥寥。为了效率,前端各方面的内容都有涉猎,深度却相当不足,面试时暴露各种问题。 最近面试了不少家,苦于前端经验薄弱,被各种血虐。做了不少家面试题,把各种不会的回来再做一遍,作为经验总结吧。 1.如何最优性能去重一个数组? 方法有好多,比...

    ChanceWong 评论0 收藏0

发表评论

0条评论

DTeam

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<