2016-12-04 5 views
1

Мне нужно скопировать строку внутри массива в значение внутри другого массива, созданного в цикле. В конце, когда я печатаю, все имена являются последними в массиве имен. Я хочу скопировать/клонировать значение, чтобы у меня не было ссылки, и я бы хотел, чтобы он был только в собственном javascript без внешних библиотек.Использовать замыкание внутри массива с чистым javascript

Это мой код

var exp_names =["name1","name2","name3"]; 
var i;  
for (i = 0; i < exp_names.length; i++) { 
    d3.tsv("data/"+exp_names[i], function(data) { 
     data.forEach(function(d){ 
      //Do stuff with my tsv 
      d.expId = exp_names[i]; 
     }); 
    }); 
}); 

И тогда все expId являются "name3"

Данные загружаются правильно для каждого файла.

Я пробовал с функцией расширения jquery, а также функцию клонирования lodash, я пробовал свою собственную функцию клонирования, и ничего не работает, она все равно будет кидать «имя3» для всего expId.

Они не работают:

var newname = new String(exp_names[i]); 
var newname = $.extend(true, {}, exp_names[i]); 
var newname = $.extend({}, exp_names[i]); 
var newname = _.clone(exp_names[i]); 
var newname = exp_names[i].slice(0); 

Я отчаянный сейчас.

+0

Написать пожалуйста ожидаемый результат от вашего входного массива exp_names –

ответ

1

Вам необходимо использовать функцию bind.

var exp_names =["name1","name2","name3"]; 
var i; 
var func = [];  
for (i = 0; i < exp_names.length; i++) { 
    func[i]=(function(index){ 
     d3.tsv("data/"+exp_names[index], function(data) { 
      data.forEach(function(d){ 
       //Do stuff with my tsv 
       d.expId = exp_names[index]; 
      }); 
     }); 
    }).bind(this,i); 
} 
for(i = 0; i < 3; i++){ 
    func[i](i); 
} 

Другим решением является использование ключевого слова let.

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

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

for (let i = 0; i < exp_names.length; i++) { 
    d3.tsv("data/"+exp_names[i], function(data) { 
     data.forEach(function(d){ 
      //Do stuff with my tsv 
      d.expId = exp_names[i]; 
     }); 
    }); 
} 
+0

спасибо очень много, «пусть» ключевое слово мне очень помог! Bind не сработал, он даже не сделал цикл, может быть, я что-то написал неправильно. Но в любом случае «пусть» спасли день. Спасибо! –

+0

Добро пожаловать. –

+0

@ZloySmiertniy, теперь должен работать метод '.bind'. –

0

Я предполагаю использование IIFE и связать друг с другом, в первом ответе немного странно. Лучше выбрать один из них. Начиная с in the newest versions of the browsers bind is way faster than an IIFE closure и с ключевым словам let, я могу посоветовать вам bind way.

Аналогичный пример для вашего случая может быть как у всех;

var exp_names = ["name1","name2","name3"], 
 
      lib = {doStg: function(d,cb){ 
 
          cb(d); 
 
         } 
 
       }, 
 
     data = [{a:1},{a:2},{a:3}]; 
 

 
for (i = 0; i < exp_names.length; i++) { 
 
    lib.doStg(data, function(i,d) { 
 
         d.forEach(function(e){ 
 
            //Do stuff with doStg 
 
            e.expId = exp_names[i]; 
 
            console.log(e); 
 
           }); 
 
        }.bind(null,i)); 
 
}