简体   繁体   中英

How to change the context of a function in javascript

I'm trying to understand why in javascript, you might want to change the context of a function. I'm looking for a real world example or something which will help me understand how / why this technique is used and what its significance is.

The technique is illustrated using this example (from http://ejohn.org/apps/learn/#25 )

var object = {}; 
function fn(){ 
  return this; 
} 
assert( fn() == this, "The context is the global object." ); 
assert( fn.call(object) == object, "The context is changed to a specific object." );

jQuery makes use of it to good effect:

$('a').each(function() {
    // "this" is an a element - very useful
});

The actual jQuery code looks like this:

for ( name in object ) {
    if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
        break;
    }
}

If it just did callback( name, object[ name ] ) then this wouldn't be set to the current object in your iterator and you'd have to use the parameter instead. Basically it just makes things easier.

Please have a look at this example:

<script>
var el = document.getElementById('button');
el.onclick = function(){
    this.value = "Press Me Again"; //this --> now refers to the the element button not on the window
}

//Another Example:
var Person = function(name,location){
  this.name = name;
  this.location = location;  
  alert(this.location); 
}   
var p2 = new Person("Samantha","California"); //this refers to the instance of the function Person(Person now acts as a class)
var p1 = Person(); // this refers to the window(Person simply acts as a simple function)
</script>
<button id="button1">Press Me</button>

The new keyword changes the context.

It's very useful when doing callbacks from AJAX requests:

function Person(_id, _name) {
    this.id = _id;
    this.name = _name;
};

Person.prototype.sayHi = function(greeting) {
    alert(greeting + " from " + this.name);
};

Person.prototype.loadFromAJAX = function(callback) {
    // in this example, it's jQuery, but could be anything
    var t = this;
    $.get("myurl.php", function(data) {
        callback.call(t, data.greeting);
    });
};

Actually, that's a pretty crappy example.

There are tons of uses of it in jQuery. For example, the jQuery().get() function:

get: function( num ) {
    return num === undefined ?
        // Return a 'clean' array
        Array.prototype.slice.call( this ) :
        // Return just the object
        this[ num ];
}

It's using the functions of the Array prototype but in the context of the jQuery object.

A real world example that i've encountered:

If you add a function as an event handler to a DOM element and if you use "this" inside that function, "this" will refer to the DOM element that you added the event handler to.

But that function might be a method of an object and you want the "this" keyword used inside it to refer to the owner object...so you need to change the context so that " this " will not refer to the DOM element but will refer to the owner object .

You can easily change the context of a function in jquery using the proxy() function. See this question: jquery "this" binding issue on event handler (equivalent of bindAsEventListener in prototype) and the first answer

bind function might be what you're looking for, bind function returns a new function with in the context that you passed in , a real world scenario could be when you are using jquery delegates to attach some behavior to a dom element, and you want the callback being execute in a different context. 'cause the default context in a jquery delgate is the dom object that is bound to the handler , which means you can't access any property besides the properties that belongs to the dom object

I always find myself in the need of having different context when using setTimeout and jQuery has a handy function $.proxy which does the trick:

function iAmCalledAfterTimeout()
{
     alert(this.myProperty); //it will alert "hello world"
}    

setTimeout($.proxy(iAmCalledAfterTimeout, {myProperty:"hello world"}), 1000);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM