Как изменить контекст функции в JavaScript - PullRequest
25 голосов
/ 08 октября 2009

Я пытаюсь понять, почему в javascript вы можете изменить контекст функции. Я ищу пример из реального мира или что-то, что поможет мне понять, как / почему этот метод используется и каково его значение.

Техника проиллюстрирована на этом примере (из 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." );

Ответы [ 6 ]

20 голосов
/ 08 октября 2009

jQuery использует это с хорошим эффектом:

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

Фактический код jQuery выглядит следующим образом:

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

Если бы он просто сделал callback( name, object[ name ] ), тогда this не будет установлен на текущий объект в вашем итераторе, и вам придется использовать параметр вместо этого. По сути, это просто делает вещи проще.

6 голосов
/ 08 октября 2009

Пожалуйста, посмотрите на этот пример:

<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>

Новое ключевое слово меняет контекст.

3 голосов
/ 03 апреля 2012

Пример из реального мира, с которым я столкнулся:

Если вы добавляете функцию в качестве обработчика события к элементу DOM и используете «this» внутри этой функции, «this» будет ссылаться на элемент DOM, к которому вы добавили обработчик события.

Но эта функция может быть методом объекта, и вы хотите, чтобы ключевое слово "this", используемое внутри нее, ссылалось на объект владельца ... поэтому вам нужно изменить контекст так, чтобы " this"не будет ссылаться на элемент DOM , но будет ссылаться на объект владельца .

Вы можете легко изменить контекст функции в jquery, используя функцию proxy (). Смотрите этот вопрос: jquery «this» проблема привязки для обработчика событий (эквивалент bindAsEventListener в прототипе) и первый ответ

3 голосов
/ 08 октября 2009

Это очень полезно при выполнении обратных вызовов из запросов AJAX:

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

На самом деле, это довольно дурацкий пример.

В jQuery есть множество его применений. Например, функция jQuery (). Get ():

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

Используются функции прототипа Array, но в контексте объекта jQuery.

1 голос
/ 01 августа 2013

bind-функция может быть тем, что вы ищете, bind-функция возвращает новую функцию в контексте, который вы передали, реальный сценарий может быть, когда вы используете jquery-делегаты для присоединения некоторого поведения к элементу dom, и вы хотите, чтобы обратный вызов выполнялся в другом контексте. потому что контекст по умолчанию в jquery delgate - это объект dom, связанный с обработчиком, что означает, что вы не можете получить доступ ни к какому свойству, кроме свойств, принадлежащих объекту dom

0 голосов
/ 28 марта 2013

Мне всегда нужно иметь другой контекст при использовании setTimeout, а в jQuery есть удобная функция $. Proxy , которая делает свое дело:

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

setTimeout($.proxy(iAmCalledAfterTimeout, {myProperty:"hello world"}), 1000);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...