js运算符知识

本文介绍了,js运算符的知识。包括js中的表达式、运算符的分类、运算符的优先级、运算符的结合性、运算符的运算顺序等知识。

前提知识-表达式

表达式是一组代码的集合,它返回一个值。

原始表达式

原始表达式是表达式的最小单位,它不再包含其他表达式。
常量(变量的一种,一般是全大写字母的形式)、变量、直接量、关键字。

1
2
3
4
5
6
COUNT // 常量
i // 变量
123 // 数字直接量
'hello' // 字符串直接量
/pattern/ // 正则表达式直接量
null // 关键字

初始化表达式

1
2
3
4
5
6
7
[1,2,3] // 数组初始化表达式

// 对象初始化表达式
{
age: 18,
seet: male
}

函数定义表达式

1
2
3
var = function add(x,y){
return x + y;
}

属性访问表达式

1
2
arr.length;
arr['length']

函数调用表达式

函数调用表达式以一个函数表达式开始,这个函数表达式指代了要调用的函数。函数表达式后跟随一对圆括号,括号内是一个以逗号隔开的参数列表。
先计算函数表达式,再计算参数表达式。

1
add(1,2);

对象创建表达式

1
new Object();

运算符的分类

赋值运算符

1
2
3
4
5
6
7
8
var a = 1; //赋值
a += 10; // 加法赋值,有副作用, a = a + 10的简写
a -= 1; // 减法赋值,有副作用, a = a - 1的简写
a *= 3; // 乘法赋值,有副作用, a = a * 3的简写
a %= 2; // 求余赋值,有副作用, a = a % 2的简写
a /= 3; // 除法赋值,有副作用, a = a / 3的简写
var foo = ["one", "two", "three"];
var [one, two, three] = foo; // 解构赋值

相等运算符

等于

  • 当两边操作数类型相同时,按全等规则判断。
  • 当两边操作数类型不同时,先进行隐式类型转换,规则如下:
    • undefined和null相等,undefined、null和其他任何类型都不相等。
    • 如果有一个操作数是数字类型或布尔类型,则把另一个操作数转为数字类型在进行比较。
    • 如果有一个操作数是对象,另一个操作数是原始类型值,先把对象转为原始类型值,先调用valueOf方法,如果返回值为原始类型,则按照以上的规则比较,否则再继续调用toString方法转为原始类型值。日期对象会先调用toString方法。
1
undefined == null; // true

大牛的总结:相等运算符

全等

  • 当两边操作数类型不同时,返回false。
  • 当两边操作数类型相同时,原始类型比较的是值,对象类型比较的是引用地址。相同返回true,不同返回false。NaN不等任何数值,包括它本身。注意,当两个操作数都是字符串时,比较的是字符串的编码。

    比较运算符

    比较运算符包括:大于运算符,小于运算符,大于等于运算符,小于等于运算符

  • 数值的比较,两个操作数都是数值,有一个操作数为数值,把另一个操作数转为数值。

  • 字符串的比较,即字符串编码的比较,两个操作数都是字符串。
  • 如果操作数是引用类型,现将操作数转为原始类型值,先调用valueOf方法,如果返回原始值,则按照上面两跳规则进行判断,否则继续调用toString方法,然后再按照上面的规则进行判断。

乘性运算符

乘性运算符包括:乘法运算符,除法运算符,求模运算符

运算规则为,将操作数转为数字再进行计算。不能转为数值时,返回NaN。

逻辑与和逻辑或

逻辑与

返回值为运行到哪个操作数的返回值。如果第一个操作数为true,返回值为第二个操作数的返回值。如果第一个操作数为false,返回值为第一个操作数的返回值。

  1. 对两个布尔值进行运算,如果其中有一个为false则返回值为false,如果两个值都为true则返回值为true。
  2. 对两个表达式进行运算,如果其中有一个为false则返回值为false,如果两个值都为true则返回值为true。一般用在判断语句中,两个表达式的返回值都为布尔值。
  3. 对两个表达式进行运算,如果第一个表达式返回true,则运行第二个表达式,否则不运行第二个表达式。短路写法,一般第一个表达式为判断条件,第二个表达式是一个执行操作。
    1
    2
    3
    4
    5
    6
    7
    8
    // 应用在判断语句中
    var a = 10;
    var b = 20;
    if(a > 0 && b < 50){
    console.log('逻辑与')
    }
    // 短路写法,第一个操作数返回true,运行第二个操作数
    fn && fn();

逻辑或

返回值为运行到哪个操作数的返回值。如果第一个操作数为false,返回值为第二个操作数的返回值。如果第一个操作数为true,返回值为第一个操作数的返回值。

  1. 对两个布尔值进行运算,如果有一个为true返回值为true,如果两个都为false返回值为false。
  2. 对两个表达式进行运算,如果有一个表达式返回true则返回值为true,如果两个表达式都返回false则返回值为false
  3. 对两个表达式进行运算,如果第一个表达式返回false,则运行第二个表达式,否则不运行第二个表达值。短路写法,用于赋值操作,一般第一个表达式为判断条件,第二个表达式是一个执行操作。
    1
    2
    3
    4
    5
    6
    7
    8
    // 应用在判断语句中
    var a = 10;
    var b = 20;
    if(a > 0 || b > 50){
    console.log('逻辑或')
    }
    // 短路写法,第一个操作数返回false,进行赋值
    obj.age && obj.age = 18;

条件运算符

condition ? expression1 : expression1
当条件为true时,运算符会返回表达式1的值,当条件为false时,运算符会返回表达式2的值。
结合性为从左向右运算。

逗号运算符

逗号运算符对它的每个操作数求值(从左到右),并返回最后一个操作数的值。
是优先级最低的运算符。

加性运算符

加法运算符

  • 如果有一个操作数是字符串类型,另一个操作数是原始类型值,将另一个操作数转为字符串,然后进行字符串拼接。
  • 如果两个操作数都是原始类型值且不是字符串类型,则将操作数转为数值,然后进行数值的相加。
  • 如果有一个操作数是字符串类型,另一个操作数是复杂类型值,先将另一个操作数转为原始类型值(先调用valueOf方法,不是原始值再调用toString方法),如果不是字符串类型,然后再转为字符串,进行字符串拼接。
  • 如果一个操作数是数字类型,另一个操作数是除了字符串之外的原始类型值,就将操作数转为数字,然后进行数字的相加。
  • 如果一个或两个操作数是复杂类型值,就将操作数转为原始值(先调用valueOf方法,不是原始值再调用toString方法),然后再按照上面的规则进行字符串拼接或数字的相加。

减法运算符

将两个操作数都转为数字然后进行相减。其中复杂类型值先转为原始值(先调用valueOf方法,不是原始值再调用toString方法),然后再转为数字。

一元运算符

只能操作一个表达式的运算符叫做一元运算符。

一元加运算符

将后面的操作数转为数字类型,和使用Number方法效果相同,返回数字或NaN。

  • 原始类型值
    • 数字:返回数字本身,包括负数也是返回其本身
    • 字符串:空字符串转为0,数字字符串转为对应的数值,其他转为NaN
    • null:转为0
    • undefined:转为NaN
    • 布尔值:true转为1,false转为0
  • 引用类型值
    • 先调用vlaueOf方法,如果返回值是原始类型值,按照原始类型值的规则进行转换,如果不是原始类型值,再继续调用toString方法,得到原始类型值,再按照原始类型值的规则进行转换。

一元减

  • 数字:返回数字对应的负数
  • 其他:先将操作数转为数字(即进行和一元加一样的操作),再返回数值对应的负数。

递增和递减(有副作用)

把所有的操作数转为数字类型,然后进行加1或减1的操作。

  • 前置:先进行加或减,再进行运算
  • 后置:先进行运算,再进行加或减

逻辑非

把操作数转为布尔类型,然后再取反。

按位非

操作数是数字时,运算效果是,对操作数取负值,然后减1。

typeof

typeof返回操作数的类型。可以对操作数使用括号包裹,用以表示优先级。
返回值为字符串。包括’number’,’boolean’,’null’,’undefined’,’string’,’object’。

void

对给定的表达式进行求值,然后返回undefined

delete(有副作用)

用于删除对象的某个属性。成功删除时返回true,否则返回false。

  • 如果试图删除的属性不存在,那么将不起作用,但任然返回true。
  • 只会删除对象上自身属性,不会删除原型链上的属性
  • 使用var、let、const声明的变量不能被删除,返回false。直接声明的变量可以被删除,因为这个变量是全局对象的属性。
  • 使用definedProperty方法设置为不可配置的属性不能删除。

运算符的优先级

优先级

属性访问的优先级最高,其次是一元运算符,再次是乘性运算符,再次是加性运算符,再次是比较运算符,再次是相等运算符,再次是逻辑或和逻辑与,再次是条件运算符,再次是赋值运算符,再次是逗号运算符。

运算符的结合性

在运算符优先级相同的情况下,运算的先后顺序。
一元运算符、三目运算、赋值运算符是右结合的其他都是左结合。

运算顺序

运算符的优先级和结合性规定了,它们在复杂表达式中的运算顺序。但并没有规定子表达式的计算过程中的运算顺序。js总是严格按照从左至右的顺序来计算表达式。

复杂类型值的toString和valueOf的执行顺序

  1. 复杂类型值转为字符串时,先调用toString,返回值不为原始类型值时,继续调用valueOf,得到原始类型值,再转为字符串类型,如果还得不到原始类型值则会报错
  2. 复杂类型值转为数值时,先调用valueOf,返回值不为原始类型值时,继续调用toString,得到原始类型值,再转为数值类型,如果还得不到原始类型值则会报错
  3. 复杂类型值转为原始类型值时,先调用valueOf,返回值不为原始类型值时,继续调用toString,如果还得不到原始类型值则会报错
  4. 日期对象转为原始类型值时,先调用toString
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var obj = {
    valueOf: function(){return 10},
    toString: function(){return 'abc'}
    }
    var newObj = {
    valueOf: function(){return 10},
    toString: function(){return 'abc'}
    }
    alert(obj); // 返回'abc',相当于转为字符串
    console.log(String(obj)) // 返回'abc',相当于转为字符串
    console.log('' + obj) // 转为原始值
坚持原创技术分享,您的支持将鼓励我继续创作!