请考虑以下代码:
function Dog()
{
this.foo = function() {};
this.walk = function()
{
if(canWalk())
{
alert('walking');
return;
}
alert('I have no legs!');
}
canWalk = function()
{
this.foo();
return false;
}
}
var instance = new Dog();
instance.walk();
使用“特权”canWalk()
方法的代码中存在一个错误,假设this
指针指向Dog
的实例。它实际上似乎指向令我困惑的全球对象!我已经读过,由于闭包,我可以在构造函数的范围内获取对this
的引用,然后在我的“特权”方法中使用该引用,但这看起来像是一个黑客。
我几乎没有掌握this
指针在各种情况下的行为。我知道“附加”到对象的方法将收到指向附加对象的this
。例如,foo.doStuff()
会有一个this
指向foo
个实例。
令人不安的是,虽然我认为自己很聪明并且在我的OBJECT上创建了“特权”方法,但似乎我实际上将功能转移到全球范围内!也许有一个名为init()
的全局方法(很可能)来自另一个库或文件而不是我自己的创建。如果我然后使用名为init()
的“特权”方法定义了一个漂亮的小封装对象,我将替换另一个全局init()
方法。
我的问题是,创建“特权”方法(以及相关字段)的最佳做法是什么,这些方法的作用域是它们所属的对象?我的示例对象的其他方法将提供私有或特权方法,同时还适当地确定范围。我不是在寻找符合要求的模糊解决方案,而是寻求最佳实践。
答案 0 :(得分:4)
请勿使用this
。将var self = this;
放在Dog函数的顶部并使用self
。这样你就会对狗有一个“安全”的引用。
在您的示例this
中应指向Dog
,除非我也遗漏了某些内容。
至于您的特权方法,您忘了定义变量。添加var canWalk;
还有另一种方式:关闭。我举一个例子:
function create_dog() {
function canWalk() {
return false;
}
function walk() {
if (canWalk()) {
alert("walking");
return;
}
alert("I have no hands!");
}
return {
"walk": walk // points to the function walk()
}; // this the API of dog, like public functions (or properties)
}
var dog = create_dog();
dog.walk();
现在您不需要this
或new
。另外你可以这样做:
function create_dog() {
function canWalk() {
return false;
}
function walk() {
if (canWalk()) {
alert("walking");
return;
}
alert("I have no hands!");
}
var dog = {
"walk": walk
};
return dog;
}
var dog = create_dog();
dog.walk();
因此,您可以在priveledges函数中引用dog
。 如果您不打算使用原型设计,我会建议关闭方法。
function my_func() {}
和
var my_func = function () {};
是等同的。如果你在两个函数之间有一个循环引用,并且你想强制使用define-before-use,那么后者可能很有用。
答案 1 :(得分:1)
首先,您需要在var
前面canWalk
。这样,canWalk
函数仅限于dog()
的范围,而不是隐式全局。
this
指向该函数的“所有者”。使用new
运算符时,该函数会创建自己的范围。因此,在dog()
的主体内,this
指的是狗实例对象。在walk
函数中,this
也引用了dog实例,因为您将walk
函数设置为dog
(this.walk = function () { ... }
)的实例。但是,在canWalk
中,没有所有者,因此this
指向全局对象window
。
我意识到我的解释可能会令人困惑,所以这里是我解释的代码注释版本:
var obj = {
'f': function () {
// this === obj, because obj "owns" this function
// In other words, this function is callable by obj.f()
},
'o': {
'f': function () {
// this === obj.o, because obj.o "owns" this function
// In other words, this function is callable by obj.o.f()
}
}
};
// The new operator essentially sets "this" within the
// function to an empty object and returns that object
var instance = new Dog();
function Dog() {
// this === instance, because of the "new" operator
// For demonstration
var self = this;
this.walk = function () {
// this === instance === self, because self/instance "owns" this function
// In other words, this function is callable by self.walk()
};
var canWalk = function () {
// What's the owner of this object? Nothing,
// so it defaults to the global object, window
// this === window
// Instead, we can access the Dog instance by
// using the "self" variable we set earlier.
// self === instance
};
}
希望能够解决问题。
答案 2 :(得分:1)
正如您所收集的那样,直接调用canWalk就意味着'this'关键字被设置为该函数调用的全局对象。
如果你想在当前狗的上下文中运行调用,你可以这样明确地这样做:
canWalk.call(this)