为什么数字有效时它会显示为未定义?

时间:2020-04-24 13:52:20

标签: javascript

我有此代码要求在td中显示一个数字。但是它不能正常工作。

用户只能输入在func1中传递的最小值和最大值之间的值。并且该数字必须是有效数字。

如果满足这些条件,则td应该显示用户输入的号码,否则应再次出现提示用户输入有效数字的提示。

如果用户首先输入一个有效数字,则该代码有效,例如,在这种情况下,最小值为1,最大值为10,如果用户在这两个值之间输入数字,则该代码有效用户出现在td上。但是,如果用户输入数字0,则会出现消息“值0无效”,并再次出现提示,这是正确的。但是,如果用户输入的有效数字(例如1),则在td中显示为未定义,而不是1。

你知道为什么吗?

HTML

<tr>
    <td>Number</td>
    <td id="tdNumber"></td>
    <td>
        <button onclick="func1()">Add</button>
    </td>
</tr>

JS

let config = {
  numberX: NUMBER_X
}

function showConfig() {
  document.getElementById(TD_NUMBER).innerHTML = config.numberX;
}

function func1() {
  config.numberX = func2(1, 10, P_CONSTANT);
  showConfig();
}

function func2(min, max, p = P_CONSTANT) {
  var number = parseInt(prompt("Enter a number between " + min + "and " + max));
  if (!Number.isInteger(number)) {
    alert("The number " + number + " is not valid.");
    func1();
  } else if (number > max || number < min) {
    alert("The number " + number + " is not valid");
    func1();
  } else {
    return number;
  }
}

3 个答案:

答案 0 :(得分:0)

程序的结构是真正的问题。可能可以使它起作用,但这不是实现它的方法。取而代之的是让func2()返回一些表示无效数字的值,然后在func1()内进行迭代:

const INVALID = {};
function func1() {
  let p;
  for (p = func2(1, 10); p === INVALID; p = func2(1, 10)) {
    alert("Invalid value");
  }
  config.numberX = p;

  showConfig();
}

function func2(min, max, p = P_CONSTANT) {

  var number = parseInt(prompt("Enter a number between " + min + "and " + max));

  if(!Number.isInteger(number)){
     return INVALID;
  }

  if(number > max || number < min){
     return INVALID;
  }


  return number;
}

答案 1 :(得分:0)

您编写func1func2的方式,他们可以无限制地互相呼叫。想象一下这种情况:

  1. func1()被称为(称为func1_A
  2. func1_A呼叫func2()以获取号码(这是func2_B
  3. 用户输入了无效号码,func2_B发起了另一个呼叫func1func1_C
  4. 此新调用func1_C调用func2()以获取新号码(func2_D
  5. 用户输入有效数字,func2_D返回有效数字,func1_C将其分配给numberX
  6. func1_C返回,执行返回到一直在等待的func2_Bfunc2_B无事可做,因此返回undefined
  7. func1_Aundefined获取func2_B并将其分配给numberX

基本上,您拥有这些互相调用的功能的事实将继续向堆栈中添加 new 调用,而 old 调用必须等待这些调用才能返回。而且重要的是,旧的将恢复-这意味着最后发生的事情将始终是func1分配func2的最新返回值,如果用户 ever 输入了该值无效的数字将是undefined


Pointy是对的:这是一种非常差的格式,容易出现很多问题。这不是您应该追求的方法。至少,您的代码不应因不必要的递归函数调用而不必要地容易出现堆栈溢出错误。

您可以使用while循环将其简化很多。我也是有意义名称的忠实拥护者,func1 / func2与有意义的名称相距甚远,因此我已将函数重命名。

const NUMBER_X = 10;
const P_CONSTANT = "???";
const TD_NUMBER = "tdNumber";

let config = {
  numberX: NUMBER_X
};

function showConfig() {
  console.log(document.getElementById(TD_NUMBER));
  document.getElementById(TD_NUMBER).innerHTML = config.numberX;
}

function setNumber() {
  config.numberX = getValidNumber(1, 10, P_CONSTANT);
  showConfig();
}

function getValidNumber(min, max, p = P_CONSTANT) {
  var isValid = false;
  var number;

  do {
     number = parseInt(prompt("Enter a number between " + min + " and " + max));
     if(!Number.isInteger(number)) {
        alert("The number " + number + " is not valid.");
     } else if(number > max || number < min) {
        alert("The number " + number + " is not valid");
     } else {
        isValid = true;
     }
  } while(!isValid);

  return number;
}
<table>
  <tr>
    <td>Number</td>
     <td id="tdNumber"></td>
    <td><button onclick="setNumber()">Add</button></td>
  </tr>
</table>

答案 2 :(得分:0)

func1呼叫func2时, func1等待响应。

如果输入错误,func1就不会得到答案,因为func2再次调用func1 ...

这总共使 2 func1个功能都等待响应
如果新输入的内容有误,则将使它成为第三个;

只有这个堆栈上的最后一个会得到回报,
而所有其他func1将继续徒劳地等待

正确的编码方式是:

const tdNumber   = document.getElementById('td-number')
  ,   NUMBER_X   = 10
  ,   minVal     = 1
  ,   maxVal     = 10
  ,   config     = { numberX: NUMBER_X }
  ;
function setNumber()
  {
  let numberStr = ''
    , numberIn  = 0
    , badEntry  = true
    ;
  do
    {
    numberStr = prompt( "Enter a number between " + minVal + "and " + maxVal )
    numberIn  = parseFloat( numberStr )
    badEntry  = ( !Number.isInteger( numberIn ))
                || numberIn < minVal
                || numberIn > maxVal
                ;
    if ( badEntry )
      { alert("The number " + numberStr + " is not valid") }
    }
  while ( badEntry )

  tdNumber.textContent = config.numberX = numberIn
  }
table {
  border-collapse: collapse;
  margin: 1em;
  }
td {
  border: solid grey 1px;
  padding: 1em;
  text-align : center;
  }
#td-number {
  width : 4em
  }
<table>
  <tr>
    <td>Number</td>
    <td id="td-number"></td>
    <td><button onclick="setNumber()">Add</button></td>
  </tr>
</table>