我正在努力解决Javascript问题一段时间了,我无法在网上找到解释。我想这是因为我没有输入正确的关键字,这也可能与我为什么要在这方面苦苦挣扎有关。
我的基本假设是可以改变对象:
> var x = {'n': 2};
> x['n']
2
> x['n'] = 3;
3
pheww工作。但仍然(函数也是对象):
> var addn = function(a) {
var n = 2;
return n + a;
}
> addn(3);
5
> addn['n'] = 3;
3
> addn(3);
5
这次我无法改变'n'。有没有办法解决这个问题,同时保持功能的味道?而不是完全OO。我有一个相关的问题是如何维护函数的依赖性以便进行测试 - 再次没有OO?因为我正在寻找解决方案,但如果可能的话,我也想了解Javascript中的哪种机制让我苦苦挣扎。
干杯,
标记
声明: 通过提及OO,我不打算对OO说任何话。而且我也不打算对VI或Emacs说任何话。如果我以某种方式伤害了你的感情,请跳过这个。
答案 0 :(得分:15)
函数作用域中的私有变量和对象的属性是两个非常不同的东西。该函数内的var n
完全无法从该函数外部访问。
在代码运行之后addn.n == 3
,但每次运行函数时都会初始化设置为var n
的不同值。由于javascript的怪癖,一个函数无法真正访问它自己的属性非常容易。相反,通过传入参数function(n, a)
或使用对象来实现类似的东西。
var adder = {
n: 0,
addn: function(a) {
return this.n + a;
}
};
adder.n = 5;
adder.addn(2); // 7
答案 1 :(得分:5)
如果我理解你的问题,你可以给你的匿名函数命名并通过以下方式访问函数对象的属性:
var addn = function func(a) {
return func.n + a;
};
addn['n'] = 3;
addn(3); // returns 6
答案 2 :(得分:2)
对象属性和局部变量在很大程度上是不相关的:
var n
声明一个变量
确定它所处的功能(即
它在外面是不可见的
功能(通过闭合除外))。
addn['n']
添加名为n
的媒体资源
至addn
,相当于
addn.n
答案 3 :(得分:1)
由于JavaScript具有函数作用域,因此您可以使用函数来存储n的值,如下所示:
var addn = (function(n) {
return function(x) {
n += x;
return n;
}
}(2);
addn(3) // 5
addn(3) // 8
答案 4 :(得分:1)
最好完全忘记Javascript-land中“对象”的传统OO概念,并以封闭的方式来思考。我强烈建议您阅读jQuery创建者John Resig的this tutorial。
答案 5 :(得分:1)
每个函数都有一个scope
,基本上是在哪里/如何调用该函数的。当一个函数被调用时,它会创建一个新的函数执行上下文,将其压入调用堆栈。在该上下文中,该语言不会读取该行/语句,否则将不存在;在调用该函数之前,该行/语句不会发生。
您正在做的是为函数的属性分配一个值,而不访问该范围内的变量n
。
您不能从外部范围访问内部范围,因为内部范围不存在于外部但,您可以访问外部范围范围从内部范围开始,因为外部范围存在到内部范围。
此外,这里有一个供参考。
JavaScript基于prototype
;并非基于class
。 JavaScript中的一切都是对象,甚至是函数。阅读此书以了解更多有关为什么的信息(这是有关Quora的好帖子)-https://www.quora.com/Why-is-function-an-object-in-Javascript
答案 6 :(得分:0)
基本上,Javascript中的所有内容都是一个对象。如果你说
var a=3;
a['n']=4;
对'a'的引用仍将返回3,但a也有一个成员'n',其值为4.所以当你说addn['n'] = 3
时你要添加一个新成员来添加,而不影响函数无论如何。
我强烈建议阅读How good c habits can encourage bad javascript habits.在描述你可以做错的所有事情时,它是对象在Javascript中工作方式的一个很好的介绍。
答案 7 :(得分:0)
首先,你不是通过这样做来改变函数变量:
addn ['n'] = 3;
您定义的函数没有任何名称(也称为“匿名函数”)。您只需将该函数分配给名为addn
的变量。变量没有任何属性 - 它只是一个容器(除非变量引用数组)。所以addn['n']
什么都不返回。
如用户casablanca
所述,您可以将命名为func
,然后将其属性作为func.<propertyname>
访问(并修改)。