【问题标题】:Reference error (left-hand asignment) in array assignment数组赋值中的引用错误(左赋值)
【发布时间】:2018-02-02 20:10:09
【问题描述】:

我有以下代码,我试图在参数的帮助下执行一个函数。该参数告诉 Javascript 对其指示的数组/字符串执行操作(例如,如果 id 参数为 0,则为 ps 数组和 properties 字符串,如果 @987654328 为 as 数组和 attributes 字符串@不是0):

var properties = "apple=fruit";
var attributes = "carrot=vegetable banana=fruit cherry=fruit fruit";
var ps = [];
var as = [];

function getpsas(id)
  {
  (id === 0 ? ps : as) = (id === 0 ? properties : attributes).split(" ").map
    (
    function(element)
      {
      var eqlpos = element.lastIndexOf("=");
      return {name: element.substr(0, eqlpos), type: element.substr(eqlpos + 1)};
      }
    ).filter
      (
      function(element)
        {
        return (/^(vegetable|fruit)$/.test(element.type));
        }
      );
  }

getpsas(0);
getpsas(1);

console.log(ps);
console.log(as);

Fiddle 在这里。它在(id === 0 ? ps : as) = 部分抛出“未捕获的引用错误:分配中无效的左侧”。如果我从= 的左侧删除括号,它可以工作,除了它只执行后一个数组(又名as)而不是前一个数组(又名ps)的函数。

我知道我在这里做错了,缺少一个符号/一对括号或其他东西。我检查了operator precedence in Javascript,关于同一问题的其他问题,但都表明它应该工作,因为操作员(我认为)是正确的,例如=== 用于条件,简单的= 用于赋值等。最困扰我的是三元运算符中的其他引用工作(此示例的右侧部分,我的代码的其他部分)。

那么……这个有什么问题?

【问题讨论】:

    标签: javascript arrays variable-assignment operator-keyword ternary


    【解决方案1】:

    您不能在作业的左侧使用? :。三元运算符表达式的值始终是value,而不是reference;编程语言的人们通常使用术语 r-valuel-value。您只能分配给 l-value,但不能使用 ? : 生成 l-value

    “l”和“r”分别代表“left”和“right”,与赋值运算符相关。当然,并非所有语言都从右到左分配;音乐编程语言“Chuck”就是一个反例。

    如果您要为对象属性赋值,您可以执行以下操作:

    someObject[foo == bar ? "x" : "y"] = whatever();
    

    这是因为? : 是一个子表达式,它是赋值左侧确定的一部分。没关系,因为外部 [ ] 表达式返回一个 l-value

    【讨论】:

    • 我不得不承认这是最好的答案,因为它准确地解释了发生了什么以及为什么我的方法不正确。我在没有使用“对象”(严格来说)的情况下解决了这个问题,但是通过将等式的右侧部分分配给“虚拟数组”(名为 temp),然后制作 if (id === 0) {ps = temp;} else {as = temp} 在我的函数结束时。如果您提供适用于我的特定代码的简单解决方案,您的答案将是完美的,但即便如此,它也是最好的答案。谢谢你。不得不删除并重新发布我更正的评论,因为我无法编辑它。
    【解决方案2】:

    表达式(id === 0 ? ps : as) 返回psas 的值。如果您想将 something 分配给变量,请执行以下操作:

    if (0 === id) ps = something;
    else as = something;
    

    另一种方法是将对象包裹在psas 周围,并通过计算成员访问有条件地设置任一成员:

    const obj = {
        ps: [],
        as: [],
    }
    
    obj[0 === id ? 'ps' : 'as'] = something;
    

    【讨论】:

    • 很好的答案,以解决方案为导向,但它没有解释为什么会发生这种情况(Pointy 的答案并不缺乏)。我不得不标记他的答案,因为我实际上明白我错在哪里。尽管如此,我还是给了你一个赞成票 - 谢谢。
    【解决方案3】:

    您可以使用数组执行destructuring assignment,并使用computed property names 正确分配结果。

    function getpsas(id) {
        [ps, as] = Object.assign([ps, as], {
            [id]: [properties, attributes][id]
                .split(" ")
                .map(function (element) { var eqlpos = element.lastIndexOf("="); return { name: element.substr(0, eqlpos), type: element.substr(eqlpos + 1) }; })
                .filter(element => /^(vegetable|fruit)$/.test(element.type))
        });
    }
    
    var properties = "apple=fruit",
        attributes = "carrot=vegetable banana=fruit cherry=fruit fruit",
        ps = [],
        as = [];
    
    getpsas(0);
    getpsas(1);
    
    console.log(ps);
    console.log(as);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 感谢您提供完全适合我的代码的解决方案。就像杰弗里的回答一样,这无疑是有帮助的,但并没有解释我错在哪里。不过确实给你投票了。
    • 这只是一个答案,有什么可能。 Pointy已经很好地描述了您的问题,无需重复。
    • 确实如此。您可以查看我对 Pointy 的评论,看看我是如何在不使用其他对象(临时数组除外)的情况下解决它的。
    猜你喜欢
    • 2011-05-06
    • 2012-07-26
    • 1970-01-01
    • 2011-12-20
    • 2011-03-04
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    相关资源
    最近更新 更多