2.6 运算符

运算符定义了将在数据上执行的某些功能。例如,在表达式8 +7 = 15中,+和=就是一种运算符(算术运算符)。TypeScript中的主要运算符可归类为:

  •  算术运算符
  •  关系运算符
  •  逻辑运算符
  •  位运算符
  •  赋值运算符
  •  条件运算符
  •  字符串操作符
  •  类型运算符

不同的运算符可以组合使用,但是各类型的运算符的优先级不同:关系运算符的优先级低于算术运算符;关系运算符的优先级高于赋值运算符;单目运算优于双目运算;先算术运算,后移位运算,再按位运算,逻辑运算最后结合。例如,1 << 3 + 2 & 7等价于(1 << (3 + 2)) & 7。

提示

当不同运算符组合在一起的时候,用括号()将先计算的括起来,这样可以提高代码可读性。

2.6.1 算术运算符

算术运算符(arithmetic operators)就是用来处理四则运算的符号,是最简单、最常用的符号。尤其是数字的处理,几乎都会使用到算术运算符号。

提示

自增和自减运算符只能用于操作变量,不能直接用于操作数值或常量!例如,5++和8--等写法都是错误的。

另外需要注意的是a++和++a的异同点,它们的相同点都是给变量a加1,不同点是a++是先参与程序的运行再加1,而++a则是先加1再参与程序的运行。因此,如果a=8,那么console.log(a++)会打印出8,而console.log(++a)会打印出9,但最后a的值都为9。

表2.1给出了TypeScript中算术运算符的具体说明和示例。

表2.1 算术运算符说明

2.6.2 关系运算符

关系运算符用于确定两个实体对象之间的关系类型,有小于、小于等于、大于、等于、大于等于和不等于6种。关系运算符返回一个boolean值,即true或者false。TypeScript中关系运算符的具体说明和示例如表2.2所示。

表2.2 关系运算符说明

2.6.3 逻辑运算符

逻辑运算符用于组合两个或多个条件。逻辑运算符也返回一个boolean值。逻辑运算符一般和关系运算符配合使用,多用于if条件判断和循环中断条件等场景。TypeScript中逻辑运算符的具体说明和示例如表2.3所示。

表2.3 逻辑运算符说明

2.6.4 按位运算符

按位运算符用来对二进制位进行操作。位运算符一般用于数值,在具体运算时要先将十进制转成二进制后再计算。TypeScript中按位运算符的具体说明和示例如表2.4所示。

表2.4 按位运算符说明

2.6.5 赋值运算符

基本的赋值运算符是=。它的优先级别低于其他的运算符,所以对该运算符往往最后读取。TypeScript中赋值运算符的具体说明和示例如表2.5所示。

表2.5 赋值运算符说明

2.6.6 等号运算符

等号运算符===和==都可以用于判断两个对象是否相等,但是具体细节上不同。 ==在比较的时候会进行自动数据类型转换。而===是严格比较,不会进行自动转换,要求进行比较的操作数必须类型和值一致,不一致时返回false,如代码2-60所示。

【代码2-60】等号运算符示例:equal_opt.ts

    01  let a: number = 1;
    02  let b :any = "1";
    03  console.log(a == b);     //true
    04  console.log(a === b);    //false

2.6.7 否定运算符(-)

否定运算符-可以更改值的符号。举一个例子:5应用否定运算符为-5 。否定运算符的基本用法如代码2-61所示。

【代码2-61】否定运算符示例:neg_opt.ts

    01  let a: number = 1;
    02  let b: number = - a;
    03  console.log(b);         // -1

提示

两个连续的否定运算符可以抵消,但不能直接用--5 ,而是用-(-5),结果为5。

2.6.8 连接运算符(+)

连接运算符一般用于字符串拼接。用于字符串时的+运算符将第二个字符串追加到第一个字符串上。连接运算符还可以连接字符和数字、字符和数组以及字符和布尔等。这些不同的连接在结果上也是有差异的。代码2-62给出了连接运算符的相关用法。

【代码2-62】连接运算符示例:join_opt.ts

    01  let a: string = "hello";
    02  let b: string = "world";
    03  let c: string = a + " " + b;
    04  console.log(c);           // hello world
    05  let arr = [1, 2, 3];
    06  console.log("" + arr);    //"1,2,3"
    07  console.log(""+ true);    // "true"
    08  console.log("" + null);   //"null"

提示

连接运算符和算术运算符中的+不同,连接运算符中必须有一个是字符串。5+ "6"是"56";而5+6 =11。

2.6.9 条件运算符(?)

条件运算符用来表示一个条件表达式。条件运算有时也被称为三元运算符,基本语法如下:

    条件表达式 ? 条件表达式为true时的值 : 条件表达式为false时的值

代码2-63给出了条件运算符的基本用法。

【代码2-63】条件运算符示例:condition_opt.ts

    01  let a: number = 10;
    02  let c: string = a>9 ? "大于9" : "小于等于9";
    03  console.log(c);        // 大于9

在代码2-63中,第02行检查变量a中的值是否大于9。如果a设置为大于9的值,就返回字符串“大于9”,否则返回字符串“小于等于9”。由于变量a是10,10>9为true,因此返回第一个字符串“大于9”。

提示

条件运算符可以替换简单的if ... else语句,让代码更加简洁。

2.6.10 类型运算符(typeof)

typeof操作符返回一个字符串,用以获取一个变量或者表达式的类型。typeof运算符一般只能返回如下几个结果:number,boolean,string,symbol,function,object和undefined。表2.6给出常见的类型对象的typeof返回值。

表2.6 常见类型对象的typeof返回值

为了验证结果,用下面的代码2-64来查看不同类型的变量上用typeof输出的结果。

【代码2-64】类型运算符示例:typeof.ts

    01  let a: number = 2;
    02  console.log(typeof a);     //"number"
    03  let b: string = "hello";
    04  console.log(typeof b);     //"string"
    05  let c: boolean = true;
    06  console.log(typeof c);     //"boolean"
    07  let d = null;
    08  console.log(typeof d);     //"object"
    09  console.log(typeof undefinedVar);        //未定义undefined
    10  enum Colors {
    11      Red,
    12      Green,
    13      Yellow
    14  }
    15  let color: Colors = Colors.Red;
    16  console.log(typeof color); //"number"
    17  let f = function () {
    18      console.log("hello world");
    19  };
    20  console.log(typeof f);     //"function"
    21  let g = [];
    22  console.log(typeof g);     //"object"
    23  let m: number[] = [1, 2];
    24  console.log(typeof m);     //"object"

提示

let声明的变量在声明之前不可用typeof来输出操作数的类型。

代码2-65给出一个错误的示范。01行用typeof a查看a变量的类型,但是由于a类型是let声明的,因此不能在声明之前进行调用。03行用typeof b查看变量b的类型,由于b是用var声明的,会进行变量提升,因此输出undefined而没有报错。

【代码2-65】类型运算符示例2:typeof2.ts

    01  console.log(typeof a);    //声明之前不能调用
    02  let a: number = 2;
    03  console.log(typeof b);    //undefined
    04  var b: number = 2;

2.6.11 instanceof运算符

instanceof运算符可用于测试对象是否为指定类型的实例,如果是,那么返回的值为true,否则返回false。instanceof运算符的基本语法为:

    类实例 instanceof 类

下面定义了一个People类,其中有两个私有属性name和age,如代码2-66所示。05行用new People创建了一个类的实例man,06行man instanceof People则返回true。

【代码2-66】 instanceof运算符示例:instanceof.ts

    01  class People {
    02      private name: string = "";
    03      private age: string = "";
    04  }
    05  let man: People = new People ();
    06  alert(man instanceof People );      //true

提示

instanceof左边的只能是any类型或者对象类型或者类型参数(type parameter)。其他不能用,如"hello" instanceof string报错。

2.6.12 展开运算符(...)

展开运算符(spread operator)允许一个表达式在某处展开。展开运算符在多个参数(用于函数调用)或多个元素(用于数组字面量)或者多个变量(用于解构赋值)的地方可以使用。合理使用展开运算符可以使代码更加简洁。展开运算符为“...”。

展开运算符“...”主要有以下应用场景:

(1)函数动态参数

在TypeScript中可以定义add函数,其参数为...args(args是rest剩余参数,后面章节再详细介绍)可以允许传入任意个数的参数。在add函数内部,用for... of循环将传入的参数求和并返回值,如代码2-67所示。

【代码2-67】展开运算符示例:spread_opt1.ts

    01  function add(...args) {
    02      let sum = 0;
    03      for (let item of args) {
    04          sum += item;
    05      }
    06      return sum;
    07  }
    08  let arr = [1, 2, 3, 4];
    09  //let args = add(arr);      //"01,2,3,4"
    10  let args = add(...arr);
    11  console.log(args);          //10

提示

如果调用add(arr),那么返回的结果不是10。

在代码2-67中,在调用函数时先声明了一个数值型数组arr ,将add(...arr)进行传入即可获取数组元素的累加值10。

(2)数组合并

假设有两个数组,那么用展开运算符可以很方便地进行合并。展开运算符对数组进行合并的语法相当简洁,如代码2-68所示。

【代码2-68】展开运算符数组合并示例:spread_opt2.ts

    01  let arr = [1, 2, 3];
    02  let args = [...arr,4,5];
    03  console.log(args);     // [1,2,3,4,5]

(3)复制数组

由于数组是按照引用传递值的,因此要想复制一个数组的副本,不能直接赋值。此时用展开运算符可以很方便地进行数组备份,如代码2-69所示。

【代码2-69】展开运算符复制数组示例:spread_opt3.ts

    01  let arr = [1,2,3];
    02  let arr2 = [...arr];       //和arr.slice()一致
    03  arr2.push(4);
    04  console.log(arr);     //[1,2,3]
    05  console.log(arr2);    //[1,2,3,4]

(4)解构赋值

展开运算符在解构赋值中的作用是将多个数组项组合成一个新数组。不过要注意,解构赋值中展开运算符只能用在末尾,如代码2-70所示。

【代码2-70】展开运算符解构赋值示例:spread_opt4.ts

    01  let [a, b, ...arg3] = [1, 2, 3, 4];
    02  console.log(a);       //1
    03  console.log(b);       //2
    04  console.log(arg3);    //[3,4]

(5)ES7草案中的对象展开运算符

可以将对象当中的一部分属性取出来生成一个新对象赋值给展开运算符的参数。例如,下面代码2-71中的args值就为一个新的对象{b:4,c:3}。

【代码2-71】展开运算符对象解构示例:spread_opt5.ts

    01  let { y, a, ...args} = { a: 1, y: 2, c: 3, b: 4 };
    02  console.log(a);        //1 获取对象a属性
    03  console.log(y);        //2 获取对象y属性
    04  console.log(args);     //{b:4,c:3}