JavaScript基本运算符
基本运算符,数学运算符
我们在学校认识很多操作员。它们是加法+、乘法*、减法-等。
在本章中,我们将从简单的运算符开始,然后专注于 JavaScript 特定的方面,学校算术没有涵盖。
术语:“一元”、“二进制”、“操作数”
在我们继续之前,让我们掌握一些常用术语。
操作数– 是应用运算符的对象。例如,在乘法中5 * 2有两个操作数:左操作数是5,右操作数是2。有时,人们称这些为“参数”而不是“操作数”。
如果运算符只有一个操作数,则它是一元运算符。例如,一元否定-反转数字的符号:
let x = 1; x = -x; alert( x ); // -1, unary negation was applied
如果一个运算符有两个操作数,则它是二元的。同样的减号也以二进制形式存在:
let x = 1, y = 3; alert( y - x ); // 2, binary minus subtracts values
形式上,在上面的例子中,我们有两个不同的运算符共享相同的符号:否定运算符,一种反转符号的一元运算符,以及减法运算符,一种将一个数与另一个数相减的二元运算符。
数学运算符
支持以下数学运算:
加法+,
减法-,
乘法*,
除法/,
余数%,
求幂**。
前四个是直接的,而%并**需要对他们几句。
剩余百分比
%尽管出现了余数运算符,但它与百分比无关。
的结果a % b是剩余的整数除法的a通过b。
例如:
alert( 5 % 2 ); // 1, a remainder of 5 divided by 2 alert( 8 % 3 ); // 2, a remainder of 8 divided by 3
求幂 **
乘方运算a ** b提升a到的功率b。
在学校数学中,我们将其写为 a b。
例如:
alert( 2 ** 2 ); // 2² = 4 alert( 2 ** 3 ); // 2³ = 8 alert( 2 ** 4 ); // 2⁴ = 16
就像在数学中一样,幂运算符也被定义为非整数。
例如,平方根是 ½ 的幂:
alert( 4 ** (1/2) ); // 2 (power of 1/2 is the same as a square root) alert( 8 ** (1/3) ); // 2 (power of 1/3 is the same as a cubic root)
与二进制 + 的字符串连接
让我们来看看 JavaScript 运算符超出学校算术的特性。
通常,加号运算符对+数字求和。
但是,如果二进制文件+应用于字符串,它会合并(连接)它们:
let s = "my" + "string"; alert(s); // mystring
请注意,如果任何操作数是字符串,则另一个操作数也将转换为字符串。
例如:
alert( '1' + 2 ); // "12" alert( 2 + '1' ); // "21"
看,第一个操作数是字符串还是第二个操作数并不重要。
这是一个更复杂的例子:
alert(2 + 2 + '1' ); // "41" and not "221"
在这里,操作员一个接一个地工作。第一个对+两个数字求和,所以它返回4,然后下一个+将字符串添加1到它,所以它就像4 + '1' = '41'.
alert('1' + 2 + 2); // "122" and not "14"
这里,第一个操作数是字符串,编译器也将其他两个操作数视为字符串。将2被串联到'1',所以它就像'1' + 2 = "12"和"12" + 2 = "122"。
二进制+是唯一以这种方式支持字符串的运算符。其他算术运算符仅适用于数字,并且始终将其操作数转换为数字。
这是减法和除法的演示:
alert( 6 - '2' ); // 4, converts '2' to a number alert( '6' / '2' ); // 3, converts both operands to numbers
数值转换,一元+
加号+有两种形式:我们上面使用的二进制形式和一元形式。
一元加号,换句话说,加号运算符+应用于单个值,对数字没有任何作用。但如果操作数不是数字,则一元加号会将其转换为数字。
例如:
// No effect on numbers let x = 1; alert( +x ); // 1 let y = -2; alert( +y ); // -2 // Converts non-numbers alert( +true ); // 1 alert( +"" ); // 0
它实际上与 做同样的事情Number(...),但更短。
经常需要将字符串转换为数字。例如,如果我们从 HTML 表单字段中获取值,它们通常是字符串。如果我们想对它们求和怎么办?
二进制加号会将它们添加为字符串:
let apples = "2"; let oranges = "3"; alert( apples + oranges ); // "23", the binary plus concatenates strings
如果我们想把它们当作数字来处理,我们需要对它们进行转换然后求和:
let apples = "2"; let oranges = "3"; // both values converted to numbers before the binary plus alert( +apples + +oranges ); // 5 // the longer variant // alert( Number(apples) + Number(oranges) ); // 5
从数学家的角度来看,大量的加号似乎很奇怪。但是从程序员的角度来看,没有什么特别的:首先应用一元加号,它们将字符串转换为数字,然后二进制加号将它们相加。
为什么一元加号应用于二进制加号之前的值?正如我们将要看到的,这是因为它们具有更高的优先级。
请注意
赋值=也是一个运算符。它以非常低的优先级列在优先级表中3。
这就是为什么,当我们分配一个变量时,例如x = 2 * 2 + 1,首先完成计算,然后=计算 ,并将结果存储在 中x。
let x = 2 * 2 + 1; alert( x ); // 5
赋值 = 返回一个值
=作为一个操作符,而不是一个“神奇”的语言结构的事实有一个有趣的含义。
JavaScript 中的所有运算符都返回一个值。这对于+and很明显-,但对于 也是如此=。
该调用x = value将 写入value到x 然后返回它。
这是一个使用赋值作为更复杂表达式的一部分的演示:
let a = 1; let b = 2; let c = 3 - (a = b + 1); alert( a ); // 3 alert( c ); // 0
在上面的示例中,表达式的结果(a = b + 1)是分配给的值a(即3)。然后将其用于进一步评估。
有趣的代码,不是吗?我们应该了解它是如何工作的,因为有时我们会在 JavaScript 库中看到它。
虽然,请不要写那样的代码。这样的技巧绝对不会使代码更清晰或可读。
链式分配
另一个有趣的功能是链接分配的能力:
let a, b, c; a = b = c = 2 + 2; alert( a ); // 4 alert( b ); // 4 alert( c ); // 4
链式赋值从右到左求值。首先,计算最右边的表达式2 + 2,然后将其分配给左边的变量:c、b和a。最后,所有变量共享一个值。
再一次,为了可读性,最好将这些代码分成几行:
c = 2 + 2; b = c; a = c;
这更容易阅读,尤其是在快速浏览代码时。
就地修改
我们经常需要将运算符应用于变量并将新结果存储在同一变量中。
例如:
let n = 2; n = n + 5; n = n * 2;
可以使用运算符+=和来缩短此表示法*=:
let n = 2; n += 5; // now n = 7 (same as n = n + 5) n *= 2; // now n = 14 (same as n = n * 2) alert( n ); // 14
短“修改和指派”为所有算术和按位运算符存在运营商:/=,-=等等。
此类运算符与普通赋值具有相同的优先级,因此它们在大多数其他计算之后运行:
let n = 2; n *= 3 + 5; alert( n ); // 16 (right part evaluated first, same as n *= 8)
递增/递减
将数字加一或减一是最常见的数值运算之一。
因此,它有特殊的运算符:
Increment ++将变量增加 1:
let counter = 2; counter++; // works the same as counter = counter + 1, but is shorter alert( counter ); // 3 Decrement --将变量减1: let counter = 2; counter--; // works the same as counter = counter - 1, but is shorter alert( counter ); // 1
重要提示:递增/递减只能应用于变量。尝试在类似的值上使用它5++会产生错误。
运算符++and--可以放在变量之前或之后。
1、当操作符跟踪变量时,它是“后缀形式”:counter++。
2、“前缀形式”是当运算符位于变量之前时:++counter。
这两个语句做同样的事情:增加counter的1。
有什么区别吗?是的,但是我们只有使用 的返回值才能看到它++/--。
让我们澄清一下。众所周知,所有运算符都返回一个值。递增/递减也不例外。前缀形式返回新值,而后缀形式返回旧值(在递增/递减之前)。
要查看差异,这里有一个示例:
let counter = 1; let a = ++counter; // (*) alert(a); // 2
在行中(*),前缀形式++counter递增counter并返回新值2。所以,alert节目2。
现在,让我们使用后缀形式:
let counter = 1; let a = counter++; // (*) changed ++counter to counter++ alert(a); // 1
在行中(*),后缀形式counter++也会递增,counter但返回旧值(递增之前)。所以,alert节目1。
总结一下:
1、如果不使用递增/递减的结果,则使用哪种形式没有区别:
let counter = 0; counter++; ++counter; alert( counter ); // 2, the lines above did the same
2、如果我们想增加一个值并立即使用运算符的结果,我们需要前缀形式:
let counter = 0; alert( ++counter ); // 1
3、如果我们想增加一个值但使用它以前的值,我们需要后缀形式:
let counter = 0; alert( counter++ ); // 0
其他运算符之间的递增/递减
运算符++/--也可以在表达式中使用。它们的优先级高于大多数其他算术运算。
例如:
let counter = 1; alert( 2 * ++counter ); // 4 与之比较: let counter = 1; alert( 2 * counter++ ); // 2, because counter++ returns the "old" value
虽然技术上没问题,但这种符号通常会使代码可读性降低。一条线做多件事——不好。
在阅读代码时,快速的“垂直”眼睛扫描很容易错过类似的东西counter++,并且变量增加不会很明显。
我们建议采用“一行 - 一个动作”的风格:
let counter = 1; alert( 2 * counter ); counter++;
按位运算符
按位运算符将参数视为 32 位整数,并在其二进制表示级别上工作。
这些运算符不是 JavaScript 特定的。大多数编程语言都支持它们。
按位运算符有:
1、与 ( &)
2、或 ( |)
3、异或 ( ^)
4、不是 ( ~)
5、左移 ( <<)
6、右移 ( >>)
7、零填充右移 ( >>>)
当我们需要在最低(按位)级别处理数字时,很少使用这些运算符。我们很快就不需要这些操作符,因为 Web 开发很少使用它们,但是在某些特殊领域,例如密码学,它们很有用。需要时,您可以阅读MDN 上的按位运算符一章。
逗号
逗号运算符,是最罕见和最不寻常的运算符之一。有时,它用于编写较短的代码,因此我们需要了解它以了解发生了什么。
逗号运算符允许我们评估多个表达式,并用逗号分隔它们,。它们中的每一个都被评估,但只返回最后一个的结果。
例如:
let a = (1 + 2, 3 + 4); alert( a ); // 7 (the result of 3 + 4)
在这里,计算第一个表达式1 + 2并丢弃其结果。然后,3 + 4被评估并作为结果返回。
逗号的优先级很低
1、请注意,逗号运算符的优先级非常低,低于=,因此在上面的示例中括号很重要。
2、没有它们:首先a = 1 + 2, 3 + 4计算+,将数字相加到a = 3, 7,然后赋值运算符=分配a = 3,其余的被忽略。就像(a = 1 + 2), 3 + 4.
为什么我们需要一个可以丢弃除最后一个表达式之外的所有内容的运算符?
有时,人们在更复杂的结构中使用它来将多个动作放在一行中。
例如:
// three operations in one line for (a = 1, b = 3, c = a * b; a < 10; a++) { ... }
许多 JavaScript 框架都使用了这种技巧。这就是我们提到它们的原因。但通常它们不会提高代码的可读性,所以我们在使用它们之前应该好好考虑一下。