安全地检查JavaScript中是否未定义多维数组中的元素?

时间:2017-01-13 19:00:15

标签: javascript arrays multidimensional-array undefined

我想知道某个多维数组x中的元素是否未定义,例如:

typeof x[i][j][k] === 'undefined'

问题是如果例如x[i][j]未定义,我会收到错误。为了安全起见,我必须检查:

typeof x === 'undefined' 
|| typeof x[i] === 'undefined'
|| typeof x[i][j] === 'undefined'
|| typeof x[i][j][k] === 'undefined'

但JavaScript是否有更简单的方法来检查x[i][j][k]是否未定义?

4 个答案:

答案 0 :(得分:2)

您可以将其提取到一个tail-call递归函数中,该函数将检查任意级别的嵌套:

const arr = [1, 2, ['a', 'b', [3, undefined]]];
const OUT_OF_BOUNDS = null;

function getNestedElement(arr, levels, levelIndex = 0) {
  const level = levels[levelIndex];
  if (level < 0 || level >= arr.length) {
    return OUT_OF_BOUNDS;
  }
  return (levelIndex === levels.length - 1)
    ? arr[level]
    : getNestedElement(arr[level], levels, levelIndex + 1);
}

function isNestedElementUndefined(arr, levels) {
  return typeof getNestedElement(arr, levels) === 'undefined';
}

// arr[2][2][0] === 3 which is not undefined
console.log(`arr[2][2][0] = ${getNestedElement(arr, [2,2,0])}`);
console.log(`is it undefined? ${isNestedElementUndefined(arr, [2,2,0])}`);

// arr[2][2][1] is undefined
console.log(`arr[2][2][1] = ${getNestedElement(arr, [2,2,1])}`);
console.log(`is it undefined? ${isNestedElementUndefined(arr, [2,2,1])}`);

// arr[2][2][2] is out of bounds so it will be null
console.log(`arr[2][2][2] = ${getNestedElement(arr, [2,2,2])}`);
console.log(`is it undefined? ${isNestedElementUndefined(arr, [2,2,2])}`);

这里也是一个迭代版本:

const arr = [1, 2, ['a', 'b', [3, undefined]]];
const OUT_OF_BOUNDS = null;

function getNestedElement(arr, levels) {
  for (const level of levels) {
    if (level < 0 || level >= arr.length) {
      return OUT_OF_BOUNDS;
    }
    arr = arr[level];
  }
  
  return arr;
}

function isNestedElementUndefined(arr, levels) {
  return typeof getNestedElement(arr, levels) === 'undefined';
}



// arr[2][2][0] === 3 which is not undefined
console.log(`arr[2][2][0] = ${getNestedElement(arr, [2,2,0])}`);
console.log(`is it undefined? ${isNestedElementUndefined(arr, [2,2,0])}`);

// arr[2][2][1] is undefined
console.log(`arr[2][2][1] = ${getNestedElement(arr, [2,2,1])}`);
console.log(`is it undefined? ${isNestedElementUndefined(arr, [2,2,1])}`);

// arr[2][2][2] is out of bounds so it will be null
console.log(`arr[2][2][2] = ${getNestedElement(arr, [2,2,2])}`);
console.log(`is it undefined? ${isNestedElementUndefined(arr, [2,2,2])}`);

注意:上面的解决方案假设null是一个特殊的值,它不会出现在数组中,所以它不会用于传达结果。如果你不能保证null不在你的数组中,你可以抛出一个错误,或者可能返回一个包含该值的对象和一个指示是否找到该值的布尔值。

类似的东西:

const arr = [1, 2, ['a', 'b', [3, undefined]]];

function getNestedElement(arr, levels, levelIndex = 0) {
  const level = levels[levelIndex];
  if (level < 0 || level >= arr.length) {
    return { found: false };
  }
  return (levelIndex === levels.length - 1)
    ? { value: arr[level], found: true }
    : getNestedElement(arr[level], levels, levelIndex + 1);
}

function isNestedElementUndefined(arr, levels) {
  const { value, found } = getNestedElement(arr, levels);
  return found ? typeof value === 'undefined' : false;
}

// arr[2][2][0] === 3 which is not undefined
console.log(`arr[2][2][0] = ${getNestedElement(arr, [2,2,0]).value}`);
console.log(`is it undefined? ${isNestedElementUndefined(arr, [2,2,0])}`);

// arr[2][2][1] is undefined
console.log(`arr[2][2][1] = ${getNestedElement(arr, [2,2,1]).value}`);
console.log(`is it undefined? ${isNestedElementUndefined(arr, [2,2,1])}`);

// arr[2][2][2] is out of bounds
const { value, found } = getNestedElement(arr, [2,2,2]);
console.log(`arr[2][2][2] = ${found ? value : 'Not Found'}`);
console.log(`is it undefined? ${isNestedElementUndefined(arr, [2,2,2])}`);

这是迭代的堂兄:

const arr = [1, 2, ['a', 'b', [3, undefined]]];
const OUT_OF_BOUNDS = null;

function getNestedElement(arr, levels) {
  for (const level of levels) {
    if (level < 0 || level >= arr.length) {
      return { found: false };
    }
    arr = arr[level];
  }
  
  return { value: arr, found: true };
}

function isNestedElementUndefined(arr, levels) {
  const { value, found } = getNestedElement(arr, levels);
  return found ? typeof value === 'undefined' : false;
}

// arr[2][2][0] === 3 which is not undefined
console.log(`arr[2][2][0] = ${getNestedElement(arr, [2,2,0]).value}`);
console.log(`is it undefined? ${isNestedElementUndefined(arr, [2,2,0])}`);

// arr[2][2][1] is undefined
console.log(`arr[2][2][1] = ${getNestedElement(arr, [2,2,1]).value}`);
console.log(`is it undefined? ${isNestedElementUndefined(arr, [2,2,1])}`);

// arr[2][2][2] is out of bounds
const { value, found } = getNestedElement(arr, [2,2,2]);
console.log(`arr[2][2][2] = ${found ? value : 'Not Found'}`);
console.log(`is it undefined? ${isNestedElementUndefined(arr, [2,2,2])}`);

答案 1 :(得分:1)

if(x && x[i] && x[i][j] && x[i][j][k]) { }是一种方法,基于undefined是一个假值的前提,并且如果遇到if-statement,它将会短路。

作为替代方案,"It's easier to ask forgiveness than it is to get permission"。有时您可以尝试使用它并在使用try-catch块时无法处理它。 Here is another question/answer that explains the philosophy

答案 2 :(得分:1)

嵌套的三元组会更容易,但它的可读性也会低得多。

let x = [[[[]]]], // will return true
    i = 0,
    j = 0,
    k = 0;

    let isDefined = x ? x[i] ? x[i][j] ? x[i][j][k] ? true : false : false : false : false;

删除数组的任何部分后,isDefined将返回false。它还将按顺序进行评估,因此您可以为false值返回其他内容,以通知它失败的深度。

答案 3 :(得分:0)

没有其他方法可以进行检查,除非您可以通过以下方式缩短代码:

if(x && x[i] && x[i][j] && x[i][j][k]) {
 }

只要&amp;&amp; 之前的术语保持返回true,上述声明就会继续检查。只要找到错误值或未定义,它就会停止检查重新定义的条款。