在JavaScript中使用运算符链接变量 [英] Chained assignment of variables with operators in JavaScript

查看:70
本文介绍了在JavaScript中使用运算符链接变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想快速连续使用运算符对几个变量做一些事情。我不认为我想要做什么是如此重要;我的问题更多的是关于JavaScript评估的基础知识。

I want to do something to a couple of variables using operators in quick succession. I don't think what I want to do is important as such; my question is more about the fundamentals of JavaScript evaluation.

在下面的三个例子中,我尝试使用addition来改变两个变量的值。然而,并非所有表演都像我(可能是天真的)预期的那样。

In the three examples below, I try to use addition to change the values of two variables. However, not all perform as I (perhaps naïvely) expected.

JSFiddle在这里。


  1. 作为三个单独的声明的操作

  1. OPERATIONS AS THREE SEPARATE STATEMENTS

var a = 9, b = 2;
a += b; b += a; a += b;
// a === 24, b === 13


  • 运营由COMMA运营商分离

  • OPERATIONS SEPARATED BY COMMA OPERATOR

    var a = 9, b = 2;
    a += b, b += a, a += b;
    // AS EXPECTED: a === 24, b === 13
    


  • 一个陈述/表达中的操作

  • OPERATIONS IN ONE STATEMENT/EXPRESSION

    var a = 9, b = 2;
    a += (b += (a += b)); 
    // BUT HERE WE GET THIS: a === 22, b === 13
    


  • 在上一个例子中, b 按预期评估,但 a 评估的结果是前两个例子中的第二个。

    In the last example, b evaluates as expected, but a evaluates to a number two short of what appears in the first two examples.

    我认为这是因为括号中的所有内容都返回正确的值,但最终被添加原值 a ,即 9 ,而不是建议的值(a + = b)优先级较早, 11

    I think that this is because everything in the parentheses returns the correct value but is finally added to the original value of a, i.e. 9, rather than the value suggested by (a += b) earlier in precedence which would be 11.

    我看过为什么这可能出现在Flanagan的 JavaScript:The Definitive Guide (第6版)中,(特别是在4.11.1操作分配下)但在那里什么也没找到。 Crockford似乎也没有在 The Good Parts 中明确提及它。我已经使用各种搜索词来尝试查找有关此行为的更多信息。任何人都可以告诉我这种现象被称为是什么或指向我关于这种行为的一些信息(假设它是预期的)或我可能做错了什么(假设它不是)?

    I have looked for why this might be in Flanagan's JavaScript: The Definitive Guide (6th ed.), (particularly under 4.11.1 "Assignment with operation") but found nothing there. Crockford doesn't seem to mention it explicitly in The Good Parts either. I've used various search terms to try to find more information on this behaviour. Can anyone tell me what this phenomenon is called or point me to some information on this behaviour (assuming it is expected) or what I might be doing wrong (assuming it's not)?

    NB。我意识到示例3中的括号可能是多余的,因为据我所知,分配优先顺序从右到左。但我认为有它们会使这个例子更容易讨论。

    NB. I'm conscious that the parentheses in example 3 may be redundant since, as I understand it, assignment precedence goes from right-to-left anyway. But I thought having them there would make the example easier to talk about.

    根据下面的答案判断,我认为我对这个问题的困惑实际上源于从Flanagan书中吸收了几段,可能是错误的:

    Judging by the answers below, I think my confusion over this issue actually stems from having absorbed a couple of paragraphs from the Flanagan book, possibly incorrectly:

    在大多数情况下,表达式为:

    In most cases, the expression:

    a op = b

    其中 op 是一个运算符,相当于表达式:

    where op is an operator, is equivalent to the expression:

    a = a op b

    在第一行中,表达式 a 评估一次。在第二个,它被评估两次。只有当side a 包含副作用(例如函数调用或增量运算符)时,这两种情况才有所不同。例如,以下两个分配不相同:

    In the first line, the expression a is evaluated once. In the second, it is evaluated twice. The two cases differ only if side a includes side effects such as a function call or an increment operator. The following two assignments, for example, are not the same:

    data[i++] *= 2
    data[i++] = data[i++] * 2
    


    我把它带到了意味着我的一行示例应该产生与其他两个相同的结果,因为:

    I took this to mean that my one line example should produce the same results as the other two, because:


    1. Flanagan提到两个评估发生在 a = a op b 而不是1,暗示这实际上不同于 a op = b 其中 a 在右侧不被评估为 lval

    2. 我假设我使用的赋值运算符(例如 a + = b )会被视为副作用。

    1. Flanagan mentions two evaluations occurring in a = a op b as opposed to one, implying this is in fact different to a op= b where a is not evaluated as an lval on the right.
    2. I assumed the assignment operator I used (e.g. a += b) would count as a side-effect.

    恕我直言,我认为Flanagan让这令人困惑,似乎与ECMAScript惯例中的内容相矛盾(如下面的 pocka 所粘贴) ,但这可能是我的阅读/误解。他说的不正确或根本不清楚?或者,只是我吗?

    IMHO, I think Flanagan has made this confusing and it seems to contradict what's in the ECMAScript convention (as pasted below by pocka), but it could be my reading/misinterpretation. Is what he is saying incorrect or simply unclear? Or, is it just me?

    推荐答案

    我认为(不确定,虽然这是违反直觉的)

    I think (not sure, although this is counter-intuitive) you can imagine:

    a += (b += (a += b));
    

    写成:

    a = a + (b += (a += b));
    

    虽然加号 + 运营商有权左关联性,JavaScript表达式从左到右进行计算,因此首先评估 a ,现在 9 ,然后(b + =(a + = b))评估为 13

    Although the plus + operator has right to left associativity, JavaScript expressions are evaluated from left-to-right, so a is evaluated first which is 9 now, then (b += (a += b)) is evaluated to 13.

    现在 + 运算符从右到左添加,因此添加 13 9 并给我们 22

    Now the + operator adds from right-to-left, thus adding 13 to 9 and giving us 22.

    编辑:我不会直接评论你的问题,因为我读到它们感到困惑:)。

    I am not gonna comment directly on your questions because I feel confused by reading them :).

    相反,我会尝试以不同的方式解释。我认为您混淆的主要原因来自运算符优先级,关联性和评估顺序之间的差异。

    Instead I am gonna try to explain this differently. I think the main source of your confusion comes from the difference between operator precedence, associativity and order of evaluation.

    我真的建议您阅读评估顺序中的部分(本书中的4.7.7,顺便说一下这本书很棒)

    I really advise you to read the part on the Order of Evaluation (4.7.7 in the book, which is a great book by the way).

    我们先来看一个例子:

    var x =1, y = 2, z = 3;
    var alpha = (z=4) + y * z;
    console.log(x); // 1
    console.log(y); // 2
    console.log(z); // 4
    console.log(alpha);  // 12
    

    在这个例子中,虽然乘法运算符 * 的优先级高于求和运算符 + ,整个表达式的不同组件的评估仍然是从左到右。

    In this example, although the multiplication operator * has higher precedence than the summation operator +, the the evaluation of the different components of the entire expression is still from left-to-right.

    alpha ,然后(z = 4),然后 y 评估为 2 。现在 z 再次被评估,结果是 4 ,请注意这是由侧面引起的新值 - 在表达式前面将 4 分配给 z 的效果,请记住(z = 4)

    alpha on the left is declared and created first, then (z=4) is evaluated, then y is evaluated to 2. Now z is evaluated again which results in 4, notice that this is the new value which is caused by the side-effect of assigning 4 to z earlier in the expression, remember (z=4).

    这导致 alpha 的总值等于 12

    现在回到原来的表达式:

    Now back to our original expression:

    a += (b += (a += b));
    

    a 9 现在,然后评估左边的第一个 b ,现在 2 ,现在评估第二个 a ,其中 9 也是,然后是最后一个<$ c评估右边的$ c> b 再次 2

    a on the left is evaluated first which is 9 now, then the first b to the left is evaluated which is now 2, now the second a is evaluated which is 9 also, then the last b to the right is evaluated which is again 2.

    现在开始实际工作,由于括号,最后(a + = b)被评估,所以现在我们有 a = 11 ,然后(b + =(a + = b))被评估,现在 13 现在此值总计为评估的值 9 ,从而导致 22

    Now starts the real work, because of the parentheses the last (a += b) is evaluated so now we have a = 11, then (b += (a += b)) is evaluated which is now 13, now this value is summed the value already evaluated which is 9 resulting in 22.

    如果没有这种方式,这将意味着 a 位于 = 将被评估两次,但情况并非如此。

    If it hasn't happened this way, this would mean that a on the left side of = would have been evaluated twice which is not the case.

    摘要:您无法更新已评估的价值表达。

    Summary: You can't update the value of an already evaluated expression.

    我希望这可以为你清楚,如果你有任何其他问题,请随时问:)

    I hope this can clear this for you, if you have any further questions then feel free to ask :)

    这篇关于在JavaScript中使用运算符链接变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆