【问题标题】:Passing a string to function but expecting an array将字符串传递给函数但需要一个数组
【发布时间】:2018-12-24 07:23:35
【问题描述】:

我有一个选择下拉菜单,我希望它在更改时运行一个函数并将选择的值传递给该函数。但是,该函数需要一个保存数组的变量,而传入的是一个字符串(选择的值)。

您可以在下面的代码中看到它工作(或不工作)。所选值应代表其对应的变量。

我怎样才能做到这一点?

var str = ["Paul", "John", "Melissa", "Mike"];
var int = [8, 4, 55, 7];
var mix = ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2];

var main = document.querySelector('#main');
var sel = document.querySelector('select');


function testFunc(arr){
  arr.forEach((i) => {
    var p = document.createElement('p');
    p.innerHTML = i;
    main.appendChild(p);
  });
}

testFunc(mix);

sel.addEventListener('change', testFunc(sel.value));
<select>
  <option value="str">String</option>
  <option value="int">Integer</option>
  <option value="mix">Mixed</option>
</select>

<div id="main"></div>

编辑:

我应该注意到,数据数组是动态输入的,我真的很想避免对它们进行操作,以免在以后的编辑中造成额外的代码和混乱。

【问题讨论】:

  • 为什么要sting这个函数?有没有给你带来什么问题?
  • 你的函数是否曾经传递过一个数组?如果没有,则重新编码。如果是这样,那为什么不对字符串使用不同的函数呢?
  • testFunc(sel.value) 到 function(){testFunc(this.value)} 和 arr = eval(arr) 应该给出预期的输出

标签: javascript arrays select


【解决方案1】:

您的代码中有两个问题:

  1. 在事件处理函数中,通过在函数后面指定括号,您将在页面加载时调用该函数。只需在函数体内调用函数即可。这将使函数仅在事件触发时被调用。

  2. sel.value 是一个字符串,但该函数需要一个数组。要动态评估数组,请将 testFunc(mix) 更改为 testFunc('mix')(将参数值用引号括起来)并使用 window 对象,例如:

    arr = window[arr]
    

替换:

sel.addEventListener('change', testFunc(sel.value));

sel.addEventListener('change', function (){testFunc([sel.value])});

var str = ["Paul", "John", "Melissa", "Mike"];
var int = [8, 4, 55, 7];
var mix = ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2];

var main = document.querySelector('#main');
var sel = document.querySelector('select');


function testFunc(arr){
  arr = window[arr]
  arr.forEach((i) => {
    var p = document.createElement('p');
    p.innerHTML = i;
    main.appendChild(p);
  });
}

testFunc('mix');

sel.addEventListener('change', function (){testFunc(sel.value)});
<select>
  <option value="str">String</option>
  <option value="int">Integer</option>
  <option value="mix">Mixed</option>
</select>

<div id="main"></div>

【讨论】:

  • 这将导致相同的错误,您传递一个字符串值并尝试像数组一样对其进行迭代。关闭是无用的
  • 哦,对不起,没看到。
  • @Mamun 虽然您的解决方案对我来说更有意义,但它在我的项目中对我不起作用......奇怪,因为我看到它在这里工作。但是 Rajapandian 使用 eval() 方法的解决方案对我有用。
  • 这没有产生所需的输出(在输出中向下滚动)。这怎么可能被赞成?
  • @Sergio,如果解决方案在这里工作,不应该有任何原因导致代码在您的项目中不起作用......可能应该调试或 console.log 看看什么事件触发时正在发生............
【解决方案2】:

据我了解,您想这样做:

let model = {
    str : ["Paul", "John", "Melissa", "Mike"];
    int : [8, 4, 55, 7];
    mix : ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2];
}


function testFunc(key){
    var arr = []
    if(model[key]){
        arr = model[key]
    }


    //TODO: clear parent node...
    arr.forEach((i) => {
        var p = document.createElement('p');
        p.innerHTML = i;
        main.appendChild(p);
    });
}

【讨论】:

  • 不幸的是,传入的数组我无法操作...我的意思是我可以,但我宁愿直接使用传入的内容,以保持代码“更干净”。
  • @Sergio 动态访问变量是糟糕的设计,它限制了函数的使用方式。用对象替换动态变量是正确的做法。
【解决方案3】:
arr = eval(arr);

var str = ["Paul", "John", "Melissa", "Mike"];
var int = [8, 4, 55, 7];
var mix = ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2];

var main = document.querySelector('#main');
var sel = document.querySelector('select');


function testFunc(arr){
  arr = eval(arr);
  arr.forEach((i) => {
    var p = document.createElement('p');
    p.innerHTML = i;
    main.appendChild(p);
  });
}

testFunc(mix);

sel.addEventListener('change', function(){testFunc(this.value)});
<select>
  <option value="str">String</option>
  <option value="int">Integer</option>
  <option value="mix">Mixed</option>
</select>

<div id="main"></div>

【讨论】:

  • eval 应该避免。真的没有必要做这个工作。
  • @trincot 您能否解释一下为什么应该避免使用 eval。这实际上对我有用,我无法操纵传入的数组......我可以但我宁愿不这样做。
  • @trincot 请告诉我们如何避免评估。尝试了 window[arr] 但没有工作。
【解决方案4】:

有几点需要改变:

  • 不要调用传递给addEventListener 方法的函数。而是传递一个函数引用。它可以是内联函数表达式。但不要这样称呼它。

  • 使您的不同数组属性成为一个对象变量,以便您可以根据所选值轻松引用它们。

  • 在更改选择时清除输出。

  • 根据页面加载时选择的项目触发初始更改。

这是一个工作版本:

var arr = {
    str: ["Paul", "John", "Melissa", "Mike"],
    int: [8, 4, 55, 7],
    mix: ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2]
};

var main = document.querySelector('#main');
var sel = document.querySelector('select');

function testFunc(arr){
  main.innerHTML = ""; // clear the previous result
  arr.forEach((i) => {
    var p = document.createElement('p');
    p.innerHTML = i;
    main.appendChild(p);
  });
}

sel.addEventListener('change', () => testFunc(arr[sel.value]));
testFunc(arr[sel.value]); // initial load
<select>
  <option value="str">String</option>
  <option value="int">Integer</option>
  <option value="mix">Mixed</option>
</select>

<div id="main"></div>

如果您的数组是在全局范围内定义的,而您对此无能为力,则只需在新对象中复制对它们的引用即可:

// Defined beforehand: you cannot change this:
var str = ["Paul", "John", "Melissa", "Mike"],
var int = [8, 4, 55, 7],
var mix = ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2]

// In your part of the code, still create array as in above solution:
var arr = {str: str, int: int, mix: mix};
// If you have ES6 support you can shorten the above to:
var arr = {str, int, mix};

【讨论】:

  • trincot,您的解决方案有效,但如果不操作数组,我怎么能做到呢?这些是动态出现的,我真的很想避免弄乱它们,以免产生额外的代码/混乱。
  • “动态进入”是什么意思?能具体点吗?
  • 无论如何,我添加了一些关于如何处理这些全局数组的建议:仍然将对它们的引用放在包装对象中。
【解决方案5】:

如果我没有误解您的要求,那么您必须对现有的 JS 变量进行轻微更改,并将其更改为 Object。之后尝试以这种方式在下拉菜单的每个更改event 上附加新的段落元素,方法是删除现有的main.innerHTML=''

addEventListenerhttps://developer.mozilla.org/en-US/docs/Web/Events/change

对象结构https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics

var data_types = {
  str: ["Paul", "John", "Melissa", "Mike"],
  int: [8, 4, 55, 7],
  mix: ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2]
}

var main = document.querySelector('#main');
var sel = document.querySelector('select');


function testFunc(event) {
   main.innerHTML = '';
  // You can use “this” to refer to the selected element.
  if (!event.target.value) alert('Please Select One');
  var arr = data_types[event.target.value];
  arr.forEach((i) => {
    var p = document.createElement('p');
    p.innerHTML = i;
    main.appendChild(p);
  });
}
  
document.addEventListener('DOMContentLoaded', function() {
  document.querySelector('select[name="data-types"]').onchange = testFunc;
}, false);
<select name="data-types">
  <option value="str">String</option>
  <option value="int">Integer</option>
  <option value="mix">Mixed</option>
</select>

<div id="main"></div>

【讨论】:

  • 因为阳光明媚,我宁愿不操纵阵列并保持它们与我最初列出的一样。它们是动态进入的,为了避免混淆和额外的代码,我宁愿它们保持自己的数组/变量。
  • @Sergio 如果它是动态的,那么你可以用该对象模板上的键值推送它们。
猜你喜欢
  • 2021-12-12
  • 2016-12-08
  • 1970-01-01
  • 2020-02-19
  • 2013-03-22
  • 1970-01-01
  • 2015-09-09
相关资源
最近更新 更多