-1

我以为我已经了解了 javascript 中的上下文和范围。我不明白为什么在一种情况下代理/绑定有效,而在另一种情况下却没有。请问有人可以解释吗?

示例 1:代理(或绑定)工作:

function Cat(name){
    this.name = name;

    $("#cat").click(
        $.proxy(
            function(e){ this.meow(e); }
        , this)
    );

    this.meow = function(){ alert(this.name + "says meow"); }
}
var cat = new Cat();

示例 2:代理和绑定不起作用:

function Dog(breed){
    this.breed = breed;

    this.save = function(){
        var that = this;
        $.ajax({
            url: '/ajax/savedog.php', dataType: 'json',

            // This works?? Shouldn't scope be of .ajax()?
            data: this.breed, 

            // success: $.proxy(... // won't work? why?
            success: that.dogSaved, error: ajaxFail
        });
    };

    this.dogSaved = function(){ alert("Dog Saved"); }
}
var dog = new Dog();
4

1 回答 1

1

您正在复制this到“点击”处理程序that 内部。在外面做。

的值this会在每次函数调用时重新设置。因此,在您的“点击”处理程序中,this它不是一条狗,而是一个 DOM 元素。

注意 JavaScript 中的计算顺序也很重要。函数的参数在调用环境的上下文中被完全评估。在您的第一个示例中,this传入的值$.proxy()是正确的,因为它是构造函数上下文中的参数Cat,因此它正确地是一只猫。$.ajax但是,在构造函数中的调用中Dog,对的引用this.breed将不具有正确的值,因为它是在“单击”处理程序的上下文而不是构造函数的上下文中评估的。“数据”属性的值应该是that.breed在您that如上所述修复了初始化之后。

(另请注意,正如@Musa 指出的那样,Dog构造函数在语法上不正确;我认为这只是一个转录错误。)

编辑-我不确定您$.proxy()在更新的问题中尝试了什么,但是如果您像这样设置它,那么“成功”属性应该可以工作:

   success: $.proxy(that.dogSaved, that),

第一个参数$.proxy()是要调用的函数,第二个参数是调用函数时想要的值this。在这种情况下,您希望它是对 dog 对象的保存引用。但是请注意,它只有在调用“保存”函数并this设置为狗时才有效。也就是说,如果你在某个地方这样做:

   var fido = new Dog();
   fido.save();

那么事情应该会奏效。但是,如果您以某种方式使用该“保存”功能而this不是对狗的引用,那么它将不起作用。同样,如果在“Dog”构造函数中,您要将“that”的声明移出构造函数范围而不是“save”,那么如何调用“save”就无关紧要了,因为“that”总是对 dog 对象的引用。

于 2012-10-07T14:57:14.763 回答