Skip to content

运算符

参考:

需要注意两个地方

  • 运算符优先级
  • 运算符关联性,从右向左还是从左向右
js
// 优先级高的运算符最先被执行
1 || 1 ? 2 : 3 // ||的优先级高于 ?: 因此为 (1 || 1) ? 2 : 3

// 关联性,一个运算符有规定的操作方向,如 =、?: 为从右向左,||、&&等从左向右
var a = b = 1 // 从右向左执行相当于 b=1;var a=b;只声明了a

优先级

在计算表达式时,先根据运算符的优先级将子表达式绑定在一起(相当于用()包起来)

js
1 || true && fn() // && 优先级高,因此将后面的子表达式绑定在一起 => 1 || (ture  && fn())
1 || (true && fn()) // || 的关联方向从左向右,因此 先执行左边 为true,短路直接返回 1
js
var a = 42;
var b = "foo";
var c = 0;

c || b ? a : b ;  // || 的优先级高,因此将前面的关联起来 
(c || b) ? a : b; // c||b为true,因此返回a

关联性

运算符的关联式决定了我们如何拆分子表达式

js
var a = 42;
var b = "foo";
var c = 0;
a && b || c ? c || b ? a : c && b : a  
// && || 均为从左向右, ?:为从右向左,因此先拆分表达式
a && b || c ? (c || b ? a : c && b) : a  
a && b || c ? (c || b ? a : (c && b)) : a  
// 然后再根据优先级将子表达式进行绑定
((a && b ) || c ) ? ((c || b) ? a : (c && b)) : a  
// 最后返回 a

小结

关联性和优先级都是我们需要记忆的,这里了整理了一下

  • 优先级而言:属性访问 > 算术操作符 > 比较操作符> 逻辑操作符 > "="赋值符号
  • 关联性而言,
    • 从右向左的运算符有:
      • new Foo无参数列表
      • 逻辑非!xx、按位非~xx、一元加法+a、一元减法-b++a--atypeof avoid adelete a.bawait
      • a**b
      • 条件运算a ? b : c
      • 赋值运算=以及+=-=等组合赋值运算
      • yieldyield *
    • 无关联性的运算符有
      • new Foo(带参数列表)
      • a++a--
      • 展开运算符...[a,b]
    • 其余均为从左向右关联性的运算符

可以查阅文档:运算符优先级

一个常见的考题

参看下面的题目

js
function Foo() {
    getName = function () {
        console.log(1)
    }
    return this;
}
Foo.getName = function () {
    console.log(2)
}
Foo.prototype.getName = function () {
    console.log(3)
}
var getName = function () {
    console.log(4)
}

function getName() {
    console.log(5)
}

Foo.getName() // 2, 调用类的静态方法Foo.getName

getName()  // 4, function getName()会进行提升,之后被var getName重新赋值

Foo().getName() // 1, 修改外部变量getName为console.log(1)

new Foo.getName() //  2, new运算符的优先级低于属性访问符`.` => new (Foo.getName)() 将 Foo.getName作为构造函数调用

new Foo().getName() // 3, 运算符优先级 new的优先级大于函数调用Foo(),且从左向右结合,转换为 (new Foo()).getName(),访问实例对象上的getName方法,委托到原型链查找

new new Foo().getName() // 3, 表达式中的运算符均从左向右结合 new (new Foo()).getName() => new ((new Foo()).getName)(), 将Foo.prototype.getName作为构造函数调用