Почему я не могу добавить событие каждому элементу в коллекции, которая относится к себе, а не последний элемент в операторе «for () {}»

StackOverflow https://stackoverflow.com/questions/2596284

Вопрос

На Windowнагрузка, каждый DD элемент внутри Quote_App должен иметь АН onCLick Мероприятие добавлено, что триггеры функции Lorem, Однако, Lorem Возвращает nodeName а также Id последнего элемента в For утверждение, а не на элементе, который погрузил функцию. я бы хотел Lorem вернуть nodeName а также Id элемента, который вызвал функцию.

function Lorem(Control){

/*     this.Control=Control; */
    this.Amet=function(){
        return Control.nodeName+"\n"+Control.id;
    };

};

function Event(Mode,Function,Event,Element,Capture_or_Bubble){
    if(Mode.toLowerCase()!="remove"){
        if(Element.addEventListener){
            if(!Capture_or_Bubble){
                Capture_or_Bubble=false;
            }else{
                if(Capture_or_Bubble.toLowerCase()!="true"){
                    Capture_or_Bubble=false;
                }else{
                    Capture_or_Bubble=true;
                };
            };
            Element.addEventListener(Event,Function,Capture_or_Bubble);
        }else{
            Element.attachEvent("on"+Event,Function);
        };
    };
};

function Controls(){
    var Controls=document.getElementById("Quote_App").getElementsByTagName("dd");
    for(var i=0;i<Controls.length;i++){

        var Control=Controls[i];

        Event("add",function(){

            var lorem=new Lorem(Control);
            lorem.Control=Control;
            alert(lorem.Amet());

        },"click",Controls[i]);

    };
};

Event("add",Controls,"load",window);

В настоящее время вы нажимаете на любой DD элемент Lorem всегда возвращает nodeName а также Id последнего DD элемент.

Lorem должен вернуть nodeName а также Id принадлежащий Control (Control[i]) это вызвано Lorem.

Как я могу сделать это случиться?

Спасибо!

Это было полезно?

Решение

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

  for(var i=0;i<Controls.length;i++) {   
    (function() {
        var Control=Controls[i];

        Event("add",function(){

            var lorem=new Lorem(Control);
            lorem.Control=Control;
            alert(lorem.Amet());

         },"click",Controls[i]);
    })();
  };

Здесь я создал замыкание выше, используя хороший друг JavaScript, самозазывной анонимной функции.

Причина, по которой требуется закрытие, это то, что без него ценность i в точке, на котором выполняется любой функция обработчика событий, будет иметь значение i В последней итерации цикла не то, что мы хотим. Мы хотим ценность i Поскольку он находится в каждой итерации петли, в точке, в которой мы объявляем каждый обработчик событий, таким образом, при этом нам нужно для захвата этого значения в каждой итерации. Использование анонимной функции, которая выполняет, как только он объявлен, является хорошим механизмом для захвата желаемого значения.

Другой момент, слегка от темы, но это может помочь вам, это то, что захват событий не поддерживается в каждом браузере (ahem., Т.е.) Но пузырь события есть. Это эффективно делает useCapture Логический флаг в addEventListener Совершенно бесполезно для разработки веб-приложений для перекрестных браузеров. Поэтому я посоветую не использовать его.

Еще одна вещь, JavaScript обычно использует корпус верблюда для имен функций и имена переменной. Корпус Паскаля обычно используется только для функций конструктора (функции, которые создают объекты).

Другие советы

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

В твоем случае:

var functions = [];
function outer() {
    for (var i = 0; i < N; i++) { // <------------
        functions[i] = function() { //            |
            alert(i); // <-- this 'i' refers to this one
        }
    } // At the end of the for loop, i == N (or N+1?)
}
functions[x](); // Will show N (or N+1)
// because that's the current value of i in the outer function
// (which is kept alive just because something refers to it)

То, что вы хотите сделать, это захватить значение «i» на каждом этапе петли, для последующей оценки, например:

var functions = [];
function outer() {
    for (var i = 0; i < N; i++) { // <---------------------------------------
        functions[i] = (function(my_i) { // <----                            |
            return function () { //              |                           |
                alert(my_i); // my_i refers to this which is a copy of 'i' there
            }
        }(i)); // run function(with my_i = the i at each step of the loop)
    }
}
functions[x](); // Will show x

Вы можете видеть, что есть внутренняя функция, которая получает копию текущего счетчика в качестве параметра. Эта внутренняя функция остается вживую с этой копией, так что позже звонки в хранимую иннестенную функцию возвращает значение my_i функции, которая создала ее - понятно? :-)

Это замечательный мир закрытий. Это может занять немного ума, чтобы сначала получить его, но тогда вы будете рады, что вы сделали, так и Google Google «Закрытия JavaScript» к смерти!

Это может быть более очевидным вариантом ответа Русского кулачка:

function Controls() {
  var Controls = document.getElementById("Quote_App").getElementsByTagName("dd");

  var createHandlerFor = function(CurrentControl) {
    return function() {
      var lorem=new Lorem(CurrentControl);
      lorem.Control=CurrentControl;
      alert(lorem.Amet());
    }
  };

  for (var i=0; i<Controls.length; i++) {
    Event("add", createHandlerFor(Controls[i]), "click", Controls[i]);
  }
};
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top