摘要:對(duì)于這種疑問(wèn),我們只能求助給出官方解釋后自增操作符從上的算法描述,我們能夠清晰的得知,后自增操作符是先自增賦值,然后返回自增前的值,這樣的一個(gè)順序。
ES規(guī)范解讀之自增操作符
原文:https://github.com/kuitos/kuitos.github.io/issues/24
幾個(gè)月前,不知道什么緣由跟同事討論了起js里自增操作符(i++)的問(wèn)題,現(xiàn)將前因后果整理出來(lái),傳于世人?
事情起源于這樣一段代碼
var i = 0; i = i++; console.log(i);
來(lái),都來(lái)說(shuō)說(shuō)答案是啥?
結(jié)果是0
換一種形式,或許大家不會(huì)有多少疑問(wèn)
var i = 0; var a = i++; console.log(a); // 0
沒(méi)錯(cuò),這也是我們初學(xué)自增操作符的經(jīng)典例子,對(duì)這結(jié)果還有疑問(wèn)請(qǐng)自覺(jué)面壁。。。
遙想當(dāng)年學(xué)習(xí)自增操作符的口訣大致是,i++ 是先用后自增,++i 是先自增再用
那么按照這個(gè)思路,上面的代碼解析流程應(yīng)該是這樣的
var i =0; i = i; i = i + 1;
可惜結(jié)果并不是這樣的
按照犀牛書(shū)上的描述,后增量(post increment)操作符的特點(diǎn)是
它對(duì)操作數(shù)進(jìn)行增量計(jì)算,但返回未作增量計(jì)算的(unincremented)值。
但是書(shū)上并沒(méi)有告訴我們,先做增量計(jì)算再返回之前的值,還是返回之前的值再做增量計(jì)算。
對(duì)于這種疑問(wèn),我們只能求助ecmascript給出官方解釋?zhuān)?/p>
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上的算法描述,我們能夠清晰的得知,后自增操作符是先自增賦值,然后返回自增前的值,這樣的一個(gè)順序。
到這里還不算完。
既然i=i++這種操作最后i還是為原始值,也就是這段代碼不會(huì)有任何實(shí)際意義,那么js引擎有沒(méi)有可能針對(duì)性的做優(yōu)化,從而避免不必要的自增運(yùn)算?(如果你用的是IDE,IDE會(huì)提示你這是一段無(wú)用的代碼)
也就是說(shuō),我們?nèi)绾未_定,執(zhí)行引擎一定做了兩步操作:
i = i + 1; return iBeforeIncrease = 0;
i = iBeforeIncrease;
還是執(zhí)行引擎可能會(huì)針對(duì)性的優(yōu)化,只做一步操作:
i = iBeforeIncrease;
當(dāng)我在想怎么去確定這一點(diǎn)時(shí),松波給出了解決方案,用Object.observe()方法?。?!(該方法是ES7提案中的新api,不過(guò)chrome早早的實(shí)現(xiàn)了)
var obj = {i:0}; Object.observe(obj, function(changes){ console.log(changes); }); obj.i = obj.i++;
代碼放到chrome中跑一下,可以看到,改變觸發(fā)了兩次,也就是i做了兩次修改操作。
另外firefox中也提供了一個(gè)類(lèi)似的api,Object.prototype.watch,有興趣的同學(xué)可以試試用這個(gè)方式來(lái)驗(yàn)證一下。
順便抖個(gè)機(jī)靈,自增操作是非原子性操作,是非線(xiàn)程安全的,多線(xiàn)程環(huán)境下共用變量使用自增操作符是會(huì)有問(wèn)題的(前端同學(xué)們別急,ES7會(huì)為我們帶來(lái)js多線(xiàn)程編程體驗(yàn)?)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/86003.html
摘要:從表中可以看到,比較運(yùn)算符的優(yōu)先級(jí)為,而三元表達(dá)式條件運(yùn)算符的優(yōu)化級(jí)為,因此可以確定比較運(yùn)算符的優(yōu)先級(jí)要比三元表達(dá)式的要高,循環(huán)條件其實(shí)等價(jià)于第二種寫(xiě)法。從上表中也可以看出前綴自增比比較運(yùn)算符的優(yōu)化級(jí)要高。 我悟出權(quán)力本來(lái)就是不講理的——蟑螂就是海米;也悟出要造反,內(nèi)心必須強(qiáng)大到足以承受任何后果才行?!睄u《城門(mén)開(kāi)》 本文為讀 lodash 源碼的第十篇,后續(xù)文章會(huì)更新到這個(gè)倉(cāng)庫(kù)中...
摘要:與此相對(duì),強(qiáng)類(lèi)型語(yǔ)言的類(lèi)型之間不一定有隱式轉(zhuǎn)換。三為什么是弱類(lèi)型弱類(lèi)型相對(duì)于強(qiáng)類(lèi)型來(lái)說(shuō)類(lèi)型檢查更不嚴(yán)格,比如說(shuō)允許變量類(lèi)型的隱式轉(zhuǎn)換,允許強(qiáng)制類(lèi)型轉(zhuǎn)換等等。在中,加性運(yùn)算符有大量的特殊行為。 從++[[]][+[]]+[+[]]==10?深入淺出弱類(lèi)型JS的隱式轉(zhuǎn)換 本文純屬原創(chuàng)? 如有雷同? 純屬抄襲? 不甚榮幸! 歡迎轉(zhuǎn)載! 原文收錄在【我的GitHub博客】,覺(jué)得本文寫(xiě)的不算爛的...
摘要:那么什么是基礎(chǔ)對(duì)象組件呢,舉兩個(gè)例子我們?cè)賮?lái)看看屬性訪(fǎng)問(wèn)器,就是括號(hào)操作符及點(diǎn)號(hào)操作符都做了什么屬性訪(fǎng)問(wèn)器也就是說(shuō)括號(hào)跟點(diǎn)號(hào)對(duì)解釋器而言是一樣的。 ES規(guī)范解讀之賦值操作符&屬性訪(fǎng)問(wèn)器 原文:https://github.com/kuitos/kuitos.github.io/issues/24事情起源于某天某妹子同事在看angular文檔中關(guān)于Scope的說(shuō)明Understandin...
摘要:標(biāo)準(zhǔn)對(duì)象,語(yǔ)義由本規(guī)范定義的對(duì)象。三個(gè)冒號(hào)作為分隔符分割數(shù)字字符串文法的產(chǎn)生式。所有因?yàn)閹?lái)的問(wèn)題,基本上是占著茅坑不拉屎的行為導(dǎo)致。以數(shù)組測(cè)試操作為例,標(biāo)準(zhǔn)中的描述如下相對(duì)于來(lái)說(shuō),規(guī)范中增加了對(duì)的處理。 前言 本文是對(duì)《ECMAScript 2018 Language Specification》的解讀。本文是對(duì)標(biāo)準(zhǔn)的概述性導(dǎo)讀,不是對(duì) ES2018特性的詳細(xì)描述,也不會(huì)針對(duì)某個(gè)技術(shù)...
摘要:深入系列第六篇,本篇我們追根溯源,從規(guī)范解讀在函數(shù)調(diào)用時(shí)到底是如何確定的。因?yàn)槲覀円獜囊?guī)范開(kāi)始講起。規(guī)范類(lèi)型包括和。下一篇文章深入之執(zhí)行上下文深入系列深入系列目錄地址。如果有錯(cuò)誤或者不嚴(yán)謹(jǐn)?shù)牡胤?,?qǐng)務(wù)必給予指正,十分感謝。 JavaScript深入系列第六篇,本篇我們追根溯源,從 ECMAScript5 規(guī)范解讀 this 在函數(shù)調(diào)用時(shí)到底是如何確定的。 前言 在《JavaScript...
閱讀 2387·2023-04-26 01:50
閱讀 831·2021-09-22 15:20
閱讀 2697·2019-08-30 15:53
閱讀 1749·2019-08-30 12:49
閱讀 1812·2019-08-26 14:05
閱讀 2803·2019-08-26 11:42
閱讀 2415·2019-08-26 10:40
閱讀 2682·2019-08-26 10:38