JavaScript高级程序设计学习笔记【第三章 语言基础(二)】


在这里插入图片描述

3.5 操作符

ECMA-262 描述了一组可用于操作数据值的操作符,包括数学操作符(如加、减)、位操作符、关系操作符和相等操作符等。

3.5.1 一元操作符

只操作一个值的操作符叫一元操作符(unary operator)。一元操作符是 ECMAScript中最简单的操作符。

  1. 递增/递减操作符
    递增和递减操作符直接照搬自 C 语言,但有两个版本:前缀版和后缀版。顾名思义,前缀版就是位于要操作的变量前头,后缀版就是位于要操作的变量后头。前缀递增操作符会给数值加 1,把两个加号(++)放到变量前头即可:
let age = 29; 
++age; 

在这个例子中,前缀递增操作符把 age 的值变成了 30(给之前的值 29 加 1)。因此,它实际上等于
如下表达式:

let age = 29; 
age = age + 1; 

前缀递减操作符也类似,只不过是从一个数值减 1。使用前缀递减操作符,只要把两个减号(–)放到变量前头。
2. 一元加和减
一元加和减操作符对大多数开发者来说并不陌生,它们在 ECMAScript 中跟在高中数学中的用途一样。一元加由一个加号(+)表示,放在变量前头,对数值没有任何影响:

let num = 25; 
num = +num; 
console.log(num); // 25 

如果将一元加应用到非数值,则会执行与使用 Number()转型函数一样的类型转换:布尔值 false
和 true 转换为 0 和 1,字符串根据特殊规则进行解析,对象会调用它们的 valueOf()和/或toString()方法以得到可以转换的值。

3.5.2 位操作符

接下来要介绍的操作符用于数值的底层操作,也就是操作内存中表示数据的比特(位)。ECMAScript中的所有数值都以 IEEE 754 64 位格式存储,但位操作并不直接应用到 64 位表示,而是先把值转换为32 位整数,再进行位操作,之后再把结果转换为 64 位。
有符号整数使用 32 位的前 31 位表示整数值。第 32 位表示数值的符号,如 0 表示正,1 表示负。这一位称为符号位(sign bit),它的值决定了数值其余部分的格式。正值以真正的二进制格式存储,即 31位中的每一位都代表 2 的幂。第一位(称为第 0 位)表示 20,第二位表示 21,依此类推。
负值以一种称为二补数(或补码)的二进制编码存储。一个数值的二补数通过如下 3 个步骤计算
得到:
(1) 确定绝对值的二进制表示(如,对于18,先确定 18 的二进制表示);
(2) 找到数值的一补数(或反码),换句话说,就是每个 0 都变成 1,每个 1 都变成 0;
(3) 给结果加 1。

  1. 按位非
    按位非操作符用波浪符(~)表示,它的作用是返回数值的一补数。按位非是 ECMAScript 中为数不多的几个二进制数学操作符之一。看下面的例子:
let num1 = 25; // 二进制 00000000000000000000000000011001 
let num2 = ~num1; // 二进制 11111111111111111111111111100110 
console.log(num2); // -26 

这里,按位非操作符作用到了数值 25,得到的结果是26。由此可以看出,按位非的最终效果是对数值取反并减 1,
2. 按位与
按位与操作符用和号(&)表示,有两个操作数。本质上,按位与就是将两个数的每一个位对齐,然后基于真值表中的规则,对每一位执行相应的与操作。
在这里插入图片描述
按位与操作在两个位都是 1 时返回 1,在任何一位是 0 时返回 0。
下面看一个例子,我们对数值 25 和 3 求与操作,如下所示:

let result = 25 & 3; 
console.log(result); // 1 

25 和 3 的按位与操作的结果是 1。为什么呢?看下面的二进制计算过程:

 25 = 0000 0000 0000 0000 0000 0000 0001 1001 
 3 = 0000 0000 0000 0000 0000 0000 0000 0011 
AND = 0000 0000 0000 0000 0000 0000 0000 0001 

如上所示,25 和 3 的二进制表示中,只有第 0 位上的两个数都是 1。于是结果数值的所有其他位都会以 0 填充,因此结果就是 1。
3. 按位或
按位或操作符用管道符(|)表示,同样有两个操作数。按位或遵循如下真值表:
在这里插入图片描述

按位或操作在至少一位是 1 时返回 1,两位都是 0 时返回 0。
仍然用按位与的示例,如果对 25 和 3 执行按位或,代码如下所示:

let result = 25 | 3; 
console.log(result); // 27 

可见 25 和 3 的按位或操作的结果是 27:

 25 = 0000 0000 0000 0000 0000 0000 0001 1001 
 3 = 0000 0000 0000 0000 0000 0000 0000 0011 
 OR = 0000 0000 0000 0000 0000 0000 0001 1011 

在参与计算的两个数中,有 4 位都是 1,因此它们直接对应到结果上。二进制码 11011 等于 27。
4. 按位异或
按位异或用脱字符(^)表示,同样有两个操作数。下面是按位异或的真值表:
在这里插入图片描述
按位异或与按位或的区别是,它只在一位上是 1 的时候返回 1(两位都是 1 或 0,则返回 0)。
对数值 25 和 3 执行按位异或操作:

let result = 25 ^ 3; 
console.log(result); // 26 

可见,25 和 3 的按位异或操作结果为 26,如下所示:

 25 = 0000 0000 0000 0000 0000 0000 0001 1001 
 3 = 0000 0000 0000 0000 0000 0000 0000 0011 
XOR = 0000 0000 0000 0000 0000 0000 0001 1010 

两个数在 4 位上都是 1,但两个数的第 0 位都是 1,因此那一位在结果中就变成了 0。其余位上的 1在另一个数上没有对应的 1,因此会直接传递到结果中。二进制码 11010 等于 26。
5. 左移
左移操作符用两个小于号(<<)表示,会按照指定的位数将数值的所有位向左移动。比如,如果数值 2(二进制 10)向左移 5 位,就会得到 64(二进制 1000000),如下所示:

let oldValue = 2; // 等于二进制 10 
let newValue = oldValue << 5; // 等于二进制 1000000,即十进制 64
  1. 有符号右移
    有符号右移由两个大于号(>>)表示,会将数值的所有 32 位都向右移,同时保留符号(正或负)。
    有符号右移实际上是左移的逆运算。比如,如果将 64 右移 5 位,那就是 2:
let oldValue = 64; // 等于二进制 1000000 
let newValue = oldValue >> 5; // 等于二进制 10,即十进制 2 

同样,移位后就会出现空位。不过,右移后空位会出现在左侧,且在符号位之后。
7. 无符号右移
无符号右移用 3 个大于号表示(>>>),会将数值的所有 32 位都向右移。对于正数,无符号右移与有符号右移结果相同。仍然以前面有符号右移的例子为例,64 向右移动 5 位,会变成 2:

let oldValue = 64; // 等于二进制 1000000 
let newValue = oldValue >>> 5; // 等于二进制 10,即十进制 2 

对于负数,有时候差异会非常大。与有符号右移不同,无符号右移会给空位补 0,而不管符号位是什么。对正数来说,这跟有符号右移效果相同。但对负数来说,结果就差太多了。无符号右移操作符将负数的二进制表示当成正数的二进制表示来处理。因为负数是其绝对值的二补数,所以右移之后结果变得非常之大,如下面的例子所示:

let oldValue = -64; // 等于二进制 11111111111111111111111111000000 
let newValue = oldValue >>> 5; // 等于十进制 134217726

3.5.3 布尔操作符

对于编程语言来说,布尔操作符跟相等操作符几乎同样重要。如果没有能力测试两个值的关系,那么像 if-else 和循环这样的语句也没什么用了。布尔操作符一共有 3 个:逻辑非、逻辑与和逻辑或。

  • 逻辑非
    逻辑非操作符由一个叹号(!)表示,可应用给 ECMAScript 中的任何值。这个操作符始终返回布
    尔值,无论应用到的是什么数据类型。逻辑非操作符首先将操作数转换为布尔值,然后再对其取反。逻辑非操作符会遵循如下规则。
  • 如果操作数是对象,则返回 false。
  • 如果操作数是空字符串,则返回 true。
  • 如果操作数是非空字符串,则返回 false。
  • 如果操作数是数值 0,则返回 true。
  • 如果操作数是非 0 数值(包括 Infinity),则返回 false。
  • 如果操作数是 null,则返回 true。
  • 如果操作数是 NaN,则返回 true。
  • 如果操作数是 undefined,则返回 true。
  1. 逻辑与
    逻辑与操作符由两个和号(&&)表示,应用到两个值,如下所示:
let result = true && false;
  1. 逻辑或
    逻辑或操作符由两个管道符(||)表示,比如:
let result = true || false; 

逻辑或操作符遵循如下真值表:
在这里插入图片描述

3.5.4 乘性操作符

ECMAScript 定义了 3 个乘性操作符:乘法、除法和取模。

  1. 乘法操作符
    乘法操作符由一个星号(*)表示,可以用于计算两个数值的乘积。其语法类似于 C 语言,比如:
let result = 34 * 56;
  1. 除法操作符
    除法操作符由一个斜杠(/)表示,用于计算第一个操作数除以第二个操作数的商,比如:
let result = 66 / 11;
  1. 取模操作符
    取模(余数)操作符由一个百分比符号(%)表示,比如:
let result = 26 % 5; // 等于 1

3.5.5 指数操作符

ECMAScript 7 新增了指数操作符,Math.pow()现在有了自己的操作符**,结果是一样的:

console.log(Math.pow(3, 2); // 9 
console.log(3 ** 2); // 9 
console.log(Math.pow(16, 0.5); // 4 
console.log(16** 0.5); // 4 

不仅如此,指数操作符也有自己的指数赋值操作符**=,该操作符执行指数运算和结果的赋值操作:

let squared = 3; 
squared **= 2; 
console.log(squared); // 9
let sqrt = 16; 
sqrt **= 0.5; 
console.log(sqrt); // 4

3.5.6 加性操作符

加性操作符,即加法和减法操作符。

  1. 加法操作符
    加法操作符(+)用于求两个数的和,比如:
let result = 1 + 2;
  1. 减法操作符
    减法操作符(-)也是使用很频繁的一种操作符,比如:
let result = 2 - 1;

3.5.7 关系操作符

关系操作符执行比较两个值的操作,包括小于(<)、大于(>)、小于等于(<=)和大于等于(>=),用法跟数学课上学的一样。这几个操作符都返回布尔值,如下所示:

let result1 = 5 > 3; // true 
let result2 = 5 < 3; // false

3.5.8 相等操作符

判断两个变量是否相等是编程中最重要的操作之一。在比较字符串、数值和布尔值是否相等时,过程都很直观。但是在比较两个对象是否相等时,情形就比较复杂了。
ECMAScript提供了两组操作符。第一组是等于和不等于,它们在比较之前执行转换。第二组是全等和不全等,它们在比较之前不执行转换。

  1. 等于和不等于
    ECMAScript 中的等于操作符用两个等于号(==)表示,如果操作数相等,则会返回 true。不等于操作符用叹号和等于号(!=)表示,如果两个操作数不相等,则会返回 true。这两个操作符都会先进行类型转换(通常称为强制类型转换)再确定操作数是否相等。
  2. 全等和不全等
    全等和不全等操作符与相等和不相等操作符类似,只不过它们在比较相等时不转换操作数。全等操作符由 3 个等于号(===)表示,只有两个操作数在不转换的前提下相等才返回 true,比如:
let result1 = ("55" == 55); // true,转换后相等
let result2 = ("55" === 55); // false,不相等,因为数据类型不同

3.5.9 条件操作符

条件操作符是 ECMAScript 中用途最为广泛的操作符之一,比如

let max = (num1 > num2) ? num1 : num2; 

在这个例子中,max 将被赋予一个最大值。这个表达式的意思是,如果 num1 大于 num2(条件表达式为 true),则将 num1 赋给 max。否则,将 num2 赋给 max。

3.5.10 赋值操作符

简单赋值用等于号(=)表示,将右手边的值赋给左手边的变量,如下所示:

let num = 10; 

复合赋值使用乘性、加性或位操作符后跟等于号(=)表示。

3.5.11 逗号操作符

逗号操作符可以用来在一条语句中执行多个操作,如下所示:

let num1 = 1, num2 = 2, num3 = 3; 

在一条语句中同时声明多个变量是逗号操作符最常用的场景。不过,也可以使用逗号操作符来辅助赋值。在赋值时使用逗号操作符分隔值,最终会返回表达式中最后一个值:

let num = (5, 1, 4, 8, 0); // num 的值为 0 

在这个例子中,num 将被赋值为 0,因为 0 是表达式中最后一项。

3.6 语句

ECMA-262 描述了一些语句(也称为流控制语句),而 ECMAScript 中的大部分语法都体现在语句中。

3.6.1 if 语句

if 语句是使用最频繁的语句之一,语法如下:

if (condition) statement1 else statement2 

这里的条件(condition)可以是任何表达式,并且求值结果不一定是布尔值。

3.6.2 do-while 语句

do-while 语句是一种后测试循环语句,即循环体中的代码执行后才会对退出条件进行求值。换句
话说,循环体内的代码至少执行一次。do-while 的语法如下:

do { 
 statement 
} while (expression); 
下面是一个例子:
let i = 0; 
do { 
 i += 2; 
} while (i < 10); 

在这个例子中,只要 i 小于 10,循环就会重复执行。i 从 0 开始,每次循环递增 2。

3.6.3 while 语句

while 语句是一种先测试循环语句,即先检测退出条件,再执行循环体内的代码。因此,while 循
环体内的代码有可能不会执行。下面是 while 循环的语法:
while(expression) statement
这是一个例子:

let i = 0; 
while (i < 10) { 
 i += 2; 
} 

在这个例子中,变量 i 从 0 开始,每次循环递增 2。只要 i 小于 10,循环就会继续。

3.6.4 for 语句

for 语句也是先测试语句,只不过增加了进入循环之前的初始化代码,以及循环执行后要执行的表
达式,语法如下:

for (initialization; expression; post-loop-expression) statement

3.6.5 for-in 语句

for-in 语句是一种严格的迭代语句,用于枚举对象中的非符号键属性,语法如下:
for (property in expression) statement
下面是一个例子:

for (const propName in window) { 
 document.write(propName); 
} 

这个例子使用 for-in 循环显示了 BOM 对象 window 的所有属性。每次执行循环,都会给变量
propName 赋予一个 window 对象的属性作为值,直到 window 的所有属性都被枚举一遍。

3.6.6 for-of 语句

for-of 语句是一种严格的迭代语句,用于遍历可迭代对象的元素,语法如下:
for (property of expression) statement
下面是示例:

for (const el of [2,4,6,8]) { 
 document.write(el); 
} 

在这个例子中,我们使用 for-of 语句显示了一个包含 4 个元素的数组中的所有元素。循环会一直
持续到将所有元素都迭代完。

3.6.7 break 和 continue 语句

break 和 continue 语句为执行循环代码提供了更严格的控制手段。其中,break 语句用于立即退
出循环,强制执行循环后的下一条语句。而 continue 语句也用于立即退出循环,但会再次从循环顶部
开始执行。下面看一个例子:

let num = 0; 
for (let i = 1; i < 10; i++) { 
 if (i % 5 == 0) { 
 break; 
 } 
 num++; 
} 
console.log(num); // 4 

在上面的代码中,for 循环会将变量 i 由 1 递增到 10。而在循环体内,有一个 if 语句用于检查 i
能否被 5 整除(使用取模操作符)。如果是,则执行 break 语句,退出循环。变量 num 的初始值为 0,表示循环在退出前执行了多少次。

3.6.8 with 语句

with 语句的用途是将代码作用域设置为特定的对象,其语法是:

with (expression) statement; 

使用 with 语句的主要场景是针对一个对象反复操作,这时候将代码作用域设置为该对象能提供便
利,如下面的例子所示:

with(location) { 
 let qs = search.substring(1); 
 let hostName = hostname; 
 let url = href; 
} 

这里,with 语句用于连接 location 对象。

3.6.9 switch 语句

switch 语句是与 if 语句紧密相关的一种流控制语句,从其他语言借鉴而来。ECMAScript中 switch语句跟 C 语言中 switch 语句的语法非常相似。


3.7 小结

JavaScript 的核心语言特性在 ECMA-262 中以伪语言 ECMAScript 的形式来定义。ECMAScript 包含所有基本语法、操作符、数据类型和对象,能完成基本的计算任务,但没有提供获得输入和产生输出的机制。理解 ECMAScript 及其复杂的细节是完全理解浏览器中 JavaScript 的关键。下面总结一下ECMAScript 中的基本元素。

  1. ECMAScript 中的基本数据类型包括 Undefined、Null、Boolean、Number、String 和 Symbol。
  2. 与其他语言不同,ECMAScript 不区分整数和浮点值,只有 Number 一种数值数据类型。
  3. Object 是一种复杂数据类型,它是这门语言中所有对象的基类。
  4. 严格模式为这门语言中某些容易出错的部分施加了限制。
  5. ECMAScript 提供了 C 语言和类 C 语言中常见的很多基本操作符,包括数学操作符、布尔操作符、关系操作符、相等操作符和赋值操作符等。
  6. 这门语言中的流控制语句大多是从其他语言中借鉴而来的,比如 if 语句、for 语句和 switch
    语句等。ECMAScript 中的函数与其他语言中的函数不一样。
  7. 不需要指定函数的返回值,因为任何函数可以在任何时候返回任何值。
  8. 不指定返回值的函数实际上会返回特殊值 undefined。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值