一、表达式与运算符
1.运算符
JavaScript 拥有如下类型的运算符。本节描述了运算符和运算符的优先级。
- 赋值运算符(Assignment operators)
- 比较运算符(Comparison operators)
- 算数运算符(Arithmetic operators)
- 位运算符(Bitwise operators)
- 逻辑运算符(Logical operators)
- 字符串运算符(String operators)
- 条件(三元)运算符(Conditional operator)
- 逗号运算符(Comma operator)
- 一元运算符(Unary operators)
- 关系运算符(Relational operator)
JavaScript 拥有二元和一元运算符, 和一个特殊的三元运算符(条件运算符)。一个二元运算符需要两个操作数,分别在运算符的前面和后面:
操作数1 运算符 操作数2
例如, 3+4 或 x*y。
一个一元运算符需要一个操作数,在运算符前面或后面:
运算符 操作数
或
操作数 运算符
例如, x++ 或 ++x。
注意: 在一般情况下 ++x 和 x++ 两者返回值没有什么区别,当参与运算时:
let x = 1
++x x先自增后参与运算 ++x + 3 = 5
x++ x先参与运算后再自增 x++ + 3 = 4
1.1 赋值运算符
一个 赋值运算符 将它右边操作数的值赋给它左边的操作数。最简单的赋值运算符是等于(=),它将右边的操作数值赋给左边的操作数。那么 x = y 就是将 y 的值赋给 x。
还有一些复合赋值操作符,它们是下表列出的这些操作的缩写:
| 名字 | 简写的操作符 | 含义 |
|---|---|---|
| 赋值 | x = y | x = y |
| 加法赋值 | x += y | x = x + y |
| 减法赋值 | x -= y | x = x - y |
| 乘法赋值 | x *= y | x = x * y |
| 除法赋值 | x /= y | x = x / y |
| 求余赋值 | x %= y | x = x % y |
| 求幂赋值 | x **= y | x = x ** y |
| 左移位赋值 | x <<= y | x = x << y |
| 右移位赋值 | x >>= y | x = x >> y |
| 无符号右移位赋值 | x >>>= y | x = x >>> y |
| 按位与赋值 | x &= y | x = x & y |
| 按位异或赋值 | x ^= y | x = x ^ y |
| 按位或赋值 | x |= y | x = x | y |
解构
对于更复杂的赋值,解构赋值语法是一个能从数组或对象对应的数组结构或对象字面量里提取数据的 Javascript 表达式。
let a, b, rest;
[a, b] = [10, 20];
// expected output: 10
console.log(a);
// expected output: 20
console.log(b);
[a, b, ...rest] = [10, 20, 30, 40, 50];
// expected output: Array [30,40,50]
console.log(rest);
1.2 比较运算符
比较运算符比较它的操作数并返回一个基于表达式是否为真的逻辑值。操作数可以是数字,字符串,逻辑,对象值。
字符串比较,是比较的字符对应的ASCII码
从左往右依次比较
如果第一位一样再比较第二位,以此类推
NaN不等于任何值,包括它本身
尽量不要比较小数,因为小数有精度问题
不同类型之间比较会发生隐式转换
最终把数据隐式转换转成number类型再比较
所以开发中,如果进行准确的比较我们更喜欢 === 或者 !==
| 运算符 | 描述 | 返回true示例 |
|---|---|---|
等于(==) | 如果两边操作数相等时返回true。 | 3 == ‘3’ |
不等于(!=) | 如果两边操作数不相等时返回true | 3 != 4 |
全等 (===) | 两边操作数相等且类型相同时返回true。 参见 Object.is and sameness in JS. | 3 === 3 |
不全等(!==) | 两边操作数不相等或类型不同时返回true。 | 3 !== ‘3’ |
大于(>) | 左边的操作数大于右边的操作数返回true | ‘12’ > 2 |
大于等于(>=) | 左边的操作数大于或等于右边的操作数返回true | 3 >= 3 |
小于 (<) | 左边的操作数小于右边的操作数返回true | ‘2’ < 12 |
小于等于(<=) | 左边的操作数小于或等于右边的操作数返回true | 4 <= 5 |
备注:(=>) 不是运算符,而是箭头函数的标记符号 。
编程中建议使用 ===(全等) 作比较
1.3 算数运算符
算术运算符使用数值(字面量或者变量)作为操作数并返回一个数值.标准的算术运算符就是加减乘除(+ - * /)。当操作数是浮点数时,这些运算符表现得跟它们在大多数编程语言中一样(特殊要注意的是,除零会产生Infinity)。
1.4 位运算符
位运算符将它的操作数视为32位元的二进制串(0和1组成)而非十进制八进制或十六进制数。例如:十进制数字9用二进制表示为1001,位运算符就是在这个二进制表示上执行运算,但是返回结果是标准的JavaScript数值。
| 操作符 | 用法 | 描述 |
|---|---|---|
| 按位与AND | a & b | 在a,b的位表示中,每一个对应的位都为1则返回1, 否则返回0. |
| 按位或OR | a | b | 在a,b的位表示中,每一个对应的位,只要有一个为1则返回1, 否则返回0. |
| 按位异或XOR | a ^ b | 在a,b的位表示中,每一个对应的位,两个不相同则返回1,相同则返回0. |
| 按位非NOT | ~ a | 反转被操作数的位。 |
| 左移shift | a << b | 将a的二进制串向左移动b位,右边移入0. |
| 算术右移 | a >> b | 把a的二进制表示向右移动b位,丢弃被移出的所有位.(译注:算术右移左边空出的位是根据最高位是0和1来进行填充的) |
| 无符号右移(左边空出位用0填充) | a >>> b | 把a的二进制表示向右移动b位,丢弃被移出的所有位,并把左边空出的位都填充为0 |
1.5 逻辑运算符
逻辑运算符常用于布尔(逻辑)值之间; 当操作数都是布尔值时,返回值也是布尔值。 不过实际上&&和||返回的是一个特定的操作数的值,所以当它用于非布尔值的时候,返回值就可能是非布尔值。
| 运算符 | 范例 | 描述 |
|---|---|---|
逻辑与(&&) | expr1 && expr2 | (逻辑与) 如果expr1能被转换为false,那么返回expr1;否则,返回expr2。因此,&&用于布尔值时,当操作数都为true时返回true;否则返回false. |
逻辑或(||) | expr1 || expr2 | (逻辑或) 如果expr1能被转换为true,那么返回expr1;否则,返回expr2。因此,||用于布尔值时,当任何一个操作数为true则返回true;如果操作数都是false则返回false。 |
逻辑非(!) | !expr | (逻辑非) 如果操作数能够转换为true则返回false;否则返回true。 |
逻辑运算符里的短路
- 短路:只存在于 && 和 || 中,当满足一定条件会让右边代码不执行
false&& anything // 被短路求值为falsetrue|| anything // 被短路求值为true
**注意:**能被转换为
false的值有null,0,NaN, 空字符串(" ")和undefined。
下面是&&(逻辑"与")操作符的示例。
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
var a5 = "Cat" && "Dog"; // t && t returns Dog
var a6 = false && "Cat"; // f && t returns false
var a7 = "Cat" && false; // t && f returns false
下面是||(逻辑"或")操作符的示例。
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
var o5 = "Cat" || "Dog"; // t || t returns Cat
var o6 = false || "Cat"; // f || t returns Cat
var o7 = "Cat" || false; // t || f returns Cat
下面是!(逻辑"非")操作符的示例。
var n1 = !true; // !t returns false
var n2 = !false; // !f returns true
var n3 = !"Cat"; // !t returns false
1.6 字符串运算符
除了比较操作符,它可以在字符串值中使用,连接操作符(+)连接两个字符串值相连接,返回另一个字符串,它是两个操作数串的结合。
可以称字符串拼接。
1.7 条件(三元)运算符
条件运算符是JavaScript中唯一需要三个操作数的运算符。运算的结果根据给定条件在两个值中取其一。语法为:
条件 ? 值1 : 值2
如果条件为真,则结果取值1。否则为值2。你能够在任何允许使用标准运算符的地方使用条件运算符。
例如:
var status = (age >= 18) ? "adult" : "minor";
当 age 大于等于18的时候,将“adult”赋值给status;否则将“minor”赋值给 status。
1.8 逗号操作符
逗号操作符(,)对两个操作数进行求值并返回最终操作数的值。它常常用在 for 循环中,在每次循环时对多个变量进行更新。
例如,假如 a 是一个二维数组,每个维度各有10个元素,以下代码利用逗号操作符来同时改变两个变量的值。这段代码的功能是打印出该二维数组的对角线元素的值:
var x = [0,1,2,3,4,5,6,7,8,9]
var a = [x, x, x, x, x];
for (var i = 0, j = 9; i <= j; i++, j--)
console.log('a[' + i + '][' + j + ']= ' + a[i][j]);
1.9 一元操作符
一元操作符仅对应一个操作数。
delete
delete操作符,删除一个对象的属性或者一个数组中某一个键值。语法如下:
delete objectName.property;
delete objectName[index];
delete property; // legal only within a with statement
objectName是一个对象名,property 是一个已经存在的属性,index是数组中的一个已经存在的键值的索引值。
第三行的形式只在with声明的状态下是合法的, 从对象中删除一个属性。
你能使用 delete 删除各种各样的隐式声明, 但是被var声明的除外。
如果 delete 操作成功,属性或者元素会变成 undefined。如果 delete可行会返回true,如果不成功返回false。
x = 42;
var y = 43;
myobj = new Number();
myobj.h = 4; // create property h
delete x; // returns true (can delete if declared implicitly)
delete y; // returns false (cannot delete if declared with var)
delete Math.PI; // returns false (cannot delete predefined properties)
delete myobj.h; // returns true (can delete user-defined properties)
delete myobj; // returns true (can delete if declared implicitly)
删除数组元素
删除数组中的元素时,数组的长度是不变的,例如删除a[3], a[4],a[4]``和a[3] 仍然存在变成了undefined。
delete 删除数组中的一个元素,这个元素就不在数组中了。例如,trees[3]被删除,trees[3] 仍然可寻址并返回undefined。
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
delete trees[3];
if (3 in trees) {
// 不会被执行
}
如果想让数组中存在一个元素但是是undefined值,使用undefined关键字而不是delete操作. 如下: trees[3]分配一个undefined,但是这个数组元素仍然存在:
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
trees[3] = undefined;
if (3 in trees) {
// this gets executed(会被执行)
}
typeof
typeof操作符 可通过下面2种方式使用:
typeof operand
typeof (operand)
typeof操作符返回一个表示 operand 类型的字符串值。operand 可为字符串、变量、关键词或对象,其类型将被返回。operand 两侧的括号为可选。
假设你定义了如下的变量:
var myFun = new Function("5 + 2");
var shape = "round";
var size = 1;
var today = new Date();
typeof操作符将会返回如下的结果:
typeof myFun; // returns "function"
typeof shape; // returns "string"
typeof size; // returns "number"
typeof today; // returns "object"
typeof dontExist; // returns "undefined"
对于关键词 true 和 null, typeof 操作符将会返回如下结果:
typeof true; // returns "boolean"
typeof null; // returns "object"
对于一个数值或字符串, typeof 操作符将会返回如下结果:
typeof 62; // returns "number"
typeof 'Hello world'; // returns "string"
对于属性值,typeof操作符将会返回属性所包含值的类型:
typeof document.lastModified; // returns "string" 返回时间
typeof window.length; // returns "number"
typeof Math.LN2; // returns "number"
void
void 运算符运用方法如下:
void (expression)
void expression
void运算符,表明一个运算没有返回值。expression是JavaScript表达式,括号中的表达式是一个可选项,当然使用该方式是一种好的形式。
你可以使用void运算符指明一个超文本链接。该表达式是有效的,但是并不会在当前文档中进行加载。
如下创建了一个超链接文本,当用户单击该文本时,不会有任何效果。
<a href="javascript:void(0)">Click here to do nothing</a>
下面的代码创建了一个超链接,当用户单击它时,提交一个表单。
<a href="javascript:void(document.form.submit())">
Click here to submit</a>
1.10 关系操作符
关系操作符对操作数进行比较,根据比较结果真或假,返回相应的布尔值。
in
in操作符,如果所指定的属性确实存在于所指定的对象中,则会返回true,语法如下:
propNameOrNumber in objectName
在这里 propNameOrNumber可以是一个代表着属性名的字符串或者是一个代表着数组索引的数值表达式,而objectName则是一个对象名。
下面的例子是 in 操作的常见用法。
// Arrays
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
0 in trees; // returns true
3 in trees; // returns true
6 in trees; // returns false
"bay" in trees; // returns false (you must specify the index number,
// not the value at that index)
"length" in trees; // returns true (length is an Array property)
// Predefined objects
"PI" in Math; // returns true
var myString = new String("coral");
"length" in myString; // returns true
// Custom objects
var mycar = {make: "Honda", model: "Accord", year: 1998};
"make" in mycar; // returns true
"model" in mycar; // returns true
instanceof
如果所判别的对象确实是所指定的类型,则返回true。其语法如下:
objectName instanceof objectType
objectName 是需要做判别的对象的名称,而objectType是假定的对象的类型, 例如Date或 Array.
当你需要确认一个对象在运行时的类型时,可使用instanceof. 例如,需要 catch 异常时,你可以针对抛出异常的类型,来做不同的异常处理。
例如, 下面的代码使用instanceof去判断 theDay是否是一个 Date 对象. 因为theDay是一个Date对象, 所以if中的代码会执行.
var theDay = new Date(1995, 12, 17);
if (theDay instanceof Date) {
// statements to execute
}
1.11 运算符优先级
| 优先级 | 顺序 |
|---|---|
| 1 | . [] |
| 2 | () new |
| 3 | ! ~ - + ++ -- typeof void delete |
| 4 | * / % |
| 5 | + - |
| 6 | << >> >>> |
| 7 | < <= > >= in instanceof |
| 8 | == != === !== |
| 9 | & |
| 10 | ^ |
| 11 | | |
| 12 | && |
| 13 | || |
| 14 | ?: |
| 15 | = += -= *= /= %= <<= >>= >>>= &= ^= |= |
| 16 | , |
2.表达式
表达式是一组代码的集合,它返回一个值。
每一个合法的表达式都能计算成某个值,但从概念上讲,有两种类型的表达式:
- 有副作用的(比如赋值)例如:x=7
- 单纯计算求值的。例如:3 + 4
JavaScript有以下表达式类型:
- 算数: 得出一个数字, 例如 3.14159.
- 字符串: 得出一个字符串, 例如, “Fred” 或 “234”.
- 逻辑值: 得出true或者false.
- 基本表达式: javascript中基本的关键字和一般表达式。
- 左值表达式: 分配给左值。
基本表达式
this
this关键字被用于指代当前的对象,通常,this指代的是方法中正在被调用的对象。
假设一个用于验证对象value属性的validate函数,传参有对象,最高值和最低值。
function validate(obj, lowval, hival){
if ((obj.value < lowval) || (obj.value > hival))
console.log("Invalid Value!");
}
你可以在任何表单元素的onchange事件处理中调用validat函数,用this来指代当前的表单元素,用例如下:
<p>请输入18 ~ 99之间的数字:</p>
<input type="text" name="age" size=3 onChange="validate(this, 18, 99);">
左值表达式
左值可以作为赋值的目标。
new
你可以使用new operator 创建一个自定义类型或者是预置类型的对象实例。用法如下:
var objectName = new objectType([param1, param2, ..., paramN]);
super
super关键字可以用来调用一个对象父类的函数,它在用来调用一个类的父类的构造函数时非常有用,比如:
super([arguments]); // 调用父构造函数。 super.functionOnParent([arguments]);
扩展语句
扩展语句符允许一个表达式在原地展开, 当需要多个参数 (比如函数调用时) 或者多个值(比如字面量数组) 。
**例如:**现在你有一个数组,你想创建一个新数组,并将刚才那个作为它的一部分,用array的字面语法是不够的,你不得不写一些代码实现它,比如用些push, splice, concat等等。但是用spread syntax就没问题了:
var parts = ['shoulder', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];
类似的,扩展语句也可以用在函数调用的时候:
function f(x, y, z) { }
var args = [0, 1, 2];
f(...args);