简体   繁体   English

JavaScript delete array [i]-在OSX中运行良好,但在Windows中无法运行?

[英]JavaScript delete array[i] — runs great in OSX but won't run in Windows?

I'm building a listbuilder app in vanilla JavaScript, and it's working on my macbook, but not on my PC. 我正在使用香草JavaScript构建listbuilder应用,并且该产品可在我的Macbook上运行,但无法在我的PC上运行。

What difference between Mac and PC am I missing? 我缺少Mac和PC之间的什么区别?

The specific error in question is values aren't being deleted from my array in Windows. 有问题的具体错误是Windows中没有从我的数组中删除值。 I'm not getting a Chrome or Firefox console error from Windows, but the "delete" function isn't removing the values from the array. 我没有从Windows收到Chrome或Firefox控制台错误,但“删除”功能并未从数组中删除值。 Instead, it removes the LI from the HTML, but the targeted array value's LI reappears whenever a new entry is made and the unordered list is redrawn. 相反,它从HTML中删除了LI,但是只要创建新条目并重绘无序列表,目标数组值的LI就会重新出现。

I've run the code through Firefox and Chrome on my mac and my PC, and updated the browsers as well. 我已经在Mac和PC上通过Firefox和Chrome运行代码,并且还更新了浏览器。

The functionality I'm trying for is allowing the user to create a LI on the DOM by adding a value to an array, and then to remove both this LI and the array value by clicking on the LI. 我正在尝试的功能是允许用户通过向数组添加值来在DOM上创建LI,然后通过单击LI来删除此LI和数组值。

My HTML: 我的HTML:

    <div>
        <h2>Enter your Input!</h2><input class="feedback-input" id=
        "entryBox" placeholder="Type anything!" type="text"> <button id=
        "addEntry" onclick="addEntry()">Add your Entry</button>
    </div>

    <div id="outputBox">
        <ul id="outputList"></ul>

        <p>Click list item to remove</p>
    </div>
</div>

My JavaScript: 我的JavaScript:

var output = document.getElementById("outputList");
var list = [];
var entry = {};

function addEntry() {
  input = document.getElementById("entryBox").value; //Reads value from form
  document.getElementById("entryBox").value = ""; //Clears entry box for new text
  list.push(input);
  while (outputList.firstChild) //clearing the old displayed list 
  {
    outputList.removeChild(outputList.firstChild);
  }

  for (i = 0; i < list.length; i++) //For loop to draw LIs in unordered list
  {
    var li = document.createElement('li'); //Creates li
    output.appendChild(li); //attaches li to the output list
    li.onclick = function() //provides list items removal function
    {

      function remove() {
        delete list[i]; //pulls it out of the array. Delete prefered to Splice so I can maintain original location of other array items.
        console.log(list);
      }
      remove();
      this.parentNode.removeChild(this); //pulls it out of the DOM
    };

    li.innerHTML = li.innerHTML + list[i]; //adds the entryBox value to the li
  }
}

I also put the code in a JSFiddle; 我还将代码放在JSFiddle中。 the JS in the Fiddle didn't work at all, but I don't want to distract this into a JSFiddle lesson. Fiddle中的JS根本没有用,但我不想将其分散到JSFiddle课程中。 https://jsfiddle.net/y3sjs7po/ https://jsfiddle.net/y3sjs7po/

document.getElementById("outputList"); will return null as the element doesn't exist until the page loads, so your script will fail. 由于该元素直到页面加载才存在,将返回null,因此脚本将失败。

This works: https://jsfiddle.net/y3sjs7po/1/ (loaded after the body) 这有效: https : //jsfiddle.net/y3sjs7po/1/ (在正文之后加载)

BUT, you are also doing it wrong in the loop. 但是,您在循环中也做错了。 You cannot capture the state of i in a closure like that. 您无法在这样的闭包中捕获i的状态。 By the time the onclick event fires, i is always the last element in the array. onclick事件触发时, i始终是数组中的最后一个元素。 Also, this does not refer to the element the event is from - you have to pass it in. Finally, use splice() to remove elements in this case, not delete . 另外, this并不涉及事件的来源-您必须将其传递。最后,在这种情况下,请使用splice()删除元素,而不是delete

Try this: https://jsfiddle.net/y3sjs7po/4/ 试试这个: https : //jsfiddle.net/y3sjs7po/4/

I changed it to store object items that contain details of each stored item. 我将其更改为存储包含每个存储项目详细信息的对象项目。 Because indexes shift when items are removed, you cannot store the indexes and expect items to be at the same position. 由于删除项目时索引会移动,因此您无法存储索引,也无法期望项目位于同一位置。 To this end, I've change this line: 为此,我更改了这一行:

list.push({
    input: input,
    li: null
});

It instead stores the input value and list element in an object for tracking, and later removal. 而是将输入值和列表元素存储在对象中以进行跟踪,并在以后删除。

var li = document.createElement('li'); //Creates li
list[i].li = li;

The part that makes it work is this: 使它起作用的部分是这样的:

li.onclick = (function (item) {
    return function () // creates a closure over the local `item` variable in the parent scope
    {
        // ... find the item's position (changes as items are deleted) ...
        for (var i = 0; i < list.length; ++i)
            if (list[i] == item) {
                list.splice(i, 1); //pulls it out of the array
                item.li.parentNode.removeChild(item.li); //pulls it out of the DOM
                break;
            }
        console.log(list);
    };
})(list[i]); // pass in the current item

It properly wraps each item (input and element) in a closure (by passing it into a wrapper function). 它将每个项目(输入和元素) 适当地包装在闭包中(通过将其传递给包装函数)。 This can also be done using the bind() function as well. 也可以使用bind()函数来完成此操作。

There are lots of mistakes that aren't outright errors but are poor coding practice. 有很多错误不是完全错误,但编码实践很差。 James has pointed out the error due to a closure, I'll cover some other stuff. James指出了由于关闭而导致的错误,我将介绍其他一些内容。

var output = document.getElementById("outputList");

Doing DOM operations when you aren't really sure whether the element exists or not isn't a good strategy. 当您不确定该元素是否存在时,执行DOM操作并不是一个好的策略。 Wherever possible, make sure the element exists first. 尽可能确保该元素首先存在。 And don't use global variables unless there's a good reason, these can all be kept local. 并且除非有充分的理由,否则不要使用全局变量,这些变量都可以保持局部。

var list = [];
var entry = {};

function addEntry() {
  input = document.getElementById("entryBox").value; //Reads value from form

This undeclared variable becomes global when addEntry is called the first time. 首次调用addEntry时,此未声明的变量变为全局变量。

  document.getElementById("entryBox").value = ""; //Clears entry box for new text
  list.push(input);
  while (outputList.firstChild) //clearing the old displayed list 

outputList is not declared or assigned a value, so it "works" because "outputList" is the ID of an element. 未声明outputList分配值,因此它是“有效的”,因为“ outputList”是元素的ID。 ID's are made global variables (unless there's a conflicting declared variable or function declaration), it's considered very bad practice to rely on this behaviour. ID是全局变量(除非有声明的变量或函数声明冲突),依靠这种行为被认为是非常不好的做法。

  {
    outputList.removeChild(outputList.firstChild);
  }

  for (i = 0; i < list.length; i++) //For loop to draw LIs in unordered list
  {
    var li = document.createElement('li'); //Creates li
    output.appendChild(li); //attaches li to the output list
    li.onclick = function() //provides list items removal function
    {

You are (attempting to) create a sparse array, but the above will visit removed members. 您正在(尝试)创建一个稀疏数组,但是上面的内容将访问已删除的成员。 You must test if the member exists before creating an LI for it. 您必须先测试该成员是否存在,然后才能为其创建LI。 Using forEach will help is it doesn't iterate over missing members. 使用forEach会有所帮助,因为它不会遍历丢失的成员。

[...]

Here's an alternative function. 这是一个替代功能。 It keeps variables out of the global scope and seems to implement what you're after. 它使变量不在全局范围之内,并且似乎实现了您所追求的目标。 I don't understand why you remove all the LIs only to add them again, but that seems to be what you want to do. 我不明白为什么您删除所有LI只是为了再次添加它们,但这似乎就是您想要的。

var addEntry = (function() {
  // Shared variables here
  var input,
      outputList,  // Declare it so not reliant on ID to global mapping
      list = [],
      entry = {};  // Unused?

  // Keep in a closure so only one instance exists, not one for each element
  function remove(el) {
    el.parentNode.removeChild(el);
  }

  // return the function
  return function() {
    outputList = outputList || document.getElementById('outputList');
    input = input || document.getElementById('entryBox');

    // store the value of the input
    list.push(input.value);

    // clear for next time
    input.value = '';

    // Remove LIs
    while (outputList.firstChild) {
      outputList.removeChild(outputList.firstChild);
    }

    // Add new LIs for each member of list
    for (var i=0, iLen=list.length; i<iLen; i++) {

      // list is sparse, so only add LI if i exists
      // could use forEach and save test
      if (list.hasOwnProperty(i)) {
        var li = document.createElement('li');
        li.innerHTML = list[i] + ' ' + i;

        // Assign listener with IIFE to break closure with i
        li.onclick = (function(i) {
          return function() {
            remove(this);
            delete list[i];
          };
        }(i));

        outputList.appendChild(li);
      }
    }
  }
}())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM