function getCtr(){
var i = 0;
return function(){
console.log(++i);
}
}
var ctr = getCtr();
ctr();
ctr();
我已经使用JavaScript五年了,但在最近的一次面试中,这个问题让我感到十分困惑。我尝试了我所了解的一切,但是仍然无法弄清楚。
你能否帮助我找出问题的输出和原因,这样如果我有未来的面试,我就可以更好地准备。
function getCtr(){
var i = 0;
return function(){
console.log(++i);
}
}
var ctr = getCtr();
ctr();
ctr();
我已经使用JavaScript五年了,但在最近的一次面试中,这个问题让我感到十分困惑。我尝试了我所了解的一切,但是仍然无法弄清楚。
你能否帮助我找出问题的输出和原因,这样如果我有未来的面试,我就可以更好地准备。
var ctr = getCtr();
getCtr()
函数,它会将i初始化为0,并存储对该函数的引用。function() {
console.log(++i)
}
在ctr中。因为该函数是在getCtr()的作用域内创建的,所以变量i仍然可以在存储在ctr
中的函数的作用域内访问。
第一次调用
ctr()
执行了console.log(++i)
,它对i进行了前自增,因此打印出1
。第二次调用执行相同的代码,使用相同的前自增,并打印出2
。
免责声明:我不是JavaScript开发人员。如果我犯了错误或使用了一些不受欢迎的措辞,请原谅。
所以你发布的代码输出 1
2
。然而,这段代码:
function getCtr(){
var i = 0;
return function(){
console.log(++i);
}
}
getCtr()();
getCtr()();
仅输出 1
1
!
区别在于如果使用 var ctr = getCtr();
保存 getCtr() 的引用,您将创建所谓的闭包。
因此,调用 getCtr()()
和 ctr()
之间的区别在于,ctr
在其作用域中定义了 i,并且由于 var ctr = getCtr();
保存了该作用域。因为引用被保存了,ctr
内部的函数能够始终对同一变量进行操作。
在那个函数中,return语句保存了i。因此,当仅调用var ctr = getCtr();
时,var i = 0;
变成了返回的函数:
function () {
console.log(++i)
}
变量 ctr 在外部函数 getCtr()
的作用域中具有 i
,而返回函数也在 getCtr()
的作用域中。
var ctr = getCtr()
ctr()
让我们使用你可能从传统继承为基础的面向对象编程语言所了解的术语来细分它:
// In javascript functions are first-class objects
// This function is being used like a class would be in Java
function getCtr(){
// You can think of this as a private variable of the getCtr "class"
var i = 0;
// Because it is returned, this is effectively a public method of getCtr
return function(){
// Which increments i and then prints it.
console.log(++i);
}
}
// This makes the variable ctrl an instance of getCtr.
var ctr = getCtr();
// This calls ctr's only public method.
ctr();
ctr();
因此输出将是“1, 2”。
这个问题的目的是测试您是否理解Javascript的原型继承,具有匿名函数和闭包的能力。
一个更明确的版本将会做同样的事情:
var myProtoype = function() {
var privateVariable = 0;
var privateMethod = function () {
privateVariable++;
console.log(privateVariable);
}
return {
publicMethod: privateMethod
};
}
var myInstance = new myPrototype();
myInstance.publicMethod();
myInstance.publicMethod();
这个函数是一个Javascript模块。你可以在《Javascript: the Good Parts》中找到关于它的详细阅读,这是一本非常好的书籍,我强烈推荐。模块使用Javascript闭包来创建私有变量,如果被分配给一个var,那么每次调用该var时,它将保留它的变量而不是重新定义变量。
一个模块的工作方式如下:
function moduleName(privateVar1){
var privateVar1;
var privateVar2;
return {
exposedFunction1: function (var1) {
// Do stuff... using private vars
return something;
},
exposedFunction2: function (var1, var2) {
// Do stuff...
return something;
}
}
}
var moduleInstance = moduleName(privateVar1);
moduleInstance.exposedFunction(var1);
好的,getCtr是一个返回另一个函数的函数。 它还包含一个名为“i”的变量,其值设置为0。 “i”也可以在返回的函数的作用域中使用。 在将其记录到控制台之前对“i”进行预增量操作会导致每次调用存储在“ctr”中的返回函数时,“i”都会增加1。