【问题标题】:How can I reference a primitive type in JavaScript?如何在 JavaScript 中引用原始类型?
【发布时间】:2019-12-20 15:45:33
【问题描述】:

我想让这样的函数在 JavaScript 中按预期工作:

function isLastElem(array, elem) {
    if (elem === array[array.length-1]) {
        return true;
    }
    else {
        return false;
    }
}

目的是该函数应该能够识别任何数组的最后一个元素。例如:

let arr = [0, 1, 2];
console.log(isLastElem(arr, 2)); // I would expect false to be returned
console.log(isLastElem(arr, arr[2])); // I would expect true to be returned

但是,由于数字是原始值,它们通过它们的值传递给函数,因此两个函数调用都返回 true。 有什么办法可以解决这个问题并通过引用传递数字?

这里的重要想法是让它在每个循环中都可用。例如:

let arr = [0, 1, 0];
arr.forEach((elem) => {
    if (isLastElem(arr, elem)) {
        console.log("Found the last element!");
    }
});

函数应该在第一个 0 处返回 false,因为它不是数组的最后一个元素。然后在第二个 0 它应该返回 true 并记录消息。

【问题讨论】:

  • 但是 ... 2 实际上是 === 到 2。所有为 2 的数值都无法区分。
  • 您必须比较内存空间条目,这在 JavaScript 中是不可能的。
  • 即使对于对象,您的代码也只有在您传递实际的数组元素值时才有意义。由于您必须知道索引才能执行此操作,因此将索引与数组长度进行比较会简单得多。
  • 如果要传递“对数组元素的引用”,请改为传递数组和索引。在这种情况下,巧合的是arr 和2。 (讨论数组元素是否不等于索引会是一个更好的例子)。
  • 所以,根据 Rager 的回应,我想要做的事情几乎是不可能的。可惜了,不过还是谢谢!

标签: javascript arrays object reference primitive


【解决方案1】:

您可以通过将您的数字包装在一个数组或对象中来做到这一点,就像这样:

let arr = [[0], [1], [2]];
console.log(isLastElem(arr, [2])); // returns false
console.log(isLastElem(arr, arr[2])); // returns true

【讨论】:

    【解决方案2】:

    尽管我很难想象为什么有人需要这样做,但我认为我们可以通过 Symbol 完成这项工作:

    从 Symbol() 返回的每个符号值都是唯一的。符号值可以用作对象属性的标识符;这是数据类型的唯一用途。

    所以这意味着我们可以使用Symbol 来标记数组的每个元素。如您所见,1s 的数组可以转换为1 的符号数组,它们全部是唯一的:

    const xs = [1, 1];
    
    xs[0] === xs[1];
    //=> true
    
    const ys = [Symbol(1), Symbol(1)];
    
    ys[0] === ys[1];
    //=> false
    
    ys[0] === Symbol(1);
    //=> false
    
    ys[1] === ys[1];
    //=> true
    

    因此,要识别数组的最后一个元素,您实际上需要对该元素的引用:

    console.log(
    
      [1, 1, 1]
        // convert to list of symbols of 1
        .map(Symbol)
        // check if current element is equal to the last element
        .map((x, _, xs) => x === xs[xs.length - 1])
        
    );
    //=> [false, false, true]

    当然,问题在于它将每个元素包裹在一个无法逃脱的盒子中。

    我们可以将每个元素放在一个对象中,隐藏在一个“秘密唯一”键后面。每个对象都有一个方法来提取其值并与其他类似对象进行比较:

    const obj = (k, v) => (
      { [k]: v
      , get: () => v
      , equals: o => o[k] === v
      });
    
    const stamp = (arr, secret = Date.now()) =>
      arr.map((x, i) => obj(`${secret}@@${i}`, x));
      
    const arr = stamp([1, 1, 1]);
    
    arr.forEach((x, _, xs) => {
      console.log(x.get(), x.equals(xs[xs.length - 1]));
    });

    【讨论】:

      【解决方案3】:

      您可能不存储本机号码,而是一个 Number..的实例。

      例如。

      function isLastElem(array, elem) {
          if (elem === array[array.length-1]) {
              return true;
          }
          else {
              return false;
          }
      }
      
      let arr = [new Number(0), new Number(1), new Number(2)];
      
      console.log(isLastElem(arr, 2)); // I would expect false to be returned
      console.log(isLastElem(arr, arr[2])); // I would expect true to be returned

      【讨论】:

      • 是的,这将是一个解决方案,但使用new Number 通常是一种非常糟糕的做法。
      • 恐怕这在我目前的项目中是不可能的:(不过谢谢你的回答。
      • @Bergi 是的,我个人不会这样做。但只是回答OP的问题。具体来说——>Any way to solve this and pass numbers by reference?
      【解决方案4】:

      你可以试试这个代码

      
      let arr = [0, 1, 2];
      console.log(isPrimitive(arr[index+1]));
      
      function isPrimitive(val) {
        return isString(val) || isBoolean(val) || (isNumber(val) && !isNaN(val));
      }
      

      【讨论】:

      • 这和问题有什么关系?
      • @Pointy 检查数组索引 => 例如 isPrimitive(index + 1)
      猜你喜欢
      • 2015-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-22
      • 1970-01-01
      • 2016-01-21
      • 1970-01-01
      相关资源
      最近更新 更多