从/到数组添加/删除项目的好 JavaScript?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14815560/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
A good JavaScript to add/remove items from/to array?
提问by Jason Vasilev
folks! Today I created this script that has the following functionality:
伙计们!今天我创建了这个具有以下功能的脚本:
- add new items to array
- list all items from the array
- remove an item from the array
- 将新项目添加到数组
- 列出数组中的所有项目
- 从数组中删除一个项目
There are two functions:
有两个功能:
- addToFood() - adds the value of input to the array and updates innerHTML of div
- removeRecord(i) - remove a record from the array and updates innerHTML of div
- addToFood() - 将 input 的值添加到数组中并更新 div 的innerHTML
- removeRecord(i) - 从数组中删除一条记录并更新 div 的innerHTML
The code includes 3 for loops and you can see it at - http://jsfiddle.net/menian/3b4qp/1/
该代码包括 3 个 for 循环,您可以在 - http://jsfiddle.net/menian/3b4qp/1/看到它
My Master told me that those 3 for loops make the solution way to heavy. Is there a better way to do the same thing? Is it better to decrease the loops and try to use splice? Thanks in advance.
我的主人告诉我,这 3 个 for 循环使解决方案变得沉重。有没有更好的方法来做同样的事情?减少循环并尝试使用拼接会更好吗?提前致谢。
HTML
HTML
<!-- we add to our foodList from the value of the following input -->
<input type="text" value="food" id="addFood" />
<!-- we call addToFood(); through the following button -->
<input type="submit" value="Add more to food" onClick="addToFood();">
<!-- The list of food is displayed in the following div -->
<div id="foods"></div>
JavaScript
JavaScript
var foodList = [];
function addToFood () {
var addFood = document.getElementById('addFood').value;
foodList.push(addFood);
for (i = 0; i < foodList.length; i++) {
var newFood = "<a href='#' onClick='removeRecord(" + i + ");'>X</a> " + foodList[i] + " <br>";
};
document.getElementById('foods').innerHTML += newFood;
}
function removeRecord (i) {
// define variable j with equal to the number we got from removeRecord
var j = i;
// define and create a new temporary array
var tempList = [];
// empty newFood
// at the end of the function we "refill" it with the new content
var newFood = "";
for (var i = 0; i < foodList.length; i++) {
if(i != j) {
// we add all records except the one == to j to the new array
// the record eual to j is the one we've clicked on X to remove
tempList.push(foodList[i]);
}
};
// make redefine foodList by making it equal to the tempList array
// it should be smaller with one record
foodList = tempList;
// re-display the records from foodList the same way we did it in addToFood()
for (var i = 0; i < foodList.length; i++) {
newFood += "<a href='#' onClick='removeRecord(" + i + ");'>X</a> " + foodList[i] + " <br>";
};
document.getElementById('foods').innerHTML = newFood;
}
采纳答案by JohnJohnGa
You should use array.splice(position,nbItems)
你应该使用 array.splice(position,nbItems)
function removeRecord (i) {
foodList.splice(i, 1); // remove element at position i
var newFood = "";
for (var i = 0; i < foodList.length; i++) {
newFood += "<a href='#' onClick='removeRecord(" + i + ");'>X</a> "
+ foodList[i] + " <br>";
};
document.getElementById('foods').innerHTML = newFood;
}
Now using JQuery:
现在使用 JQuery:
$(function(){
$(document).on('click','input[type=submit]',function(){
$('#foods')
.append('<div><a href="#" class="item">X</a> '
+ $('#addFood').val() + '</div>');
});
$(document).on('click','.item',function(){
$(this).parent().remove();
});
});
回答by Aaron Digulla
Your problem isn't the arrays, your problem is this code:
你的问题不是数组,你的问题是这个代码:
node.innerHTML += newFood;
This code is very, very, veryslow. It will traverse all exising DOM nodes, create strings from them, join those strings into one long string, append a new string, parse the result to a new tree of DOM nodes.
这段代码非常非常非常慢。它将遍历所有现有的 DOM 节点,从中创建字符串,将这些字符串连接成一个长字符串,附加一个新字符串,将结果解析为一棵新的 DOM 节点树。
I suggest to use a framework like jQuery which has methods to append HTML fragments to existing DOM nodes:
我建议使用像 jQuery 这样的框架,它具有将 HTML 片段附加到现有 DOM 节点的方法:
var parent = $('#foods');
...
for (var i = 0; i < foodList.length; i++) {
parent.append( "<a href='#' onClick='removeReco..." );
That will parse the HTML fragments only once.
那只会解析 HTML 片段一次。
If you really must do it manually, then collect all the HTML in a local string variable (as suggested by JohnJohnGa in his answer) and then assign innerHTMLonce.
如果您确实必须手动执行此操作,则将所有 HTML 收集到本地字符串变量中(如 JohnJohnGa 在他的回答中所建议的那样),然后分配innerHTML一次。
回答by Tivie
Here's some tips to, at least, make your code more portable (dunno if it will be better performance wise, but should be, since DOM Manipulation is less expensive)
这里有一些技巧,至少可以让你的代码更便携(不知道它是否会在性能上更好,但应该是,因为 DOM 操作更便宜)
Tips
提示
- First separate your event handle from the HTML
- Pass the "new food" as a function paramater
- Tie the array elements to the DOM using the ID
- Instead of rerendering everything when something changes (using innerHTML in the list), just change the relevant bit
- 首先将您的事件句柄与 HTML 分开
- 将“新食物”作为函数参数传递
- 使用 ID 将数组元素绑定到 DOM
- 当某些事情发生变化时(使用列表中的innerHTML),而不是重新渲染所有内容,只需更改相关位
Benefits:
好处:
- You actually only loop once (when removing elements from the array).
- You don't re-render the list everytime something changes, just the element clicked
- Added bonus: It's more portable.
- Should be faster
- 您实际上只循环一次(从数组中删除元素时)。
- 每次更改时您都不会重新渲染列表,只需单击元素
- 额外的好处:它更便携。
- 应该更快
Example code:
示例代码:
HTML
HTML
<div id="eventBinder">
<!-- we add to our foodList from the value of the following input -->
<input id="addFood" type="text" value="food" />
<!-- we call addToFood(); through the following button -->
<button id="addFoodBtn" value="Add more to food">Add Food</button>
<!-- The list of food is displayed in the following div
-->
<div id="foods"></div>
</div>
JS
JS
// FoodList Class
var FoodList = function (selectorID) {
return {
foodArray: [],
listEl: document.getElementById(selectorID),
idCnt: 0,
add: function (newFood) {
var id = 'myfood-' + this.idCnt;
this.foodArray.push({
id: id,
food: newFood
});
var foodDom = document.createElement('div'),
foodText = document.createTextNode(newFood);
foodDom.setAttribute('id', id);
foodDom.setAttribute('class', 'aFood');
foodDom.appendChild(foodText);
this.listEl.appendChild(foodDom);
++this.idCnt;
},
remove: function (foodID) {
for (var f in this.foodArray) {
if (this.foodArray[f].id === foodID) {
delete this.foodArray[f];
var delFood = document.getElementById(foodID);
this.listEl.removeChild(delFood);
}
}
}
};
};
//Actual app
window.myFoodList = new FoodList('foods');
document.getElementById('eventBinder').addEventListener('click', function (e) {
if (e.target.id === 'addFoodBtn') {
var food = document.getElementById('addFood').value;
window.myFoodList.add(food);
} else if (e.target.className === 'aFood') {
window.myFoodList.remove(e.target.id);
}
}, false);
回答by Augusto Hack
Here is another sugestion:
这是另一个建议:
function remove(arr, index) {
if (index >= arr.lenght) { return undefined; }
if (index == 0) {
arr.shift();
return arr;
}
if (index == arr.length - 1) {
arr.pop();
return arr;
}
var newarray = arr.splice(0, index);
return newarray.concat(arr.splice(1,arr.length))
}

