Javascript范围和self = this,_this = this,that = this

时间:2015-01-13 15:47:08

标签: javascript

为什么_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

3 个答案:

答案 0 :(得分:2)

致电时

new PersonClass()

第一次创建原型方法。

致电时

new PersonClass()

第二次,原型方法被替换,现在他们在关闭范围内有 last _this

因此,将原型方法移到构造函数之外。

答案 1 :(得分:2)

问题是您的内部函数的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

是的,那就做了。

嘿,看,它的作品! Here's the updated Fiddle

仅提供有关bind

的更多信息

让我说我有object

var myObj = {};

我们为object分配了一个属性:

myObj.test_property = "Hello World!";

我们可以通过bindthis从其他媒体资源中访问该媒体资源。

让我们说我们制作另一个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_functest_func2共享相同的范围。

Here's a JSFiddle illustrating everything I've said about bind

答案 2 :(得分:2)

您的代码存在很多问题。

  1. _this=this;

    创建全局变量window._this。  使用像jshint这样的工具来避免这种错误。

  2. PersonClass.prototype不应在构造函数中使用。您正在混合两种不同的对象创建模式。在构造函数中,你应该使用类似

    的东西

    this.getAge2 = function(){...}

  3. 不一定是一个错误,但是对于你的示例代码将此绑定到_这不是必需的。这仅适用于未在您创建的对象上调用函数的情况,例如,使用window.setTimeout(john.getAge, 100)

    之类的内容

    这会导致getAge函数在调用时从john对象中解除绑定。

  4. 这里的代码包含所讨论的更改(这并不是说我推荐这种模式):

    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