2013-06-22 2 views
5

Я знаю, как использовать методы для изменения контекста вызова функции/метода: применить, связать, вызвать. Мой вопрос в том, есть ли способ проверить, был ли уже установлен этот параметр/метод?Проверка контекста JavaScript/метода

// given 
var beta; 

function alpha() { 
    return this; 
} 

function isContextSet (fn) { 
    /* check for context binding on fn */ 
} 

beta = alpha.bind("hello"); 

isContextSet(alpha); // returns false 
isContextSet(beta); // returns true 

Я думаю, я знаю ответ на этот вопрос уже, но думал, что я хотел бы спросить в любом случае, если для каких-либо других причин, чем: 1. подтверждает мое предположение, или 2. научиться чему-то. Я уверен, что я не первый, кто задал этот вопрос, но я понятия не имел, как на самом деле найти ответ, поскольку все, что я получаю, - это ответы на способы использования: .apply(), .call() или. связывания().

+1

Возможно, это помогает: [К какой объектной функции javascript привязана (каково ее «это»)?] (Http://stackoverflow.com/q/14307264/218196). –

+2

_ «уже имеет свой контекстный набор» _ Что вы подразумеваете под «уже»? '.apply()', '.call()' и '.bind()' не постоянно устанавливают 'this' для каждого вызова функции (отмечая, что' .bind() 'возвращает функцию _new_, которая постоянно имеет конкретное 'this', но фактически не изменяет функцию _original_). Каждый возможный способ вызова функции устанавливает 'this' в _something_ - это просто некоторые способы сделать это неявно, некоторые делают это явно ... – nnnnnn

+0

Я добавил код, чтобы показать, к чему я пытаюсь добраться. Я понимаю, как работают эти три метода, и я знаю, как проверить контекст функции/метода, находясь внутри тела вызова. Как вы проверяете контекст вне вызова, как я показал выше? Я не могу придумать способ сделать это вообще в JS. – kalisjoshua

ответ

2

No.

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

Функции могут быть связаны разными способами. Например, я мог бы связать его сам:

function bind(fn,ctxt){ 
    return function(){ 
     fn.apply(ctxt,arguments); 
    }; 
} 

Или я мог бы связать его с Function.prototype.bind или подкладкой, которая делает то же самое, или _.bind Underscore в. Я мог бы связать его с начальными аргументами в дополнение к контексту. В каждом случае невозможно определить, что произошло, фактически не выполняя функцию.

Связывание является лишь одним из многих способов преобразования одной функции в другую. Я мог бы также преобразовать функцию, чтобы выполнить одну секунду с этого момента, или выполнить два раза. Нет ничего волшебного в привязке; он просто создает новую функцию, основанную на старой. В функции, которую вы могли бы проверить, нет специальной переменной с именем [[bound_to]], если вы не используете собственную собственную реализацию привязки, как предлагает другой ответ). Нет способа post facto определить, как функция была преобразована.

Ближайшее, что я могу себе представить, это проверить возможную связанную функцию с несвязанной версией и посмотреть, равны ли они.

function log_this(){console.log(this);} 
var bound_func=log_this.bind(my_var); 
console.log(log_this===bound_func); // FALSE 
+1

Думаю, вы подытоживаете это довольно хорошо. Я согласен с тем, что нет возможности по-настоящему проверить контекст, как я определяю выше. JavaScript просто предоставляет слишком много способов обойти ситуацию, в которой я пытаюсь проверить. – kalisjoshua

0

Что можно было бы сделать что-то вроде этого:

function f(context, whatever) { 
    if(this !== context) { 
     //context has been changed 
    } 
} 

var y = f.bind(thingy); 
y(otherThingy, something); 

Вы также можете иметь пользовательские функции связывания и есть своего рода хак, как это:

function bind(func, context) {  
    var newFunc = func.bind(context); 
    newFunc._this = context; 
    return newFunc; 
} 

function checkContext(func, context) { 
    return func._this !== context; 
} 
+0

И вот скрипка, демонстрирующая мою собственную версию пользовательской функции связывания, которую я собирался опубликовать в качестве ответа, когда увидел, что вы уже накрыли ее аналогичной идеей: http: // jsfiddle .net/jx4fY/ – nnnnnn

-1

Я думаю, что это интересный вопрос для тех, кто как любит JavaScirpt, и я надеюсь, что это ответ, что вы ищете:


var isContextSet = function (fn) { 
    var testThis = {}; //unique object for testing what is this inside fn 
    return fn.call(testThis) !== testThis; 
} 

я стараюсь «установить» это внутри п : fn.call(testThis);, и если эта функция вернула ссылку на вновь созданный объект (testThis), то он не привязан. Я надеюсь, что вы получите его :)

EDIT: Это работает, когда Fn Retuns это (как показано на вопрос). В противном случае вы не можете правильно определить isContextSet.

+0

Что делать, если функция не возвращает это ?, но другое значение или вообще не имеет значения? Это создаст много ложных срабатываний. Самый простой пример: 'isContextSet (function() {})' будет давать 'true', хотя функция не привязана к определенному значению. –

+0

В вопросе примера функция возвращает это. Но если это не так, вы правы. Я руководствовался вопросом. – Zango