Skip to content

表达式与运算符

运算符

WhirlScript 的运算符和其它编程语言(如 Java、JS)很相似。

赋值运算符

一个 赋值运算符 (assignment operator) 将它右边操作数的值赋给它左边的操作数。最简单的赋值运算符是等于(=),它将右边的操作数值赋给左边的操作数。那么 x = y 就是将 y 的值赋给 x。

还有一些复合赋值操作符,它们是下表列出的这些操作的缩写:

名字简写的操作符含义
赋值 (Assignment)x = yx = y
加法赋值 (Addition assignment)x += yx = x + y
减法赋值 (Subtraction assignment)x -= yx = x - y
乘法赋值 (Multiplication assignment)x *= yx = x * y
除法赋值 (Division assignment)x /= yx = x / y
求余赋值 (Remainder assignment)x %= yx = x % y
求幂赋值 (Exponentiation assignment)x **= yx = x ** y
左移位赋值 (Left shift assignment)x <<= yx = x << y
右移位赋值 (Right shift assignment)x >>= yx = x >> y
按位与赋值 (Bitwise AND assignment)x &= yx = x & y
按位异或赋值 (Bitwise XOR assignment)x ^= yx = x ^ y
按位或赋值 (Bitwise OR assignment)x |= yx = x | y

比较运算符

比较运算符比较它的操作数并返回一个基于表达式是否为真的逻辑值。操作数可以是数字,字符串,逻辑,对象值。字符串比较是基于标准的字典顺序,使用 Unicode 值。在多数情况下,如果两个操作数不是相同的类型,JavaScript 会尝试转换它们为恰当的类型来比较。这种行为通常发生在数字作为操作数的比较。类型转换的例外是使用 ===!== 操作符,它们会执行严格的相等和不相等比较。这些运算符不会在检查相等之前转换操作数的类型。下面的表格描述了该示例代码中的各比较运算符

WhirlScript
var var1 = 3;
var var2 = 4;
运算符描述返回 true 的示例
等于 Equal (==)如果两边操作数相等时返回 true。3 == var1 "3" == var1 3 == '3'
不等于 Not equal (!=)如果两边操作数不相等时返回 truevar1 != 4 var2 != "3"
大于 Greater than (>)左边的操作数大于右边的操作数返回 truevar2 > var1 "12" > 2
大于等于 Greater than or equal (>=)左边的操作数大于或等于右边的操作数返回 truevar2 >= var1 var1 >= 3
小于 Less than (<)左边的操作数小于右边的操作数返回 truevar1 < var2 "2" < 12
小于等于 Less than or equal (<=)左边的操作数小于或等于右边的操作数返回 truevar1 <= var2 var2 <= 5

算术运算符

算术运算符使用数值 (字面量或者变量) 作为操作数并返回一个数值。标准的算术运算符就是加减乘除 (+ - * /)。

WhirlScript 并不提供浮点类型。这意味着,您得不到小数。结果将会向下取整。例如:

WhirlScript
1 / 2; // 0

除了标准的算术运算符,WhirlScript 还提供了下表中的算术运算符。

运算符描述示例
求余(%二元运算符。返回相除之后的余数。12 % 5 返回 2。
自增(++一元运算符。将操作数的值加一。如果放在操作数前面(++x),则返回加一后的值;如果放在操作数后面(x++),则返回操作数原值,然后再将操作数加一。var x=3; println(++x); //4 println(x); //4 var y=3; println(y++); //3 println(y); //4
自减(--一元运算符。将操作数的值减一。前后缀两种用法的返回值类似自增运算符。var x=3; println(--x); //2 var y=3; println(y--); //3
一元负值符(-一元运算符,返回操作数的负值。var x=3; println(-x); //-3
一元正值符(+一元运算符,如果操作数在之前不是数值,试图将其转换为数值。println( +'3' ); // 3 println( '3' ); // '3' println(+true); // 1
指数运算符(**计算底数(base)的指数(exponent)次方,表示为 base^exponent2 ** 3 返回 810 ** -1 返回 0.1

位运算符

⚠️ 警告

位运算语法还在设计中

位运算符将它的操作数视为 32 位元的二进制串(0 和 1 组成)而非十进制八进制或十六进制数。例如:十进制数字 9 用二进制表示为 1001,位运算符就是在这个二进制表示上执行运算,但是返回结果是标准的 WhirlScript 数值。

下表总结了 WhirlScript 的位运算符。

操作符用法描述
按位与 ANDa & b在 a,b 的位表示中,每一个对应的位都为 1 则返回 1,否则返回 0.
按位或 ORa | b在 a,b 的位表示中,每一个对应的位,只要有一个为 1 则返回 1,否则返回 0.
按位异或 XORa ^ b在 a,b 的位表示中,每一个对应的位,两个不相同则返回 1,相同则返回 0.
按位非 NOT~ a反转被操作数的位。
左移 shifta << b将 a 的二进制串向左移动 b 位,右边移入 0.
算术右移a >> b把 a 的二进制表示向右移动 b 位,丢弃被移出的所有位。(译注:算术右移左边空出的位是根据最高位是 0 和 1 来进行填充的)
无符号右移 (左边空出位用 0 填充)a >>> b把 a 的二进制表示向右移动 b 位,丢弃被移出的所有位,并把左边空出的位都填充为 0

位逻辑运算符

概念上来讲,位逻辑运算符工作流程如下:

  • 操作数被转换为 32bit 整數,以位序列(0 和 1 组成)表示。若超過 32bits,則取低位 32bit,如下所示:
txt
  Before: 11100110111110100000000000000110000000000001
  After:              10100000000000000110000000000001
  • 第一个操作数的每一位都与第二个操作数的对应位组对:第一位对应第一位,第二位对应第二位,以此类推。
  • 运算符被应用到每一对"位"上,最终的运算结果由每一对“位”的运算结果组合起来。

例如,十进制数 9 的二进制表示是 1001,十进制数 15 的二进制表示是 1111.因此,当位运算符应用到这两个值时,结果如下:

表达式结果二进制描述
15 & 991111 & 1001 = 1001
15 | 9151111 | 1001 = 1111
15 ^ 961111 ^ 1001 = 0110
~15-16~ 0000 0000 … 0000 1111 = 1111 1111 … 1111 0000
~9-10~ 0000 0000 … 0000 1001 = 1111 1111 … 1111 0110

注意位运算符“非”将所有的 32 位取反,而值的最高位 (最左边的一位) 为 1 则表示负数 (2-补码表示法)。

移位运算符

移位运算符带两个操作数:第一个是待移位的数,第二个是指定第一个数要被移多少位的数。移位的方向由运算符来控制。

移位运算符把操作数转为 32bit 整数,然后得出一个与待移位数相同种类的值。

移位运算符列表如下。

运算符描述示例
<<(左移位)将第一个操作数向左移动指定数量的位。左边移出位被抛弃。左边移出的几位被丢弃。右边多出的空位由 0 补齐。9<<2 产生 36,因为 1001 移位 2 比特向左变为 100100,它是 36。
>>(带符号右移)将第一个操作数向右移动指定数量的位。右边移出位被抛弃。左边多出的空位由原值的最左边数字补齐。9>>2 产生 2,因为 1001 移位 2 位向右变为 10,其是 2。同样,-9>>2 产生 -3,由于符号被保留。

逻辑运算符

逻辑运算符常用于布尔(逻辑)值之间; 当操作数都是布尔值时,返回值也是布尔值。不过实际上&&||返回的是一个特定的操作数的值,所以当它用于非布尔值的时候,返回值就可能是非布尔值。逻辑运算符的描述如下。

运算符范例描述
逻辑与(&&)expr1 && expr2(逻辑与) 如果 expr1 能被转换为 false,那么返回 expr1;否则,返回expr2。因此,&&用于布尔值时,当操作数都为 true 时返回 true;否则返回 false.
逻辑或 (||)expr1 || expr2(逻辑或) 如果 expr1 能被转换为 true,那么返回 expr1;否则,返回expr2。因此,|| 用于布尔值时,当任何一个操作数为 true 则返回 true;如果操作数都是 false 则返回 false。
逻辑非 (!)!expr(逻辑非) 如果操作数能够转换为 true 则返回 false;否则返回 true。

下面是&&(逻辑"与")操作符的示例。

WhirlScript
var a1 = true && true; // t && t returns true
var a2 = true && false; // t && f returns false
var a3 = false && true; // f && t returns false
var a4 = false && 3 == 4; // f && f returns false

下面是 ||(逻辑"或")操作符的示例。

WhirlScript
var o1 = true || true; // t || t returns true
var o2 = false || true; // f || t returns true
var o3 = true || false; // t || f returns true
var o4 = false || 3 == 4; // f || f returns false

下面是!(逻辑"非")操作符的示例。

js
var n1 = !true; // !t returns false
var n2 = !false; // !f returns true

短路求值

作为逻辑表达式进行求值是从左到右,它们是为可能的“短路”的出现而使用以下规则进行测试:

  • false && anything // 被短路求值为 false
  • true || anything // 被短路求值为 true

逻辑的规则,保证这些评估是总是正确的。请注意,上述表达式的anything部分不会被求值,所以这样做不会产生任何副作用。

字符串运算符

除了比较操作符,它可以在字符串值中使用,连接操作符(+)连接两个字符串值相连接,返回另一个字符串,它是两个操作数串的结合。

例如,

WhirlScript
println("my " + "string"); // console logs the string "my string".

简写操作符 += 也可以用来拼接字符串,例如:

WhirlScript
var myString = "alpha";

myString += "bet"; // 返回 "alphabet"

条件(三元)运算符

条件运算符是 JavaScript 中唯一需要三个操作数的运算符。运算的结果根据给定条件在两个值中取其一。语法为:

txt
条件 ? 值 1 : 值 2

如果条件为真,则结果取值 1。否则为值 2。你能够在任何允许使用标准运算符的地方使用条件运算符。

例如,

WhirlScript
var status = age >= 18 ? "adult" : "minor";

age 大于等于 18 的时候,将“adult”赋值给 status;否则将“minor”赋值给 status

运算符优先级

运算符的优先级,用于确定一个表达式的计算顺序。在你不能确定优先级时,可以通过使用括号显式声明运算符的优先级。

下表列出了描述符的优先级,从最高到最低。

类型操作符
调用. :: ()
自增/自减++ --
!
乘/除* / %
加/减+ -
移位<< >> >>>
大小比较< <= > >=
相等判断== !=
逻辑与&&
逻辑或||
条件判断?:
赋值= += -= *= /= %=

表达式

表达式是一组代码的集合,它返回一个值。(译注:定义比较不好理解,看下面的举例就很好懂了。)

每一个合法的表达式都能计算成某个值,但从概念上讲,有两种类型的表达式:有副作用的(比如赋值)和单纯计算求值的。

表达式 x=7 是第一类型的一个例子。该表达式使用=运算符将值 7 赋予变量 x。这个表达式自己的值等于 7。

代码 3 + 4 是第二个表达式类型的一个例子。该表达式使用 + 运算符把 3 和 4 加到一起但并没有把结果(7)赋值给一个变量。

WhirlScript 有以下表达式类型:

  • 算数:得出一个数字,例如 3.14159。(通常使用算数运算符
  • 字符串:得出一个字符串,例如,"Fred" 或 "234"。(通常使用字符串运算符。)
  • 逻辑值:得出 true 或者 false。(经常涉及到逻辑运算符。)
  • 基本表达式:WhirlScript 中基本的关键字和一般表达式。
  • 左值表达式:分配给左值。

分组操作符

分组操作符()控制了表达式中计算的优先级。举例来说,你可以改变先乘除后加减的顺序,转而先计算加法。

WhirlScript
var a = 1;
var b = 2;
var c = 3;

// 默认优先级
a + b * c; // 7
// 默认是这样计算的
a + b * c; // 7

// 现在使加法优先于乘法
(a + b) * c; // 9

// 这等价于
a * c + b * c; // 9

左值表达式

左值可以作为赋值的目标。

Released under the MIT License.