当我运行此代码时:
var Test = function() {
return this.stuff;
};
Test.stuff = 'Neat!';
document.write(Test() || 'Not neat.');
为什么我会'不整洁'?为什么我不能使用this.stuff
访问stuff属性?
答案 0 :(得分:5)
类方法和变量放在prototype属性上:
Test.prototype.stuff = 'Neat!'
构造函数(我假设这是你想要的,给定大写情况和this
)应该用new
运算符调用:
new Test()
并且它们不应返回值(您应该使用返回this
的默认值)
function Test(){
this.instanceVariable = 17;
//no return!
}
至于你的真正需要,你可以直接访问该功能及其属性
function Test(){
return Test.stuff;
}
但是,我并不是滥用像这样的命名空间函数的忠实粉丝。我更喜欢有一个命名空间对象来做事情
//in a real case I would probably use the module pattern for private variables
//but whatever...
var Namespace = {};
Namespace.stuff = 'Neat!';
Namespace.F = function(){
console.log(Namespace.stuff);
};
答案 1 :(得分:5)
这就是你所做的:
var Test = function() { //Test is a Function object
return this.stuff; //this is a pointer to an object, not Test
};
Test.stuff = 'Neat!'; //Add a property to Test
document.write(Test() || 'Not neat.'); //this has no property stuff
将代码的最后一行更改为:
document.write(Test.call(Test) || 'Not neat.'); //this now points to Test
您的代码无效的原因是因为this
指针指向:
new
关键字为前缀时创建的构造函数的实例。 (例如var foo = new Foo(); //the this in Foo points to foo [for the sake of explanation]
)。call
和apply
的对象作为第一个参数。您想要做的事情是:
var Test = function Temp() { //Test is a Function object, alias Temp
return Temp.stuff; //Temp is the same as Test, only locally
};
Test.stuff = 'Neat!'; //Add a property to Test
document.write(Test() || 'Not neat.'); //writes Neat!
如果您喜欢,请回复此答案。欢呼声。
答案 2 :(得分:3)
您从全局上下文中调用Test
,因此this
引用全局对象,因此this.stuff
引用全局变量stuff
undefined
这是假的。这就是您看到"Not neat."
您可以将其显示为Neat!
,如下所示:
window.stuff = 'Neat!';
var Test = function() {
return this.stuff;
};
alert(Test() || 'Not neat.');
<强>附录强>
以下是一种让this
作为封闭对象工作的方法:
var Test = function () {
return this.stuff;
};
var example = {
g: Test,
stuff: "Pretty neat"
};
alert(example.g() || 'Not neat.');
我们在这里通过目标对象调用Test
。
答案 3 :(得分:3)
虽然其他人已经发布了为什么会发生这种情况(对this
的理解不正确),但这是一个可靠的解决方案。
更新:正如Raynos在ECMAScript第5版中所指出的那样when using strict mode functions,使用arguments.callee
无效(它会引发TypeError)。因此,如果使用这种方法,应该谨慎行事。 (当使用[正确] ECMAScript第5版引擎时,没有理由使用arguments.callee
覆盖绑定到新范围的函数的名称 - 请参阅答案的结尾。)
var Test = function() {
// arguments.callee is the current function, if any
return arguments.callee.stuff
}
Test.stuff = 'Neat!'
alert(Test() || 'Not neat.') // Neat!
另一个是使用闭包:
var Test = (function () {
function fn () {
// closure over fn, which names this function-object
return fn.stuff
}
fn.stuff = 'Neat!' // here
return fn // do not combine with function declaration!
})()
Test.stuff = 'Neat!' // or here
alert(Test() || 'Not neat.') // Neat!
或者,直接关闭变量:
var Test = (function () {
var stuff = 'Neat!'
return function () {
// variable closure, no property
return stuff
}
})()
alert(Test() || 'Not neat.') // Neat!
或......有很多方法。
快乐的编码。
Aadit M Shah指出的另一种方法是使用函数标识符来引用当前函数:
var Test = function Temp () {
return Temp.stuff
}
Test.stuff = 'Neat!'
alert(Test() || 'Not neat.') // Neat! (But see below.)
正如Aadit指出的那样,根据ECMAScript 5th edition specification第99页,这是有效的:
可以从FunctionExpression的FunctionBody内部引用FunctionExpression中的标识符 允许函数以递归方式调用自身。但是,与FunctionDeclaration不同,FunctionExpression中的标识符不能被引用,也不会影响包含FunctionExpression的范围。
然而,某些浏览器(至少是IE9)错误地实现了这个(我不确定上面提到的行为是否在第3版中得到了明确定义)。考虑:
var x = function y () { return y }; y = 42; x();
在IE9中它将产生42,在FF8中它将产生函数对象。 IE9在这里不正确,因为它将y
作为封闭范围内的变量引入,ECMAScript禁止该函数用于函数表达式。以下是这种不正确的实现如何导致不同结果的上下文示例:
var Test = function Temp () {
return Temp.stuff
}
Test.stuff = "Neat!"
Temp = {}
alert(Test() || 'Not neat.') // 'Not neat.' in IE9, 'Neat!' in FF8
答案 4 :(得分:0)
stuff属性被分配给函数,但是从全局读取...这两个是单独的实体