开发者

Please help me understand Javascript anonymous functions and jQuery .proxy()

开发者 https://www.devze.com 2023-03-29 01:29 出处:网络
I\'ve been trying to wrap my head around how javascript functions and scope work, and it just doesn\'t make sense to me. Can someone please explain why the following code outputs: \'animal says meow\'

I've been trying to wrap my head around how javascript functions and scope work, and it just doesn't make sense to me. Can someone please explain why the following code outputs: 'animal says meow' instead of 'kitty says meow'?

(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);

UPDATE

@FunkyFresh pointed out in the comments that console.log calls toString when it's passed an object, which by default returns the object's type (animal开发者_开发问答). When I update the above code with

animal.prototype.name = 'Mammal';

in the top block of code, and

kitty.name = 'Zax';

in the bottom, the console outputs 'Zax says meow', which seems about right.


(function($) {})(jQuery)

in this code (function($){}) declares the function. Then (jQuery) imediately calls the function passing in the jQuery object.

so the first block of code passes in jQuery and the window object. Animal is added to the window object, which is the global scope.

in the second block a click event is added to an element and kitty.sayHi is passed in as the event handler. However if the event handler was not proxied then the this keyword in the eventhandler would return the element that has triggered the event. So by using the proxy the scope of the eventhandler becomes kitty.

I hope that is correct, this is new to me also.


Update: kitty is an instance of Animal. So it'll never say kitty. All those proxy wrappers are careful misdirections.

Lets see:

(function($, exports){
  var animal = function(){};
  exports.Animal = animal;
})(jQuery, window);

Just a disguise to say: window.Animal = function(){};

You're creating an anonymous function passing jQuery and window object to it and executing it immediately. This creates Animal class in window scope


Now jquery.proxy allows you to change the context of a function: jQuery.proxy( functionName, context ) - so inside functionName, this refers to context (this == context).

$.proxy(kitty.sayHi, kitty) says call sayHi passing kitty as context.

Now kitty = new Animal (this is called a closure actaully since you're accessing parent function's variable), so 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);

So when the click handler is called, its actually Animal.sayHi.

0

精彩评论

暂无评论...
验证码 换一张
取 消