这个问题归结为在 JavaScript 中调用函数的上下文。
在另一个函数中调用的函数在全局范围的上下文中执行。
在您的示例中,您有以下代码:
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return this;
})(testVal);
}
内部函数在全局范围内被调用,因此this
引用全局对象。在 JavaScript 中,在另一个函数中执行的函数是在其范围设置为全局范围的情况下完成的,而不是它所在函数的范围。这往往会使开发人员误会一点(或者至少,它对我有影响!)。
为了论证的缘故,假设 this 在浏览器中,因此this
指的是window
对象。这就是您被2
记录两次的原因,因为第二次运行时,会this.getVal
覆盖getVal
您运行时定义的方法var a = testFn(4);
。
JavaScript 范围在函数级别,因此每个函数都有自己的范围:
var x = 3;
function foo() {
var x = 2;
console.log(x);
};
console.log(x); //gives us 3
foo(); // logs 2
因此,您要做的是在 function的上下文中运行该内部testFn
函数,而不是在全局范围内。call
您可以使用方法运行具有特定上下文的函数。我还录制了一个截屏视频call
,apply
其中更详细地讨论了这一点。的基本用法call
是:
function foo() {...}.call(this);
这foo
在this
. 因此,第一步是确保在正确的上下文(testFn
方法的上下文)中调用您的内部函数。
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return this;
}.call(this, testVal);
}
第一个参数call
是上下文,后面的任何参数都作为参数传递给函数。所以现在内部函数在正确的范围内被调用,它不会添加getVal
到全局范围内,这是朝着正确方向迈出的一步:)
接下来,尽管您还需要确保每次调用时都是在新范围内进行的,因此第二次调用时testFn
不会覆盖。您可以使用关键字来执行此操作。这篇关于关键字的 SO 帖子非常值得一读。当您创建并执行 的新实例时,从而创建一个新范围。这个 SO question 也是相关的。this.getVal
testFn
new
new
var foo = new testFn()
testFN
您现在需要做的就是将您的声明更改a
为b
:
var a = new testFn(4);
var b = new testFn(2);
现在console.log(b.getVal(), a.getVal());
将根据需要给予2
。4
我在 JSBin 上放了一个工作示例,它应该有助于解决问题。请注意此示例如何this.x
在全局和函数内定义,并查看哪些被记录。玩这个,希望它可能有用。