Cada vez que ejecuto este ciclo, cada marcador en la matriz de marcadores tiene su icono sobrescrito por los resultados de let icon = iconLoader.getIcon(data[index][5]);. dejando que cada marcador tenga el último ícono cargado, en lugar de que el ícono se cargue durante cada pasada del ciclo for.

Pensé que pasar el ícono al cierre esencialmente lo pasaría por valor, evitando que se sobrescribiera fuera del alcance del cierre, pero esto no parece estar funcionando para mí. ¿Qué me estoy perdiendo?

var markers = []   
for (var index in data) {    
    let icon = iconLoader.getIcon(data[index][5]);
    var createMarker = (function (i) {  
        return function () {
            var marker = new L.marker([data[index][2], data[index][3]])
                .setIcon(i)    
            markers.push(marker);
        }
    })(icon);
    createMarker();
}

var iconLoader = (function () {   
    var icon = L.icon({
        // options
    });    
    return {
        getIcon: function (iconName) {
            // do stuff to get icon
            return icon;
        }
    };
}());

JSFiddle

1
Chris Hull 9 mar. 2017 a las 00:26

2 respuestas

La mejor respuesta

Entonces, como mencioné en mi comentario original, los objetos y matrices de JavaScript siempre se pasan por referencia a menos que usted cree y pase una copia explícitamente. Nada en su código es inherentemente incorrecto y no está causando este problema: en realidad es un problema con la forma en que el folleto maneja las referencias de los objetos internamente. La forma de evitar esto es hacer una copia profunda del resultado de iconLoader.getIcon(). Si está utilizando jQuery, puede hacerlo de manera muy simple utilizando $.extend().

for (var index in data) {
  let icon = $.extend(true, {}, iconLoader.getIcon(data[index][2]));
  var marker = new L.marker([data[index][0], data[index][1]])
  .setIcon(icon);     
  markers.push(marker);
}

Si no, puede buscar soluciones que no sean jQuery: no es ideal, pero están en todas partes.

1
mhodges 9 mar. 2017 a las 00:10

Estaba escribiendo esto mientras mhodges escribía su respuesta. Seguiré y lo publicaré, ya que es una solución diferente que también me resolvió el problema.

Después de mirar la demostración de trabajo de mhodges, me di cuenta de que había configurado el cargador de iconos de forma un poco diferente a la mía. Tenía el iconloader como objeto ...

var iconLoader = {
    getIcon: function (elem) {
        return elem;
    }
 }

Mientras que el mío se creó como un cierre ...

var iconLoader = (function () {   
    var icon = L.icon({
        // options
    });    
    return {
        getIcon: function (iconName) {
            // do stuff to get icon
            return icon;
        }
    };
}());

Pensé que tal vez podría intentar configurarlo un poco diferente y ver si eso marcaba la diferencia, ¡y VOILA!

const proto = {
        getIcon (iconName) {
            var icon = L.icon({
                // options
            });   
            // do stuff to get icon
            return icon;
        }
    };

function factoryIcon() {
    return Object.create(proto);
}

Y luego agarró el ícono con

const iconFactory = factoryIcon();
let icon = iconFactory.getIcon(data[index][5]);
0
Chris Hull 9 mar. 2017 a las 00:26