我一直试图围绕javascript函数和作用域如何工作,这对我来说没有意义。有人可以解释为什么以下代码输出:'动物说喵'而不是'小猫说喵'?
(function($, exports){
var animal = function(){};
exports.Animal = animal;
})(jQuery, window);
(function($, Animal){
var kitty = new Animal;
kitty.sayHi = function(){
console.log(this);
console.log('says meow');
}
$($.proxy(function(){
$('#js_test').click($.proxy(kitty.sayHi, kitty));
}, kitty))
})(jQuery, Animal);
更新
@FunkyFresh在评论中指出,当console.log传递一个对象时,它会调用toString,默认情况下会返回对象的类型(animal)。当我用
更新上面的代码时animal.prototype.name = 'Mammal';
顶部代码块中的和
kitty.name = 'Zax';
在底部,控制台输出'Zax说喵',这似乎是正确的。
答案 0 :(得分:2)
(function($){})(jQuery)
在此代码中(function($){})声明该函数。然后(jQuery)立即调用传递jQuery对象的函数。
所以第一个代码块传递给jQuery和window对象。 Animal被添加到window对象中,这是全局范围。
在第二个块中,将click事件添加到元素中,并将kitty.sayHi作为事件处理程序传入。但是,如果事件处理程序未被代理,则eventhandler中的this关键字将返回触发事件的元素。因此,通过使用代理,事件处理程序的范围变为kitty。
我希望这是正确的,这对我来说也是新的。
答案 1 :(得分:2)
更新: kitty
是Animal
的实例。所以它永远不会说小猫。所有这些proxy
包装都是谨慎的误导。
让我们看看:
(function($, exports){
var animal = function(){};
exports.Animal = animal;
})(jQuery, window);
只是伪装成:window.Animal = function(){};
您正在创建一个匿名函数,将jQuery和window对象传递给它并立即执行它。这会在Animal
范围
window
类
现在jquery.proxy允许您更改函数的上下文:jQuery.proxy( functionName, context )
- 所以在functionName
内,this
引用context
(this == context
)
$.proxy(kitty.sayHi, kitty)
说调用sayHi
作为上下文传递kitty
。
现在kitty = new Animal
(因为你正在访问父函数的变量,所以这被称为闭包),所以this
- > Animal
(function($, Animal){
// create a new instance of Animal, assign it to local variable kitty
var kitty = new Animal;
// assign sayHi to kitty object
kitty.sayHi = function(){
console.log(this);
console.log('says meow');
}
// $() shortcut that says run this code on DOM ready
$($.proxy(function(){
// this proxy almost does nothing as we do not refer to this object insdie it
// says on click of js_Test, call kitty.sayHi with context = kitty
$('#js_test').click($.proxy(kitty.sayHi, kitty));
}, kitty))
})(jQuery, Animal);
因此,当调用click处理程序时,它实际上是Animal.sayHi
。