Persistence of JQuery Functions

前端 未结 3 939
醉酒成梦
醉酒成梦 2021-01-17 18:53

I am trying to set up an on-click callback for an HTML that causes another node to become visible. Along the way, I was surprised to find out that the following two statemen

3条回答
  •  醉酒成梦
    2021-01-17 19:50

    When you use this in a JS function, it refers to whatever object the function is currently being called on, not where it was defined. For instance, you can define a function and copy it onto another object, like this:

    foo = {'name': 'foo'}; bar = {'name': 'bar'};
    foo.test= function() { console.log(this.name); }
    bar.test= foo.test;
    foo.test(); // logs 'foo'
    bar.test(); // logs 'bar'
    

    When you run foo.test(), this is set to point at foo; but when you run the same function as bar.test(), this is set to bar instead. There is nothing in the function that knows it was originally part of foo, so you basically have two separate but identical functions, like this:

    foo.test = function() { console.log(this.name); }
    bar.test = function() { console.log(this.name); }
    

    When you run $("#title").click($("#content").toggle);, a similar thing happens - you get a reference to the toggle function, and copy that function into jQuery's list of event handlers. When the callback runs, the $("#content") part is forgotten, just like the foo was above, so when the implementation in jQuery looks at this to see what you want to toggle, it will find the wrong thing.

    Exactly what it finds instead has an extra little quirk: jQuery sets this on click handlers to be the DOM element that was clicked on (there are various ways in JS of explicitly telling a function what it should use as this). The exact error comes about because the implementation of toggle is expecting a jQuery object, not a native DOM object, but even if a jQuery object was set as this, it would be the wrong node: you clicked on $('#title'), but want to toggle $('#content'), and jQuery has no way of knowing that.

    For completeness, to explain why $("#title").click(function() { $("#content").toggle(); } does work: here the function being saved in jQuery is an anonymous function, which doesn't make any use of this, so doesn't care what it gets set to when the callback finally fires. When the event runs (when you click) it calls toggle with an explicit context (the object returned by the $('#content') lookup), which is exactly what it's expecting.

提交回复
热议问题