浅谈从一道面试测试题谈谈对Nodejs编程的理解
发布于 10 年前 作者 SweetHeartXi 19749 次浏览 最后一次编辑是 8 年前 来自 分享
var value1 = 0, value2 = 0, value3 = 0;
for ( var i = 1; i <= 3; i++) {
    var i2 = i;
    (function() {
        var i3 = i;
        setTimeout(function() {
            value1 += i;
            value2 += i2;
            value3 += i3;
        }, 1);
    })();
}
setTimeout(function() {
    console.log(value1, value2, value3);
}, 100);
value1=12
value2=9
value3=6
wdx345 <- add wechat

此段程序应该这样理解 循环语句条件下:

  1. 匿名自执行函数与闭包的关系
(function() {
  var i3 = i; 
  setTimeout(function() { 
  value1 += i; value2 += i2; value3 += i3;
  }, 1); 
})(); 

的作用域与setTimeout的闭包引用i在for循环下i对应的4,4,4的3个不同闭包实例相加value1=12

  1. 闭包外部匿名函数
function() {
  var i3 = i; 
  setTimeout(function() { 
    value1 += i; 
	value2 += i2; 
    value3 += i3; 
  }, 1); 
}

的作用域与setTimeout的闭包引用i2在for循环下i对应的3,3,3的3个不同闭包实例相加value2=9

  1. 闭包内部匿名函数
function() {
  value1 += i;
  value2 += i2;
  value3 += i3;
}

的作用域与setTimeout的闭包引用i3在for循环下i对应的1,2,3的3个不同闭包实例相加value3=6

形成3个闭包相加的三个匿名函数的事件循环的异步输出,即个匿名函数事件驱动的经典题目。 包含面向对象封装、继承、多态的思想,大赞!好题!

招node.js(附测试题)史上最奇特招聘

26 回复

三个闭包实例(value1,value2,value3)可以理解为三个异步事件,其中的每个事件机制当中由于存在简单的数学计算,每计算一次闭包setTimeout被实例化一次,循环计算3次闭包setTimeout被实例化3次,根据其作用域得出最终的结果。形成了for循环利用闭包成功处理3个作用域不同的事件,返回三个事件各自的结果。由于Nodejs的单线程不适合处理数学运算。所以这个程序对加深Nodejs作用域、闭包、事件驱动、异步I/O、单线程、不适合处理数学运算的理解有帮助。

@booxood 你用的啥工具

继承 在哪?

Markdown Markdown

看明白了,有意思

1.setTimeout 我写这里的目的确实是为了模拟node的异步 2.包含面向对象封装、继承、多态的思想,我这个我还真没看出来

@wdongxv 封装:闭包本身就是封装闭包内自变量的体现,即封装的思想 继承:闭包内的自变量可以访问外部函数的自变量直到全局变量,而闭包外的变量不可以访问闭包内的自变量可以理解为闭包内部自变量函数对象对外部函数对象的继承,即继承的思想 多态:三个闭包实例对象实例化闭包可以理解为三个对象实例化类,即多态的思想

对象是穷人的闭包,闭包是穷人的对象。

我原以为是9,9,6呢。原来 i 跑完都到4了。 闭包其实很好理解,就是在函数调用“()操作符”的那一刹那,把上下文环境“冻结”住,函数定义代码中的所有本地变量都冻住,复制出来一份,等待执行或者访问。函数定义代码外的变量是共享的。(函数定义和函数运行的有区别,好比lisp语言里的quote操作)

这题并不涉及到面向对象的思想。“多态”等名词是有公认的语义的,不可以随便改变语言这种人类通讯协议哈。

@LongHorn-C Nodejs开发指南 javascript高级特性里面就是这样讲解对应理解的,setTimeout(Vx, 1);可以理解为构造函数,value1,value2,value3是对其的三次实例化

@SweetHeartXi 他说滴构造和实例,就是函数定义和函数运行吧。似乎和面向对象不打架木关系。

@LongHorn-C 思想。。造不,相信你会达到这个层面的理解的

aaa.png

烦请楼主解释下这个阿里的面试题,有点不太懂

@lmyzzu 我的理解是这样的,这个主要是考虑JavaScript的面像对象的思想,第一种main()的方式,因为函数一开始并未定义foo变量所以第一个是undefined,然后第二个alert中,因为this此时的上下文应该是window,所以this.foo指的就是全局的foo值。第二种new main()方式,通过new的方式就定义了一个对象obj了,第一alert中,因为这个obj并没有foo这个属性,所以是undefined,第二个alert中,因为此时this指的对象就是这个obj,所以这个alert也是undefined。

@lanceng 同学 建议你买本犀牛书看看

最重要的是这段代码在node中和浏览器(chrome)中的执行结果是不一样的

@shadow88sky 把你想法说出来呗,干嘛说一半话。。。

@lanceng 同学你可能是对于js中作用域与作用域链还有变量声明提前的理解不太够,在两次main函数中,第一个alert被undefined的原因都是因为var foo的声明被提前,在当前函数中覆盖了全局下的foo声明,可以直接搜一下“js 作用域”看看。

@lmyzzu main()方法中,由于输出在定义之前,变量或者对象或者函数的声明会被提升到顶部,所以输出一个仅仅声明的变量会输出undefined。 new main() 中,相当于构建了一个实例出来,但其内部与上者分析相同,不同的是this会传递到实例中,因此在输出两次undefined之后,所创建的实例中会有this.fo这么个对象。

@wfsovereign 你的理解方式不错,就应该从程序运行环境分析

for (var i = 1; i <= 3; i++) {
  var j = i;
  (function() {
    var k = i;
    setTimeout(function() {
      console.log('i', i);
      console.log('j', j);
      console.log('k', k);
    }, 1);
  })();
}

i, j , k 的值分别是 4 4 4 , 3 3 3 , 1 2 3 value1 = 4 + 4 + 4 = 12 value2 = 3 + 3 + 3 = 9 value2 = 1 + 2 + 3 = 6

太透彻了 理解又加深一层

楼主在没有任何class和new的情况都能理解出封装,继承,和多态。实在令在下叹为观止,当场凌乱! Nodejs开发指南吗?记下了,一定不要买了! node4出来了,把 var 改成 let 一切都安静了。

异步事件都来了。。

回到顶部