ES范例解读之自增操纵符
原文:https://github.com/kuitos/kuitos.github.io/issues/24
几个月前,不知道什么启事跟同事议论了起js里自增操纵符(i++)的题目,现将来龙去脉整理出来,传于众人?
事变起源于如许一段代码
var i = 0;
i = i++;
console.log(i);
来,都来说说答案是啥?
效果是0
换一种情势,也许人人不会有若干疑问
var i = 0;
var a = i++;
console.log(a); // 0
没错,这也是我们初学自增操纵符的典范例子,对这效果另有疑问请自发面壁。。。
遐想昔时进修自增操纵符的口诀大抵是,i++ 是先用后自增,++i 是先自增再用
那末根据这个思绪,上面的代码剖析流程应该是如许的
var i =0;
i = i;
i = i + 1;
惋惜效果并非如许的
根据犀牛书上的形貌,后增量(post increment)操纵符的特点是
它对操纵数举行增量盘算,但返回未作增量盘算的(unincremented)值。
然则书上并没有通知我们,先做增量盘算再返回之前的值,照样返回之前的值再做增量盘算。
关于这类疑问,我们只能乞助ecmascript给出官方诠释:
Postfix Increment Operator(后自增操纵符)
The production PostfixExpression : LeftHandSideExpression [no LineTerminator here] ++ is evaluated as follows:
Evaluate LeftHandSideExpression.
Call GetValue(Result(1)).
Call ToNumber(Result(2)).
Add the value 1 to Result(3), using the same rules as for the + operator (see 11.6.3).
Call PutValue(Result(1), Result(4)).
Return Result(3).
从es上的算法形貌,我们能够清楚的得知,后自增操纵符是先自增赋值,然后返回自增前的值,如许的一个递次。
到这里还不算完。
既然i=i++
这类操纵末了i照样为原始值,也就是这段代码不会有任何实际意义,那末js引擎有无能够针对性的做优化,从而防止不必要的自增运算?(假如你用的是IDE,IDE会提醒你这是一段无用的代码)
也就是说,我们怎样肯定,实行引擎肯定做了两步操纵:
i = i + 1;
return iBeforeIncrease = 0;i = iBeforeIncrease;
照样实行引擎能够会针对性的优化,只做一步操纵:
i = iBeforeIncrease;
当我在想怎样去肯定这一点时,松波给出了解决方案,用Object.observe()要领啊!!(该要领是ES7提案中的新api,不过chrome早早的完成了)
var obj = {i:0};
Object.observe(obj, function(changes){
console.log(changes);
});
obj.i = obj.i++;
代码放到chrome中跑一下,能够看到,转变触发了两次,也就是i做了两次修正操纵。
别的firefox中也供应了一个相似的api,Object.prototype.watch,有兴致的同砚能够试试用这个体式格局来考证一下。
趁便抖个灵巧,自增操纵黑白原子性操纵,黑白线程平安的,多线程环境下共用变量运用自增操纵符是会有题目的(前端同砚们别急,ES7会为我们带来js多线程编程体验?)。