在阮一峰先生的微博上看到如许一道题:
javascript
function a(x, y) { y = function(){ x = 2; }; return function() { var x = 3; y(); console.log(x); }.apply(this, arguments); } a();
问:输出是多少?为何?
我想到了答案,而且考证准确,小高兴,在这里写下解题思绪:
- 这道题的疑惑许多
-
return
实在没用,代码能够变成
javascript
function a(x, y) { y = function(){ x = 2; }; (function() { var x = 3; y(); console.log(x); }).apply(this, arguments); } a();
- 实行
a();
实际上是实行
javascript
function() { 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
,这是为何呢? 现在我还没搞邃晓,求解。
javascript
function 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;
赋值给了函数a
的x
参数。并没有赋值给window
作用域下的x
,而console.log(this.x);
中this
指的是window,所以输出为undefined。
假如将函数a
的参数去掉,问题变成:
javascript
function 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 的匿名函数
内里,问题变成:
javascript
function 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言语的作用域很有协助。虽然这道题对编程自身没有什么意义。