为什么_this.
不工作,但this.
正在工作。
我认为_this=this
的全部意义在于为调用对象函数提供一种机制,您有一个"保证"的引用,回到实例化的对象,因为它现在在对象函数的闭包中模仿传统的类行为。 我读了很多关于范围的文章,但由于某种原因,我只是没有看到它。 我错过了什么?
var PersonClass = function PersonClass(_name, _age) {
_this=this;
this.name=_name;
this.age=_age;
console.log("created "+this.name+":"+this.age);
function changeAge(num) {
console.log("changing age for:" + _this.name);
_this.age=num;
}
PersonClass.prototype.changeAge=changeAge;
PersonClass.prototype.getAge=function() {
console.log(_this.name+":"+_this.age);
return _this.age;
};
PersonClass.prototype.getAge2=function() {
console.log(this.name+":"+this.age);
return this.age;
};
};
// comments indicate what value is displayed in console
var john=new PersonClass("john",1); // john:1
var sue=new PersonClass("sue",2); // sue:2
john.getAge(); // sue:2
john.getAge2(); // john:1
john.changeAge(10); // sue
sue.getAge(); // sue:10
sue.getAge2(); // sue:10
john.getAge(); // sue:10
john.getAge2(); // john:1
问题是您的内部函数的scope
没有被解析为this
,因此,它们失去了对在new PersonClass()
实例化时创建的作用域的所有引用。bind
方法会将内部函数的scope
解析为父函数类的this
。
var PersonClass = function PersonClass(_name, _age)
{
var _this=this;
this.name=_name;
this.age=_age;
console.log("created "+this.name+":"+this.age);
this.changeAge = function(num)
{
console.log("changing age for:" + _this.name);
_this.age = num;
}.bind(this);
this.getAge = function()
{
console.log(_this.name+":"+_this.age);
return _this.age;
}.bind(this);
this.getAge2 = function()
{
console.log(this.name+":"+this.age);
return this.age;
};
};
// comments indicate what value is displayed in console
var john = new PersonClass("john",1); // john:1
var sue = new PersonClass("sue",2); // sue:2
john.getAge(); // sue:2
john.getAge2(); // john:1
john.changeAge(10); // sue
sue.getAge(); // sue:10
sue.getAge2(); // sue:10
john.getAge(); // sue:10
john.getAge2(); // john:1
是的,那就行了。
嘿,看,它有效!这是更新的小提琴
只是为了提供有关bind
的更多信息
假设我有一个object
:
var myObj = {};
我们为该object
分配一个属性:
myObj.test_property = "Hello World!";
我们可以通过其他属性访问该属性 bind
和 this
.
假设我们制作另一个属性,它是一个function
:
myObj.test_func = function()
{
alert(this.test_property);
}.bind(myObj);
等等,你猜这样行吗?
由于bind
方法,this
的范围被解析为myObj
。
因此,this.test_property
等于 myObj.test_property
,保留范围。
让我们更进一步...
我们将声明另一个函数:
myObj.test_func2 = function(val)
{
this.test_property = val;
}.bind(myObj);
现在,让我们运行一个测试:
myObj.test_func();
myObj.test_func2("Hello Dude");
myObj.test_func();
如您所见,test_func
和test_func2
共享相同的范围。
这是一个JSFiddle,说明了我所说的关于bind
的所有内容
当你打电话时
new PersonClass()
第一次,创建原型方法。
当您致电时
new PersonClass()
第二次,原型方法被替换,现在它们在闭合范围内具有最后一个_this。
因此,将原型方法移到构造函数之外。
你的代码有很多问题。
-
_this=this;
创建全局变量
window._this
。 使用像jshint这样的工具来避免这种错误。 -
PersonClass.prototype
不应在构造函数中使用。您正在混合两种不同的对象创建模式。在构造函数中,您应该使用类似的东西this.getAge2 = function(){...}
-
不一定是错误,但对于您的示例代码,不需要将其绑定到_this。仅当函数未在您创建的对象上调用时,才会使用此功能,例如,使用
window.setTimeout(john.getAge, 100)
这会导致 getAge 函数在调用时与 john 对象解除绑定。
这是包含所讨论更改的代码(这并不是说我推荐这种模式):
var PersonClass = function PersonClass(_name, _age) {
var _this=this;
this.name=_name;
this.age=_age;
console.log("created "+this.name+":"+this.age);
function changeAge(num) {
console.log("changing age for:" + _this.name);
_this.age=num;
}
this.changeAge=changeAge;
this.getAge=function() {
console.log(_this.name+":"+_this.age);
return _this.age;
};
this.getAge2=function() {
console.log(this.name+":"+this.age);
return this.age;
};
};
var john=new PersonClass("john",1); // john:1
var sue=new PersonClass("sue",2); // sue:2
john.getAge(); // john:1
john.getAge2(); // john:1
john.changeAge(10); // john
sue.getAge(); // sue:2
sue.getAge2(); // sue:2
john.getAge(); // john:10
john.getAge2(); // john:10
window.setTimeout(john.getAge, 200); //john:10
window.setTimeout(john.getAge2, 400); // incorrect