我正在尝试从在线教程中学习JS - http://ejohn.org/apps/learn/#33,你可以在那里测试JS代码。我试图将嵌套函数理解为其他函数内部的方法以及“this”关键字引用的内容。为什么我从下面放置上面的代码 - 它不起作用?有人可以解释JS的这个方面吗?
function Ninja(name){
this.name = name;
this.changeName = function(newname) {
this.name = newname;
this.anotherFunction = function(newname2) {
this.name2 = newname2;
}
}
}
var ninja = new Ninja("John");
assert( ninja.name == "John", "The name has been set on initialization" );
// ninja.anotherFunction("Luken");
// ninja.changeName.anotherFunction("Luken");
// Why both above functions doesn't work?
assert(ninja.name2, "It works?");
ninja.changeName("Bob");
assert( ninja.name == "Bob", "The name was successfully changed." );
答案 0 :(得分:3)
this
的值是在调用函数时确定的,而不是在定义函数时确定的。因此,在您的代码中,您必须使用this
的不同值:当调用ninja.changeName()
时,您不会为this
指定值,因此它可能是未定义的,也可能是正确的值现在
另一方面,new
运算符在调用函数this
之前设置了Ninja
。
您需要做的是在this
内“保存”Ninja
的值,以便内部函数继续使用它(而不是this
中的任何随机值他们被叫的时间)。这样做比听起来更简单:
function Ninja(name){
this.name = name;
var self = this; // Create a hidden reference to "this" that is only visible in
// any functions defined before we return
self.changeName = function(newname) {
self.name = newname;
self.anotherFunction = function(newname2) {
self.name2 = newname2;
}
}
}
这是有效的,因为JavaScript在您定义函数时会保留上下文的副本(=所有可到达的变量)。
答案 1 :(得分:1)
这很简单:
function Ninja(name)
{//this points to Ninja object inside constructor scope
this.name = name;
this.changeName = function(newname)
{//method of Ninja, this points to context object, ie Ninja
this.name = newname;//accesses the name property of Ninja
this.anotherFunction = function(newname2)
{//defines new method for this ==> Ninja object
this.name2 = newname2;//context object is Ninja
};
};
}
var foo = new Ninja('foobar');
foo.name;//foobar
foo.changeName;//function, is defined in constructor
typeof foo.anotherFunction//undefined because it's assigned when the changeName method is called!
foo.changeName('Me');
foo.name;//Me
foo.anotherFunction('You');//works: changeName was called, and assigned anotherFunction to foo (instance of Ninja)
foo.name2;//You
发生了什么:简单,通过调用changeName方法,anotherFunction
已定义并分配给this
。那时this
引用了Ninja
对象,因此该方法已分配给调用Ninja
方法的changeName
实例。在调用changeName
方法之前,anotherFunction
方法根本不存在。
虽然这可能看似无用或愚蠢,但确实有意义。你需要记住的是,函数/方法本质上是独立的对象。在这段代码中,它们恰好被定义为属性/方法,但它们不需要这样使用。回到上面的代码:
foo.name;//Me
bar = {};//some object
foo.changeName.apply(bar,['You']);
foo.name;//Me, nothing has changed, the changeName method was applied to the bar object
bar.name;//You, in the apply call, this pointed to bar, not foo
typeof bar.anotherFunction;//function
//You could even create the anotherFunction globally:
// JUST TO SHOW YOU CAN, THIS IS DANGEROUS
// ONLY USE THIS IF YOU KNOW WHAT THE POSSIBLE CONSEQUESES ARE!
foo.changeName.call();//in global scope
typeof antoherFunction;//function ==> this function is now globally available
changeName
方法可以应用于任何对象,添加新方法,将某些属性更改/添加到该特定实例。