37

看了此文,你还敢说你懂了Javascript运算符吗

 4 years ago
source link: https://www.tuicool.com/articles/niYfiqu
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

“JavaScript的很多奇技淫巧,都来自于对运算符的灵活使用。”

fYnQZ3I.jpg!web

1 运算符基础

1.1 优先级: 优先级高的运算符最先被执行

问题: 1 || 1 ? 2 : 3 ; 
答案:2
解析:||的优先级高
相当于: (1 || 1 )? 2 : 3
而不是: 1 || (1 ? 2 : 3 )

1.2 关联性: 运算符执行时的方向。是从左向右,还是从右向左

问题:+function (){var a = b = 1;}();
console.log(b);
console.log(a);
答案:1 error
解析:赋值从右到左,var a = b = 1所以相当于
b = 1;
var a = b;
那有同学可能会问,为什么不是?
var b = 1;
var a = b;
还记得变量提升吗?var a = b = 1;在变量提升的时候,只会把a去声明,并不会执行赋值中的b。
所以要想把b也声明了就需要按照语法 var a=1 , b ;

现在我们仔细把优先级的题改一下

1 || fn() && fn() 

MDN上写的是优先级高的运算符最先被执行,我们都知道 ||是短路的,后边不会执行。那么这个最先被执行的含义是什么呢?

1.3 短路:

  • && 运算符的短路(a && b):如果a为假,b就不用执行了
  • | | 运算符的短路(a || b):如果a为真,b就不用执行了
问题:1 || fn() && fn() 
答案:1 fn不会执行
解析:就是利用&&运算符的短路原理啊。

讲到这有些同学会觉得很简单啊,就是这样啊,看到短路后边就不用算了啊。也有的同学可能会有点懵,不是说好了, 优先级高的先被执行吗?明明&&的优先级高啊。哈哈,别吵吵,我们一起看下一题。

问题:var a = 42;
var b = "foo";
var c = 0;
c || b ? a : b ; // 42

刚才说短路的同学可能会说还是要参考优先级。刚才说优先级的同学可能一脸懵逼,静静地不想说话。那么我们开始今天的学习吧。

2 绑定

定义:运算符的优先级高先执行,并不是真正的执行,而是更强的绑定。

我们用上面来两个问题

1 || fn() && fn() // &&的优先级高,所以将后边的绑定
1 ||(fn() && fn()) // 所以相当于1 和(fn() && fn())的值去逻辑或
1 ||(fn() && fn()) // 我们查表,逻辑或从左到右执行。
1 ||(fn() && fn()) // 左执行,1是真值,所以短路,后边不执行
问题: var a = 42;
var b = "foo";
var c = 0;
c || b ? a : b ;
答案:42
解析:c || b ? a : b ; //查表 条件运算符权重是4,逻辑与符权重是6,所以逻辑与有更强的绑定
(c || b )? a : b ; //(c || b )相当于条件运算符里的条件
(c || b )? a : b ; //(c || b )值是0 ,所以值是 a

好,我们在做两题巩固一下

问题: var a = 5;
var b = 5;
var c = 5+a+++b;
[ a , c ]
答案: [6, 15]
解析: b = 5+a+++b; //查表 后置递增权重17 前置递增权重16
b = 5 +(a++)+ b; //++优先级更高,所以和绑定a绑定在一起
b = 5 +(a++)+ b; //根据语法后置递增先执行语句,后递增
b = 5 +(a++)+ b; //执行语句时a是5,所以b是15
b = 5 +(a++)+ b; //a在进行自增,得到6
问题: var a = 5;
var b = 5;
var c = ++a-b;
[ a , c ]
答案: [6, 1]
解析: var c = ++a-b; //查表 前置递增权重和一元减权重都是16,从左往右执行
var c = ++a-b; //根据语法前置递增先递增,后执行语句 a = 6
var c = ++a-b; //执行语句时a是6,所以b是1

看到这,同学们可能恍然大悟,就这么回事啊。别急,我们来看下一题。 要解决这个问题,需要我们理解下一节的概念。

问题: var a = 42;
var b = "foo";
var c = 0;
a && b || c ? c || b ? a : c && b : a

3 关联

定义:运算符的关联性去定义表达式的处理方向

来,用题说话

问题:a && b && c 的执行顺序
解析:(1)两个运算符都是&&,权重一样。所以这个时候就要看关联性。
(2)查表 &&的关联性是从左到右
(3)所以表达式应该是 ( a && b ) && c
问题:a ? b :c ? d : e 的执行顺序
解析:(1)两个运算符都是条件运算符,权重一样。所以这个时候就要看关联性。
(2)查表条件运算符的关联性是从右到左
(3)所以表达式应该是 a ? b :(c ? d : e )

好了,现在我们就可以轻松解决上面那个问题啦。

问题: var a = 42;
var b = "foo";
var c = 0;
a && b || c ? c || b ? a : c && b : a
答案: 42
解析:(a && b) || c ? c || b ? a :(c && b) : a //首先查表逻辑与权重是6最高
((a && b) || c) ? c || b ? a :(c && b) : a //然后是逻辑或
((a && b) || c) ? (c || b ? a :(c && b)) : a //两个条件运算符,权重一样。关联性从右到左

啊、、有没有很开心 最后的最后,我们来讲一个释疑

4 释疑

释疑顾名思义就是解释调疑惑的地方,那最好的办法就是加()。

如果你能够熟练运用优先级/关联的规则,你的代码能更简洁,许多框架都是这样写的,非常漂亮。

但是你要叫不准,那就加()吧,千万别逞能,美其名曰有助于代码的可阅读性。

【责任编辑:庞桂玉 TEL:(010)68476606】


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK