2009-10-08 4 views
25

Я пытаюсь понять, почему в javascript вы можете изменить контекст функции. Я ищу пример реального мира или что-то, что поможет мне понять, как/почему этот метод используется и каково его значение.Как изменить контекст функции в 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."); 
+13

Funny; Я нашел эту страницу, потому что мне нужно установить контекст для вызова, который я создаю, и не смог вспомнить синтаксис ... :) – rinogo

+1

+1 должно быть озаглавлено: «Как изменить контекст функции в javascript» (jk - спасибо за публикацию этого!) –

+0

+1 Я искал, как сохранить это согласование внутри класса ... – LoremIpsum

ответ

20

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 не будет установлен на текущий объект в вашем итераторе, и вам придется использовать этот параметр. В основном это просто облегчает ситуацию.

+2

Чтобы быть ясным, первый параметр '.call()' становится 'this'. Подробнее @ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call – EpicVoyage

6

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

<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

Это очень полезно при выполнении обратных вызовов с помощью 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: function(num) { 
    return num === undefined ? 
     // Return a 'clean' array 
     Array.prototype.slice.call(this) : 
     // Return just the object 
     this[ num ]; 
} 

Она использует функцию массива прототипа, но в контексте объекта JQuery.

3

Реальный пример, который я столкнулся:

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

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

Вы можете легко изменить контекст функции в jquery с помощью функции proxy(). Смотрите этот вопрос: jquery "this" binding issue on event handler (equivalent of bindAsEventListener in prototype) и первый ответ

0

Я всегда нахожусь в необходимости иметь различный контекст при использовании setTimeout и JQuery имеет удобную функцию $.proxy, которая делает трюк:

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

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

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

Смежные вопросы