阿喵的 TypeScript 教程・第三章 - 基本语法

254 阅读6分钟

运算符

前言(阿喵的话)

运算是程序之本。如果你想成为一名优秀的程序猿,熟练的掌握(精通)程序的运算过程,是必修课!

算数运算符

设: a = 5,b 为运算结果

运算符描述例子a 运算结果b 运算结果
+加法b = a + 156
-减法b = a - 154
*乘法b = a * 2510
/除法b = a / 252.5
%取余b = a % 550
++自增b = ++a66
b = a++65
--自减b = --a44
b = a--45

运算误差问题

0.1 + 0.2; // 0.30000000000000004
0.1 + 0.7; // 0.7999999999999999

0.3 - 0.2; // 0.09999999999999998
1.5 - 1.2; // 0.30000000000000004

0.8 * 3; // 2.4000000000000004
19.9 * 100; // 1989.9999999999998

0.3 / 0.1; // 2.9999999999999996
0.69 / 10; // 0.06899999999999999

Javascript 的浮点数采用的是 IEEE 754 二进制浮点数算术标准,以 0.1 + 0.2 为例,其计算步骤为:

  1. 0.1 + 0.2 计算时,会先转换为 二进制,但由于浮点数用二进制表示是 无穷,即:
0.1 ===> 0.0001 1001 1001 1001 ...(1001循环)
0.2 ===> 0.0011 0011 0011 0011 ...(0011循环)
  1. IEEE 754 标注下的 64 位 双精度浮点数 的 小数部分至多支持 53 位二进制,多余的部分会被截断,所以两者相加后的和是:
0.0100110011001100110011001100110011001100110011001101

双精度浮点数 的 小数部分至多支持 53 位二进制,多余的二进制数字被截断,所以两者相加之后的二进制之和是

  1. 再将截取的 二进制 转换为 十进制,所以结果为 0.30000000000000004,就与预期产生了误差

小技巧一:转换数字类型

+"100"; // 100
+"-100"; // 100

小技巧二:转换字符串类型

100 + ""; // '100'

解决方案

建议使用 mathjsdecimal.js 等 依赖库

关系运算符

设: a = 5

运算符描述比较返回值
==等于a == 8false
a == 5true
!=不等于a != 8true
>大于a > 8false
<小于a < 8true
>=大于或等于a >= 8false
<=小于或等于a <= 8true

=====

let a = new Number(1);
let b = 1;

a == b; // true
a === b; // false

=== “严格比较运算符” (Strict Equality Operator) 会认为 不同类型(的数据) 是不同的

let a = new Number(1);
let b = 1;

console.log(a); // 1
console.log(b); // 1

typeof a; // object
typeof b; // number

逻辑运算符

设: a = 5, b = 10

运算符描述详细说明例子返回值
&&与 and运算符两侧条件均成立,返回 true(a < 10 && b > 8)true
||或 or运算符两侧有一侧条件成立,返回 true(a == 5 || b == 5 )true
!非 not条件不成立,返回 truea != 8true

| 运算符

3 | 4; // 7
4 | 4; // 4
8 | 3; // 11
5.3 | 4.1; // 5
9 | 3455; // 3455

| 运算符会将参与运算的数转换为 二进制,继而相加,再转换回 十进制 得到结果

3 | 4; // 011 + 100 = 111 => 7
8 | 3; // 1000 + 011 = 1011 => 11

小技巧:取整

3.1415926 | 0; // 3
-3.1415926 | 0; // -3

位运算符

上述文中 | 运算符,属于一种 位运算符,其他位运算符还有:

  • &: 与 and,按位与处理两个长度相同的二进制数,两个相应的二进位都为 1,该位的结果值才为 1,否则为 0
  • |: 或 or,按位或处理两个长度相同的二进制数,两个相应的二进位中只要有一个为 1,该位的结果值为 1
  • ~: 取反,取反是一元运算符,对一个二进制数的每一位执行逻辑反操作。使数字 1 成为 0,0 成为 1
  • ^: 异或,按位异或运算,对等长二进制模式按位或二进制数的每一位执行逻辑异按位或操作。操作的结果是如果某位不同则该位为 1,否则该位为 0
  • <<: 左移,把 << 左边的运算数的各二进位全部左移若干位,由 << 右边的数指定移动的位数,高位丢弃,低位补 0
  • >>: 右移,把 >> 左边的运算数的各二进位全部右移若干位,>> 右边的数指定移动的位数
  • >>>: 无符号右移,与有符号右移位类似,除了左边一律使用 0 补位
运算符例子二进制计算过程二进制结果十进制
&x = 5 & 10101 & 000100011
|x = 5 | 10101 | 000101015
~x = ~50101 & 00010001-6
x = 5 ^ 10101 ^ 000101004
<<x = 5 << 10101 << 1101010
>>x = 5 >> 10101 >> 100102
>>>x = 2 >>> 10010 >>> 100011

小技巧:下标取反

!~"".indexOf(); // true

赋值运算

设: a = 5, b = 10

运算符描述实例返回值
=赋值a = b10
+=自加a += b15
-=自减a-= b-5
*=自乘a *= b50
/=自除a /= b0.2
%=自取余b %= a0
<<=自左移a <<= 110
>>=自右移a >>= 12

此外,类似的 赋值运算 还有 >>>=&=|=^=

小技巧:

  • a++ 等同于 a += 1
  • a-- 等同于 a -= 1
  • a ** 2 等同于 a * a 等同于 Math.pow(a, 2)
  • a ** 3 等同于 a * a * a 等同于 Math.pow(a, 3)

三元运算符

条件语句 ? exprA : exprB

条件语句 返回 true,则执行 exprA,否则执行 exprB

let a: number = 5;
let s = a > 10 ? "Jordan" : "Bryant";

嵌套使用

let a: number = 5;
let b: number = 10;

let s = a > 10 ? "Jordan" : b < 5 ? "Bryand" : "James";

小技巧:复杂嵌套时的代码可读性

在多层三元嵌套使用时,为了增加代码可读性,我们可以选择将 从属三元表达式 所在的代码块,用 () 包裹

let s = a > 10 ? "Jordan" : (b < 5 ? "Bryand" : "James");

条件语句

依据不同的条件,以执行不同的代码

if 判断

下述示例中:当 a < 10 条件成立时,则执行 a++

let a: number = 5;

if (a < 10) {
  a++;
}

if ... else 语句

下述示例中:当 a < 10 条件成立时,执行 a++,否则执行 a--

let a: number = 5;

if (a < 10) {
  a++;
} else {
  a--;
}

if ... else if ... else 多条件判断

下属示例中:当 a < 10 时,执行 a++;当 a == 5 时,执行 console.log(a);否则,执行 a--

let a: number = 5;

if (a < 10) {
  a++;
} else if (a == 5) {
  console.log(a);
} else {
  a--;
}

switch ... case 语句

当存在多条件时,可以选择采用 switch ... case 语句进行判断

let a: number = 'Jordan';

swtch(a) {
  case 'Bryand':
    console.log('Kobe ', a);
    break;
  case 'Jordan':
    console.log('Michael ', a);
    break;
  case 'Iverson':
    console.log('Allen ', a);
    break;
  default:
    console.log('My name is ', a);
}

小贴士:

  1. 在一个 switch 语句中,可以添加任意数量的 case 语句。每个 case 后需跟一个要进行比较的值(数据类型也必须相同)
  2. 当遇到 break 语句时,switch 即刻终止
  3. 每个 switch 语句都可以有一个(可选)default,出现在结尾处。当所有 case 都匹配不为真时,就会执行 default 下的代码

循环

本节示例中,会使用下属用例数据

// 数组
const A = ["a", "b", "c"];

// 对象
const S = { a: 1, b: 2, c: 3 };

for 循环

for (let i = 0; i < A.length; i++) {
  console.log(i);
}

语法格式:

for (初始化; 执行条件; 递差语句;) {
  # 循环体
}

for 语句一般情况下,需要设置 3 个条件,以控制流程:

  1. 初始化: 会被优先执行,且仅执行一次。此时,允许你声明并初始化控制循环的变量
  2. 执行条件: 接下来,在每次循环之初,均会优先判断 执行条件。如果条件为 true,则执行 循环体 中的代码;如果为 fales,则即可终止循环
  3. 递差语句: 在单次 循环 执行完成后,会执行 地差语句递差语句 可以为 递增,亦可为 递减,或其他计算公式;

for ... infor ... of

获取数组 下标

for (let index in A) {
  console.log(index); // 0, 1, 2
}

获取对象的

for (let key in S) {
  console.log(key); // a, b, c
}

获取数组的

for (let value of A) {
  console.log(value); // a, b, c
}

forEachmap

使用 forEach 对数组进行循环操作

A.forEach((value, index, array) => {
  console.log(index, value, array); // 下标, 值, 原始数组(便于对其进行修改)
});

mapforEach 的区别

  • forEach 的回调函数中 不接受返回值
  • map 的回调函数中,可以接受一个返回值,作为数组对应下标的新值,且不会改变原始数组
A.map((value, index) => {
  return value + index;
}); // a0, b1, c2

everysome 循环

every 的回调函数中,如果 return 一个 true,则表示循环终止

A.every(value => {
  if (value == "b") {
    return true;
  }
});

someevery 恰恰相反,当它的回调函数中 return 一个 false 时,表示循环终止

A.some(value => {
  if (value == "b") {
    return false;
  }
});

whiledo ... while

闲话少叙,上案例

let a: number = 5;

while (a > 0) {
  a--;
}
let a: number = 5;

do {
  a--;
} while (a > 0);

上述 2 个 案例的执行过程与结果完全相同

breakcontinue

breakcontinue 语句可以在 forwhile 中使用,包括 for ... infor ... of 以及 do ... while

  • break 意为 跳出循环(或 终止循环)
  • continue 意为 跳过当前循环体(或 跳过本次循环),开始下次循环

breakfor 中的使用

for (let i = 0; i < A.length; i++) {
  if (i == 2) {
    break;
  }
}

breakwhile 中的使用

let a: number = 5;

while (a > 0) {
  if (a == 3) {
    break;
  }
  a--;
}

continuefor 中的使用

let count: number = 0;

for (let i = 0; i <= A.length; i++) {
  if (i % 2 == 0) {
    continue;
  }
  count++;
}

continuewhile 中的使用

let a: number = 5;
let count: number = 0;

while (a >= 0) {
  a--;
  if (a % 2 == 0) {
    continue;
  }
  count++;
}

无限循环

无限循环 即 未设置 或 无法触达终止条件 的循环,也被称为 死循环

for (;;) {}
while (true) {}