常让人误解的一道js小题

时间:2023-03-09 16:45:27
常让人误解的一道js小题

一道小题引发的深思

今天无意中看到一个js笔试题,不由得想起初学js那会被各种题目狂虐的心酸,虽说现在也会被笔试题所虐,但毕竟比之前好了很多,下面就是我的个人理解,欢迎拍砖、指正:

var x = 1;
function printx(){
console.log(x); } function show(f){
var x = 2;
(function(){
f();
})()
} show(printx); //1

结果后台会打印1,而不是2。这有些不合常理,因为很多人会错误的认为:函数show中的f()在执行时,由于本作用域中没有x,所以会向上层作用域寻找x,当找到上层函数show的作用域中时发现 var x=2,这时就把x确定为2,否则会继续向上找,直至window。。。终于用到所谓的“作用域链”啦!大喜,其实这样想你就错了!

第一:首先有这么一个名词叫“*变量”,*变量是指:如果作用域(函数)A中使用到了变量x,而x并不是在作用域(函数)A中定义,那么对于作用域(函数)A来说,x就是A的*变量。

第二:理解这么一句话:js没有块级作用域,仅有的块级作用域是用函数来实现的,也就是说只有函数能创建出一块独立的作用域。if、for代码块都不行!所以本文中一个作用域可以理解为一个函数。

第三:函数的作用域在函数定义时就已经确定,而不是在执行时确定。

对于嵌套函数来说按照上述:寻找*变量是沿作用域链向上一层层查找,这样理解是对的。但是这样理解太片面,甚至会产生错误,就比如上面这道题。正确的理解应该是:寻找*变量时会到创建这个函数(作用域)的那个作用域中寻找。而创建这个函数的作用域并不一定是它位置上的父级作用域,(并不是在代码结构上包含,就是子父关系)上面这道题就是这种情况:函数show中把printx函数作为参数传入执行,在执行时会寻找创建它的那个作用域,很明显创建printx函数的作用域并不是show,而是全局window(因为printx函数在window中创建),所以它会寻找全局window中的x,此x为1。 所以会打印1,这才是正解。

不知道我解释的清不清楚,总之:函数使用*变量时,会到创建这个函数的那个作用域中寻找。“向父级作用域中寻找”可能会存在偏差。(不足之处欢迎指正!)

再补充两道,加深理解

本文的评论里还有两道更加通俗易懂的两道题,征得热心博友theWalker的同意,把他给出的两个demo也展示给大家,希望对你有所帮助:

function a(){
console.log(b)
}
function c(){
var b = 1;
a()
}
c() //b is not defined /****************************************/ var b = 2;
function a(){
console.log(b)
}
function c(){
var b = 1;
a()
}
c() //