Можете ли вы сказать, что это верный пример закрытия Javascript? - PullRequest
2 голосов
/ 13 января 2010

Проблема и причина

Один из моих товарищей по команде оказался в беспорядочной ситуации, реализуя перехват функций в javascript. это фактический код

 function ActualMethod(){   
       this.doSomething = function() {
              this.testMethod();
        };

       this.testMethod = function(){
            alert("testMethod");
        };
   }


 function ClosureTest(){
       var objActual= new ActualMethod();   
    var closeHandler = objActual.doSomething;   
    closeHandler();     
    closeHandler.apply(objActual,arguments); //the fix i have added
    this.ActualTest = function() {
        alert("ActualTest");
        };
  }

В приведенном выше коде var closeHandler создается в контексте ClosureTest (), но он содержит обработчик ActualMethod.doSomething. Всякий раз, когда вызов closeHandler () заканчивался ошибкой «объект не поддерживает этот метод».

Это потому, что функция doSomething () вызывает другой метод внутри, называемый this.testMethod () ;. Здесь this относится к контексту вызывающего, а не вызываемого абонента. Поэтому я предполагаю, что closeHandler связан с фактически созданной средой (ClosureTest). Даже если он удерживает обработчик в другом контексте, он просто предоставляет свойства своего контекста.

Решение

Чтобы избежать этого, я предлагаю использовать apply для указания контекста, в котором он должен выполняться.

closeHandler.apply (objActual, аргументы);

Вопросы

это идеальный сценарий для замыканий .. ??

Какие интересные места вы встретили в javascript? .. *

UPDATE

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

скажем для примера, я использую стороннюю библиотеку aspx grid, и все события щелчка мышью отслеживаются их элементами управления. В определенной группе щелчком мыши мне нужно перехватить вызов их ilbrary метода и подключить мой mthod для выполнения вместо этого и перенаправить вызов фактическому библиотечному методу

надеюсь, это поможет

Ответы [ 2 ]

2 голосов
/ 13 января 2010

Когда я хочу подключить функцию, я использую следующий метод Function, который также является хорошим примером демонстрации Closure:

Function.prototype.wrap = function (wrapper) {
 var __method = this;
 return function() {
  var __obj = this;
  var args = [ __method.bind(__obj) ];
  for(var i=0; i<arguments.length; i++) args.push(arguments[i]);
  return wrapper.apply(__obj, args);
 }
};

Затем сделайте что-то вроде:

ActualMethod = ActualMethod.wrap(function (proceed, option) {
  // ... handle option
  proceed(); // calls the wrapped function
});

продолжить привязано к своему начальному объекту, поэтому вы можете смело вызывать его.

2 голосов
/ 13 января 2010

Обновление: Поскольку вы, вероятно, пропустили некоторые детали в своем коде, трудно адаптировать его к чему-то работающему, не упустив при этом сути вашего кода. Я думаю, что понимаю вашу основную проблему, когда вы ее описываете. Я надеюсь, что следующее поможет.

Предположим, следующий простой пример:

// Constructor function.
function Example() {
    // Method:
    this.method = function() {
        alert("original method");
    }
}

// You would use it like this:
var obj = new Example();
obj.method(); // Calls original method.

Чтобы перехватить такой вызов метода, вы можете сделать это:

function wrap(obj) {
    var originalMethod = obj.method;
    obj.method = function() {
        alert("intercepted call");
        originalMethod.apply(this, arguments);
    }
    return obj;
}

var obj = wrap(new Example());
obj.method(); // Calls wrapped method.

К сожалению, поскольку method() определен в функции конструктора, а не в прототипе, вам необходим экземпляр объекта для переноса объекта.


Ответ на оригинальный вопрос: Функция doSomething() используется в качестве метода для объектов, созданных с помощью ActualMethod(). Вы должны использовать его как метод, а не отделять его и использовать как функцию в другом контексте. Почему бы вам просто не вызвать метод напрямую?

function ClosureTest(){
    var objActual = new ActualMethod();
    // Call method directly, avoid messy apply() calls.
    objActual.doSomething();
    this.ActualTest = function() {
        alert("ActualTest");
    };
}

Если вы назначите метод (функцию некоторого объекта) локальной переменной в Javascript и вызовете ее, контекст будет другим (значение this изменится). Если вы не хотите, чтобы это произошло, не делайте этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...