且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何将数据传递给JavaScript中的匿名函数?

更新时间:2023-01-12 11:03:11

你所遇到的是正确的行为 - 这不是一个好的行为,但它是语言的一部分。 this的值在每个函数定义内重置。有四种方式调用具有不同设置this的方法的函数。


  1. 常规函数调用
     myFunc(param1,param2); 

    这种调用函数的方式将总是将this重置为全局对象。


  2. 调用它作为一个方法
     myObj.myFunc(param1,param2); 

    这不奇怪的设置this 到该方法被调用的任何对象。

    p> myFunc.apply(myObj,[param1,param2])应用方法调用
    在这里,this==myObj这是一个有趣的 - 这里this设置为您传递的对象作为apply方法的第一个参数 - 它就像在没有该方法的对象上调用一个方法(小心函数被写为称为这种方式)。所有函数默认都有apply方法。

  3. 作为一个构造函数(带有new)
     myNewObj = new MyConstructor(param1,param2); 

    以这种方式调用函数时,this被初始化为一个新对象,该对象从函数的prototype属性继承方法和属性。在这种情况下,新对象将从MyConstructor.prototype继承。此外,如果您不明确返回值,将返回this。


解决方案 - 将this的外部值赋给另一个在函数中仍然可见的变量。我唯一需要改变的是调用变量that作为TörökGábor说 - 这是事实上的标准,可能会使你的代码更容易阅读为其他程序员。


When I pass 'this' to an anonymous function like so:

MyClass.prototype.trigger = function(){
    window.setTimeout(function(){this.onTimeout();},1000);
}

I get a "this.onTimeout is not a function"-error. I guess that 'this' is no longer available at the time the anonymous function is executing? So I've been doing this:

MyClass.prototype.trigger = function(){
    var me = this
    window.setTimeout(function(){me.onTimeout();},1000);
}

Is this really how you're supposed to do things? It kinda works, but it feels weird.

Then we have this example:

$(function(){
    function MyClass(){
        this.queue = new Array();
    }
    MyClass.prototype.gotAnswer = function(count){
        $('body').append("count:"+count+"<br/>");
    }
    MyClass.prototype.loadAll = function(){
        var count = 0;
        var item;
        while(item = this.queue.pop()){
            count++;
            var me = this;
            $.getJSON("answer.html",{},function(data){me.gotAnswer(count);});
        }
    }

    var o = new MyClass();
    o.queue.push(1);
    o.queue.push(2);
    o.loadAll();

});

This outputs:

2
2

Shouldn't it output:

1
2

instead? Then I discovered that putting the $.getJSON-statement in another function makes it all work:

MyClass.prototype.loadAll = function(){
    var count = 0;
    var item;
    while(item = this.queue.pop()){
        count++;
        this.newRequest(count);
    }
}
MyClass.prototype.newRequest = function(count){
    var me = this;
    $.getJSON("answer.html",null,function(data){ me.gotAnswer(count); });
}

This outputs:

1
2

(Or the other way around.) What's happening here? What is the right way to pass variables to an anonnymous function?

Sorry for the confusing and lengthy post.

What you are experiencing is the correct behavior - it's not a good behavior, but it's part of the language. The value of "this" is reset inside every function definition. There are four ways to call a function that have different ways of setting "this".

  1. The regular function invocation
    myFunc(param1, param2);

    This way of calling a function will always reset "this" to the global object. That's what's happening in your case.

  2. Calling it as a method
    myObj.myFunc(param1, param2);

    This unsurprisingly sets "this" to whatever object the method is being called on. Here, "this" == "myObj".

  3. Apply method invocation
    myFunc.apply(myObj, [param1, param2])

    This is an interesting one - here "this" is set to the object you pass as the first parameter to the apply method - it's like calling a method on an object that does not have that method (be careful that the function is written to be called this way). All functions by default have the apply method.

  4. As a constructor (with "new")
    myNewObj = new MyConstructor(param1, param2);

    When you call a function this way, "this" is initialized to a new object that inherits methods and properties from your function's prototype property. In this case, the new object would inherit from MyConstructor.prototype. In addition, if you don't return a value explicitly, "this" will be returned.

The solution you used is the recommended solution - assign the outside value of "this" to another variable that will still be visible inside your function. The only thing I would change is to call the variable "that" as Török Gábor says - that's sort of the de-facto standard and might make your code easier to read for other programmers.