【问题标题】:JavaScript losing "this" object reference with private/public propertiesJavaScript 丢失带有私有/公共属性的“this”对象引用
【发布时间】:2010-07-23 21:15:02
【问题描述】:
运行以下页面时出现以下错误:
“this.testpublic 不是函数”
test = function() {
var testprivate = function() {
this.testpublic();
}
this.testpublic = function() {
console.log('test');
}
testprivate();
}
new test();
显然,当testprivate 被调用时,“this”开始指向“window”而不是对象。
JavaScript 不应该在同一个对象中保留“this”上下文吗?
【问题讨论】:
标签:
javascript
scope
window
this
【解决方案1】:
调用 testprivate 时需要操作上下文。您可以使用 function.call 覆盖函数的范围。试试这个:
test = function() {
var testprivate = function() {
this.testpublic();
}
this.testpublic = function() {
console.log('test');
}
testprivate.call(this);
}
new test();
【解决方案2】:
问题在于 this 实际上从一开始就没有引用 test 对象。它总是指最近的封闭对象——在这种情况下是window。
test = function() {
var testprivate = function(say) {
console.log('test', say);
}
this.testpublic = function(say) {
testprivate('test', say);
}
testprivate();
}
x = new test();
这是可行的,因为据我了解,this 是在 call 时间确定的——并且它被锁定在最近的“封闭”对象*中,除非 call() 或 apply()被使用了。
*这可能有一个much更好的词,但我不知道它是不是在我的脑海中。如果有人知道,请赐教:-)
【解决方案3】:
不,不应该。该函数仅定义范围。
当您调用 foo.bar() 时,this(在 bar() 内部)是 foo。由于本例中没有显式的foo,所以默认为window。
(this 在使用 new 关键字时的处理方式有所不同,但不适用于该调用)
【解决方案4】:
正如 Sean 所说:您实际上并没有创建对对象的新引用(创建 this 上下文),因为您只是在调用构造函数 - 而不是利用构造函数来创建新对象。如果您使用 new 关键字,它的效果非常好。
由于调用时test()的作用域是window,所以在test()中调用的任何函数都会在test()中执行窗口 范围。
通过使用 new 关键字,您将一个新对象分配到内存 - 并创建一个新范围。
例如,在 firebug 中试试这个:
var myFunction = function() {
this.memberVariable = "foo";
console.log(this);
}
myFunction();
console.log(window.memberVariable);
var myObject = new myFunction();
console.log(myObject.memberVariable);
你会看到这个结果:
Window stats
foo
Object { memberVariable="foo"}
foo
Function 基础对象有一个方法,call(),正如 Craig 所述,它允许您明确指定函数应在哪个范围内运行:
var myFunction = function() {
this.memberVariable = "foo";
}
myFunction.call(myFunction);
console.log(myFunction); // "Function()"
console.log(myFunction.memberVariable); // "foo"
然而,这不是首选的做事方式,因为您实际上并没有在这里创建一个新对象,并且 typeof myFunction 仍然会返回“function”而不是“object”——当你真的只是想创建一个对象。