Esto es lo que he hecho:

<html><head><script type="text/javascript"> 
function loaded(){
    var selectElems=document.getElementsByName("select");
    for(i=0;i<selectElems.length;i++){
      var elem=selectElems[i];
      elem.onchange=function(){
          alert(elem.selectedIndex);
       }
     }
} </script></head>
<body onload="loaded()">
<select name="select">
      <option>0</option>
      <option>1</option>
      <option>2</option>
      <option>3</option>
      <option>4</option> </select>
 <select name="select">
      <option>0</option>
      <option>1</option>
      <option>2</option>
      <option>3</option>
      <option>4</option></select>
 <select name="select">
      <option>0</option>
      <option>1</option>
      <option>2</option>
      <option>3</option>
      <option>4</option></select>
</body></html>

Necesito obtener el índice seleccionado del elemento con JavaScript. Pero tuve un problema con eso. Aquí está mi código: http://jsfiddle.net/aRMpt/139/

0
Jama A. 9 feb. 2012 a las 03:27

1 respuesta

La mejor respuesta

El problema es que su elem siempre apunta al último elemento select. La solución más simple es usar this en el controlador en lugar de la variable elem http: // jsfiddle .net / mendesjuan / aRMpt / 140 /

function loaded(){
    var selectElems=document.getElementsByName("select");
    for(i=0;i<selectElems.length;i++){
      var elem=selectElems[i];
      elem.onchange=function(){
          // This points to the select element that was changed
          alert(this.selectedIndex);
       }
     }
}

Sin embargo, esto realmente no le dice cuál es su problema. Es una solución alternativa (aunque buena). La razón por la que su código no funciona es porque su función de cierre onchange usa el mismo elem del cierre. Cuando se llama a su onchange, elem apunta al último elemento select. Una forma de evitar esto es introducir otro cierre que congele el elemento de su controlador onchange http://jsfiddle.net/mendesjuan/aRMpt/142/

function loaded(){
    var selectElems=document.getElementsByName("select");
    for(i=0;i<selectElems.length;i++){
      var elem=selectElems[i];
      // Freeze the elem variable by creating a function that passes
      // the elem and creates a separate closure for each handler
      elem.onchange= (function(el) {
          // This is the function that will actually be the handler
          return function(){
             // This points to the select element that was changed
             alert(el.selectedIndex);
          }
     }) (elem) 
}

Aquí hay otro ejemplo que puede ayudarlo a comprender cómo funciona el ejemplo anterior.

// This is a function that returns another function
// Its only reason is so that we don't use the shared closure 
// variables from the outer scope, it freezes the el
// variable at the moment its called and so that it's available
// when the handler is called
function createOnChangeHandler(el) {
  return function() {
     alert(el.selectedIndex);
  }
}

function loaded(){
    var selectElems=document.getElementsByName("select");
    for(i=0;i<selectElems.length;i++){
      var elem=selectElems[i];
      // If we just use elem here, its value will be what it was assigned last
      // in the loop. That is because the handler won't be called until
      // this loop has finished. However, by calling another function, 
      // a new scope is created with the value that we're passing into it
      elem.onchange = createOnChangeHandler(elem);
}

Esta congelación de variables también podría lograrse mediante el uso de Function.bind , pero esto solo funciona en navegadores más nuevos; sin embargo, el enlace anterior le muestra cómo hacerlo funcionar para navegadores que no lo admiten. http://jsfiddle.net/mendesjuan/aRMpt/143/

function loaded(){
    var selectElems=document.getElementsByName("select");
    for(i=0;i<selectElems.length;i++){
      var elem = selectElems[i];
      elem.onchange = (function (el) {
        alert("Select index: " + el.selectedIndex)
      }).bind(null, el);
}
3
Juan Mendes 9 feb. 2012 a las 04:55
Creo que todos los desarrolladores de JS se han encontrado con este problema antes. Me aseguraría de que comprenda la segunda solución, ya que es posible que la necesite en el futuro (digamos si desea utilizar la variable i). Pero para este caso, solo usaría el primero.
 – 
Juan Mendes
9 feb. 2012 a las 03:40
Para ser honesto, soy un novato en javascript, especialmente tu segundo ejemplo es un poco difícil de entender, y ahora estoy buscando en Google ... si conoces algún buen tutorial sobre este ejemplo, ¿puedes señalarme?
 – 
Õzbek
9 feb. 2012 a las 03:50
Se agregaron algunos comentarios sobre cómo funciona. Siéntete libre de hacer preguntas y no te preocupes, lleva algo de tiempo digerirlo, pero no puedes llamarte un buen desarrollador de JS hasta que lo entiendas.
 – 
Juan Mendes
9 feb. 2012 a las 04:23
Este no es un gran artículo, algunos de los ejemplos son raros, pero lo explica. javascriptkata.com/2007 / 04/11 /…
 – 
Juan Mendes
9 feb. 2012 a las 04:52