整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          5分鐘讀懂Unicode

          多互聯網新鮮資訊、工作奇淫技巧關注原創【飛魚在浪嶼】(日更新)


          Unicode是涵蓋世界上大多數書寫系統。用在網絡,大多數操作系統,Java和.NET的標準編碼等。

          在Unicode誕生之前,都有自己的編碼,它們都不同,而且不兼容編碼。而Unicode是幾乎所有字符的超集,因此可以用于互換信息。

          它誕生至今30多年了。

          在開始下文之前,如果遇到查詢unicode代碼的,可以使用工具類網站https://unicode.yunser.com/unicode

          Unicode 為每個字符(例如a,?, ?,不和?)定義一個代碼/數字。從Unicode 6.2開始(http://www.unicode.org/versions/Unicode6.2.0/),共有109,976個代碼!

          它還包括組合字符,諸如??之類這些字符可以添加到其他字符中;這樣,Unicode不需要字母和重音的每種可能組合設置一個代碼。另一方面,Unicode的一般不關心字體或風格上的區別:比如下面兩個是同一種字符:

          Unicode不只是字符集合。它還涵蓋了諸如UTF-8之類的標準編碼。小寫/大寫/標題大小寫映射,整理(排序),換行符,從右到左的腳本的渲染處理等。


          通用歸一化/消除重復性

          因為Unicode是其他編碼的超集,所以它有時包括同一個字符,但是卻有多個不同的代碼,例如,以下三個:

          • 帶環的? 拉丁大寫字母A(U + 00C5)
          • 一個長度計量單位,一單位等于0.1nm(U + 212B)
          • u'\u0041\u030a' , 大寫拉丁字母 A(U + 0041) + ?? 組合鍵(U + 030A)

          python輸出

          為了使它們在相等性測試等中被視為相同的字符串,您應該通過Unicode規范(http://unicode.org/reports/tr15/)運行所有輸入。最常見的形式是 NFC(Normalisation Form C),它盡可能使用預先組合字符,并如果存在多個,則一個嚴格的順序定義這變音符號。NFD D(Normalisation Form D則盡可能撰寫1個字符。只要您保持一致,使用哪種形式都沒有關系。NFD通常更快(代碼點更少),建議通過NFD運行輸入,并通過NFC輸出。

          Compatibility decomposition/兼容性分解(NFKC,compatibility decomposition + canonical composition會把?,Ⅸ和甚至?映射為為“FFI”,“IX”和“5”分別。搜索文本時,這種NFKC規范化功能會起到幫助。


          大小寫折疊

          在Unicode世界中,大小寫并不是那么簡單:

          • 有些字符串在更改大小寫時實際上會更改長度:?將大寫字母更改為“ SS”。
          • 小號拉丁小寫字母渴望著應為“s”和“S”在不區分大小寫的比較被看作是相等的。
          • Σ希臘大寫字母 Sigma有兩種小寫形式: 單詞的開頭或中間寫成σ,以及 ?在單詞的結尾。
          • 在希臘語中,若一個單字的最末一個字母是sigma,要把該字母寫成 ?。大寫Σ可以表示: 數學上的求和符號。 粒子物理學中的一類重子。 小寫σ可以表示: σ鍵
          • 外殼大多是在地區之間基本一致,但土耳其是個例外:它既有一個點線和帶點我,在這兩個小寫和大寫。

          為了確保您的代碼能夠處理這些情況以及任何新的情況,Unicode提供了 一種單向 “ casefold”操作,該操作允許不區分大小寫的比較。


          排序

          排序(或排序規則)是特定語言環境的,并且像大小寫一樣充滿特殊性:

          • 德國和瑞典都有 ?和?,但是它們排序不同。德國將它們視為相同的字母變體沒有變音符號(即“a? bcdefghijklmno ?pqrstuvwxyz”),而瑞典認為在年底這些新的字母,并把它們放在最后('ABCDEFGHIJKLMNOPQRSTUVWXYZ ??)務必按照用戶期望的順序對事物進行排序。
          • 排序也因應用程序而異;例如,電話簿的排序方式通常與書本索引不同。
          • 對于漢字和其他表意文字,有許多可能的順序,例如拼音(注音),按筆劃計數等。
          • 可以根據用戶偏好(例如,大寫優先還是小寫優先)來排序。

          僅通過二進制比較進行排序是不夠的。而且,代碼點通常也不是明智的。幸運的是,Unicode指定了一種 可高度自定義的歸類算法,該算法涵蓋了所有邊緣情況,并且做了一些巧妙的工作以使其變得相當快。這是一個示例:2

          該UCA可以把“10”和“2”視為數值,如排序“10”“放在“2”后面?” 。把“?”視為字符串“問號”。


          編碼方式

          大端序有UTF-8,UTF-16和UTF-32。每種編碼都保證幾乎每個碼點和字節序列的可逆映射。

          • UTF-32非常簡單:每個代碼點用四個字節。占用大量空間,不建議用作信息互換。
          • UTF-8在網絡上非常常見。它是面向字節的(無字節序問題),處理得很好,與ASCII兼容,并且對于大多數為ASCII(例如HTML)的文本占用最小的空間。U + 0800和U + FFFF之間的代碼點(包括常用的CJKV 字符/ 中國日本韓國越南)將占用3個字節而不是2個字節。因此,UTF-16可能更節省空間。ASCII兼容性有助于允許UTF-8在不支持Unicode的腳本和進程也能運行。但是,如果這樣的系統嘗試對數據執行任何操作(大小寫轉換,子字符串,正則表達式),則該數據會被損壞。
          • Java,.NET和Windows使用UTF-16。它使用2個字節(16位)表示最常見的63K代碼點,并使用4個字節表示不常見的1M代碼點(使用兩個“代理”代碼點)。與通常的做法相反,UTF-16不是固定寬度的編碼。但是,只要不包含代理代碼點,就可以將其視為一個獨立,從而可以加快字符串操作。UTF-16流通常以U + FEFF開頭,以檢測流的字節序(字節順序)。否則,您可以通過'UTF-16BE'或'UTF-16LE'顯式編碼或解碼以指定字節序。

          Unicode和國際化域名

          國際字符 給域名帶來了一個大問題。就像 I (I 0049 拉丁文大寫 I)和 l(l 006C拉丁L的小寫) 看起來很相似一樣,Unicode除了增加了許多不可見的控制字符,空格字符和從右到左的文本外,還將這個問題放大很多。

          瀏覽器和注冊商已針對此采取了幾種措施:

          • 許多頂級域名限制可以在域名中使用哪些字符。
          • 如果域包含來自多個腳本的字符和/或不屬于用戶首選語言之一的字符,則瀏覽器可以使用Punycode顯示該域(請參見下文)。
          • 國際化的國家/地區代碼,例如.рф(俄羅斯),僅接受西里爾字母名稱。

          名稱準備/字符串準備

          RFC 3491定義了nameprep,一種在字符串可以在域名中使用之前對字符串進行大小寫折疊,規范化和清理的機制。如果使用了禁止的代碼點,這將刪除許多不可見的字符并拋出異常。


          Punycode/域名代碼

          出于傳統原因,DNS不允許ASCII之外的擴展字符,因此Punycode是ASCII兼容的編碼方案。例如,café.com變為xn--caf-dma.com。所有Punycode編碼的域組件都可以通過其xn--前綴立即識別。


          這也適用于頂級域名 :比如中國的代碼為xn-fiqs8s。

          “用戶腳本”的問題

          在Perl至少,一切(substr,length,index,reverse...)操作是以代碼點為準。但這通常不是你想要的,因為用戶認為像?這樣的字符實際上是兩個代碼點(y + ??)。

          甚至看似沒問題的東西,例如printf "%-10s", $str完全中斷組合字符,全角字符(例如中文/日文)或零角字符的操作。


          換行

          一旦涉及到Unicode ,換行(或自動換行)就變得異常復雜。您必須考慮各種不間斷和不間斷的控制和空格字符,每種語言中的標點符號(例如?和?引號或數字中使用的句號或逗號)以及每個字符的寬度。


          文件系統

          當您使用Unicode字符串作為文件或目錄名稱時,所有操作都不好用。使用什么編碼?使用什么API?(Windows有兩種,一種使用Unicode,另一種嘗試使用與語言環境相關的編碼)。Mac OSX文件系統則會執行規范化,例如對文件名執行NFD。如果您的平臺不了解分解后的Unicode,則可能會出現問題。


          漢字統一

          漢字是中文,日文(漢字)以及韓文和越南文的共同特征。根據腳本的不同,許多腳本都有獨特的視覺外觀,但是Unicode出于簡化和性能的原因將它們統一為一個代碼點(示例)。

          這引起了爭議,因為角色的視覺形式可能有意義;可能不會向用戶顯示他們的國家/地區版本,而是其他國家/地區的版本。在某些情況下,它們看起來可能非常不同(例如,直)。正如西方名稱的變化(例如“ John”或“ Jon”)一樣,日語名稱可能使用Unicode無法提供的特定字形變體,因此人們實際上無法以自己喜歡的方式來寫自己的名字!

          實際上,用戶選擇一種字體以其想要的樣式呈現字形,無論是日語還是中文。變體選擇器(參見下文)是解決該問題的另一種方法。

          由于政治和遺留原因(與舊字符集兼容),Unicode不會嘗試統一簡體和繁體中文。


          表情符號

          Unicode 6.0版增加了722個“表情符號”字符,這些表情符號通常在日語手機上使用,但最近在Mac OS X(Lion),Gmail,iPhone和Windows Phone 7中使用。某些字體可能選擇將其呈現為全彩色表情符號。 ; 有些則可能根本不支持他們。

          表情符號的Unicode表示,包含你熟悉的LOVE HOTEL 和PILE OF POO


          區域國旗符號

          Unicode 6.0的表情符號為許多國家(地區)標志引入了符號,但并不是全部國家。作為一種可選方案,范圍U + 1F1E6 .. U + 1F1FF 定義了從A到Z的符號。如果該范圍中的兩個符號形成了ISO-3166-1國家代碼(例如,法國的“ FR”),則渲染器可以顯示為國旗!


          變體選擇器

          變體選擇器是代碼點,可更改渲染字符之前的字符方式。有256個,它們占據的范圍為U + FE00 .. U + FE0F 和U + E0100.. U + E01EF加上U + 180B,U + 180C和U + 180D。

          它們對于蒙古語腳本來說是必不可少的,蒙古語腳本具有不同的字形形式,具體取決于其在單詞中的位置,單詞的性別,附近有哪些字母,單詞是否為外國單詞以及現代與傳統拼字法(詳細信息)。

          預計這些將用于提供由Han Unification統一的字形的變體。

          它們還用于更深奧的事物,例如數學運算符的襯線版本。

          頁能將文本、圖片、音頻、視頻等諸多元素結合起來,通過CSS,能呈現這些元素預定的外觀,通過JavaScrip腳本,能呈現預定的動作。

          網頁設計前端語言HTML、HTML、JavaScript三者關系:

          前端網頁語言功能說明符號
          HTML內容Hyper Text Markup Language<tag>…</tag>
          CSS內容呈現的外觀Cascading Style Sheets<style>...</style>
          JavaScript內容呈現的動作嵌入網頁有腳本<script>...</script>

          以上由瀏覽器解釋執行。

          代碼舉例:

          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

          <html xmlns="http://www.w3.org/1999/xhtml">

          <head>

          <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

          <title>前端語言比較</title>

          </head>

          <style>

          #container{

          margin:auto;

          width:75%;

          }

          .descri{

          color:#990000;

          font-size:120%;

          }

          </style>

          <body>

          <div id="container">

          <h4>前端語言比較</h4>

          <p class="descri">簡單加法器:</p>

          <form name="myform">

          加數:<input type="text" name="first" size="6" />

          <span style="color:red;">+</span>&nbsp;被加數

          <input type="text" name="second" size="6" />

          <input type="button" onclick="sum()" value="求和" />

          <span style="color:blue;">=</span>&nbsp;

          <input type="text" name="result" size="6" />

          </form>

          </div>

          <script type="text/javascript">

          function sum(){

          var resultValue,firstValue,secondValue;

          firstValue = parseFloat(document.myform.first.value);

          secondValue = parseFloat(document.myform.second.value);

          resultValue = parseFloat(firstValue + secondValue);

          document.myform.result.value = resultValue;

          }

          </script>

          </body>

          </html>

          Chrome瀏覽器呈現:

          HTML,Hyper Text Markup Language,就其字面理解,其核心是"Markup“(標記),通過“標記”,讓將文本、圖片、音頻、視頻等諸多元素呈現“超文本”(HyperText)的特點。

          CSS,Cascading Style Sheets,就其字面理解,其核心是“Style“,也就是”樣式“。就像我們做Word文檔一樣,對文本進行格式化。但在網頁設計中,樣式是通過“屬性:屬性值“的代碼來表示,且這些“樣式”可以疊加,對對象的樣式描述可以列成序列的形式;

          JavaScript,是一種網頁腳本語言,通過網頁中的一些事件能引發一些代碼的執行。

          最好的參考網站或查詢頁面:http://www.w3school.com.cn/index.html

          們從學校里了解到過很多運算符,比如說加號 +、乘號 *、減號 - 等。

          在本章中,我們將從簡單的運算符開始,然后著重介紹 JavaScript 特有的方面,這些是在學校中學習的數學所沒有涵蓋的。

          術語:“一元運算符”,“二元運算符”,“運算元”

          在正式開始前,我們先簡單瀏覽一下常用術語。

          • 運算元 —— 運算符應用的對象。比如說乘法運算 5 * 2,有兩個運算元:左運算元 5 和右運算元 2。有時候人們也稱其為“參數”而不是“運算元”。
          • 如果一個運算符對應的只有一個運算元,那么它是 一元運算符。比如說一元負號運算符(unary negation)-,它的作用是對數字進行正負轉換:
          • let x = 1; x = -x; alert( x ); // -1,一元負號運算符生效
          • 如果一個運算符擁有兩個運算元,那么它是 二元運算符。減號還存在二元運算符形式:
          • let x = 1, y = 3; alert( y - x ); // 2,二元運算符減號做減運算
          • 嚴格地說,在上面的示例中,我們使用一個相同的符號表征了兩個不同的運算符:負號運算符,即反轉符號的一元運算符,減法運算符,是從另一個數減去一個數的二元運算符。

          數學

          支持以下數學運算:

          • 加法 +,
          • 減法 -,
          • 乘法 *,
          • 除法 /,
          • 取余 %,
          • 求冪 **.

          前四個都很簡單,而 % 和 ** 則需要說一說。

          取余 %

          取余運算符是 %,盡管它看起來很像百分數,但實際并無關聯。

          a % b 的結果是 a 整除 b 的 余數)。

          例如:

          alert( 5 % 2 ); // 1,5 除以 2 的余數
          alert( 8 % 3 ); // 2,8 除以 3 的余數

          求冪 **

          求冪運算 a ** b 將 a 提升至 a 的 b 次冪。

          在數學中我們將其表示為 ab。

          例如:

          alert( 2 ** 2 ); // 22 = 4
          alert( 2 ** 3 ); // 23 = 8
          alert( 2 ** 4 ); // 2? = 16

          就像在數學計算中一樣,冪運算也適用于非整數。

          例如,平方根是指數為 ? 的冪運算:

          alert( 4 ** (1/2) ); // 2(1/2 次方與平方根相同)
          alert( 8 ** (1/3) ); // 2(1/3 次方與立方根相同)

          用二元運算符 + 連接字符串

          我們來看一些學校算術未涉及的 JavaScript 運算符的特性。

          通常,加號 + 用于求和。

          但是如果加號 + 被應用于字符串,它將合并(連接)各個字符串:

          let s = "my" + "string";
          alert(s); // mystring

          注意:只要任意一個運算元是字符串,那么另一個運算元也將被轉化為字符串。

          舉個例子:

          alert( '1' + 2 ); // "12"
          alert( 2 + '1' ); // "21"

          你看,第一個運算元和第二個運算元,哪個是字符串并不重要。

          下面是一個更復雜的例子:

          alert(2 + 2 + '1' ); // "41",不是 "221"

          在這里,運算符是按順序工作。第一個 + 將兩個數字相加,所以返回 4,然后下一個 + 將字符串 1 加入其中,所以就是 4 + '1' = '41'。

          alert('1' + 2 + 2); // "122",不是 "14"

          這里,第一個操作數是一個字符串,所以編譯器將其他兩個操作數也視為了字符串。2 被與 '1' 連接到了一起,也就是像 '1' + 2 = "12" 然后 "12" + 2 = "122" 這樣。

          二元 + 是唯一一個以這種方式支持字符串的運算符。其他算術運算符只對數字起作用,并且總是將其運算元轉換為數字。

          下面是減法和除法運算的示例:

          alert( 6 - '2' ); // 4,將 '2' 轉換為數字
          alert( '6' / '2' ); // 3,將兩個運算元都轉換為數字

          數字轉化,一元運算符 +

          加號 + 有兩種形式。一種是上面我們剛剛討論的二元運算符,還有一種是一元運算符。

          一元運算符加號,或者說,加號 + 應用于單個值,對數字沒有任何作用。但是如果運算元不是數字,加號 + 則會將其轉化為數字。

          例如:

          // 對數字無效
          let x = 1;
          alert( +x ); // 1
          
          let y = -2;
          alert( +y ); // -2
          
          // 轉化非數字
          alert( +true ); // 1
          alert( +"" );   // 0

          它的效果和 Number(...) 相同,但是更加簡短。

          我們經常會有將字符串轉化為數字的需求。比如,如果我們正在從 HTML 表單中取值,通常得到的都是字符串。如果我們想對它們求和,該怎么辦?

          二元運算符加號會把它們合并成字符串:

          let apples = "2";
          let oranges = "3";
          
          alert( apples + oranges ); // "23",二元運算符加號合并字符串

          如果我們想把它們當做數字對待,我們需要轉化它們,然后再求和:

          let apples = "2";
          let oranges = "3";
          
          // 在二元運算符加號起作用之前,所有的值都被轉化為了數字
          alert( +apples + +oranges ); // 5
          
          // 更長的寫法
          // alert( Number(apples) + Number(oranges) ); // 5

          從一個數學家的視角來看,大量的加號可能很奇怪。但是從一個程序員的視角,沒什么好奇怪的:一元運算符加號首先起作用,它們將字符串轉為數字,然后二元運算符加號對它們進行求和。

          為什么一元運算符先于二元運算符作用于運算元?接下去我們將討論到,這是由于它們擁有 更高的優先級。

          運算符優先級

          如果一個表達式擁有超過一個運算符,執行的順序則由 優先級 決定。換句話說,所有的運算符中都隱含著優先級順序。

          從小學開始,我們就知道在表達式 1 + 2 * 2 中,乘法先于加法計算。這就是一個優先級問題。乘法比加法擁有 更高的優先級。

          圓括號擁有最高優先級,所以如果我們對現有的運算順序不滿意,我們可以使用圓括號來修改運算順序,就像這樣:(1 + 2) * 2。

          在 JavaScript 中有眾多運算符。每個運算符都有對應的優先級數字。數字越大,越先執行。如果優先級相同,則按照由左至右的順序執行。

          這是一個摘抄自 Mozilla 的 優先級表(你沒有必要把這全記住,但要記住一元運算符優先級高于二元運算符):

          優先級

          名稱

          符號

          15

          一元加號

          +

          15

          一元負號

          -

          14

          求冪

          **

          13

          乘號

          *

          13

          除號

          /

          12

          加號

          +

          12

          減號

          -

          2

          賦值符

          =

          我們可以看到,“一元加號運算符”的優先級是 15,高于“二元加號運算符”的優先級 12。這也是為什么表達式 "+apples + +oranges" 中的一元加號先生效,然后才是二元加法。

          賦值運算符

          我們知道賦值符號 = 也是一個運算符。從優先級表中可以看到它的優先級非常低,只有 2。

          這也是為什么,當我們賦值時,比如 x = 2 * 2 + 1,所有的計算先執行,然后 = 才執行,將計算結果存儲到 x。

          let x = 2 * 2 + 1;
          
          alert( x ); // 5

          賦值 = 返回一個值

          = 是一個運算符,而不是一個有著“魔法”作用的語言結構。

          在 JavaScript 中,所有運算符都會返回一個值。這對于 + 和 - 來說是顯而易見的,但對于 = 來說也是如此。

          語句 x = value 將值 value 寫入 x 然后返回 x。

          下面是一個在復雜語句中使用賦值的例子:

          let a = 1;
          let b = 2;
          
          let c = 3 - (a = b + 1);
          
          alert( a ); // 3
          alert( c ); // 0

          上面這個例子,(a = b + 1) 的結果是賦給 a 的值(也就是 3)。然后該值被用于進一步的運算。

          有趣的代碼,不是嗎?我們應該了解它的工作原理,因為有時我們會在 JavaScript 庫中看到它。

          不過,請不要寫這樣的代碼。這樣的技巧絕對不會使代碼變得更清晰或可讀。

          鏈式賦值(Chaining assignments)

          另一個有趣的特性是鏈式賦值:

          let a, b, c;
          
          a = b = c = 2 + 2;
          
          alert( a ); // 4
          alert( b ); // 4
          alert( c ); // 4

          鏈式賦值從右到左進行計算。首先,對最右邊的表達式 2 + 2 求值,然后將其賦給左邊的變量:c、b 和 a。最后,所有的變量共享一個值。

          同樣,出于可讀性,最好將這種代碼分成幾行:

          c = 2 + 2;
          b = c;
          a = c;

          這樣可讀性更強,尤其是在快速瀏覽代碼的時候。

          原地修改

          我們經常需要對一個變量做運算,并將新的結果存儲在同一個變量中。

          例如:

          let n = 2;
          n = n + 5;
          n = n * 2;

          可以使用運算符 += 和 *= 來縮寫這種表示。

          let n = 2;
          n += 5; // 現在 n = 7(等同于 n = n + 5)
          n *= 2; // 現在 n = 14(等同于 n = n * 2)
          
          alert( n ); // 14

          所有算術和位運算符都有簡短的“修改并賦值”運算符:/= 和 -= 等。

          這類運算符的優先級與普通賦值運算符的優先級相同,所以它們在大多數其他運算之后執行:

          let n = 2;
          
          n *= 3 + 5;
          
          alert( n ); // 16 (右邊部分先被計算,等同于 n *= 8)

          自增/自減

          對一個數進行加一、減一是最常見的數學運算符之一。

          所以,對此有一些專門的運算符:

          • 自增 ++ 將變量與 1 相加:
          • let counter = 2; counter++; // 和 counter = counter + 1 效果一樣,但是更簡潔 alert( counter ); // 3
          • 自減 -- 將變量與 1 相減:
          • let counter = 2; counter--; // 和 counter = counter - 1 效果一樣,但是更簡潔 alert( counter ); // 1

          重要:

          自增/自減只能應用于變量。試一下,將其應用于數值(比如 5++)則會報錯。

          運算符 ++ 和 -- 可以置于變量前,也可以置于變量后。

          • 當運算符置于變量后,被稱為“后置形式”:counter++。
          • 當運算符置于變量前,被稱為“前置形式”:++counter。

          兩者都做同一件事:將變量 counter 與 1 相加。

          那么它們有區別嗎?有,但只有當我們使用 ++/-- 的返回值時才能看到區別。

          詳細點說。我們知道,所有的運算符都有返回值。自增/自減也不例外。前置形式返回一個新的值,但后置返回原來的值(做加法/減法之前的值)。

          為了直觀看到區別,看下面的例子:

          let counter = 1;
          let a = ++counter; // (*)
          
          alert(a); // 2

          (*) 所在的行是前置形式 ++counter,對 counter 做自增運算,返回的是新的值 2。因此 alert 顯示的是 2。

          下面讓我們看看后置形式:

          let counter = 1;
          let a = counter++; // (*) 將 ++counter 改為 counter++
          
          alert(a); // 1

          (*) 所在的行是后置形式 counter++,它同樣對 counter 做加法,但是返回的是 舊值(做加法之前的值)。因此 alert 顯示的是 1。

          總結:

          • 如果自增/自減的值不會被使用,那么兩者形式沒有區別:
          • let counter = 0; counter++; ++counter; alert( counter ); // 2,以上兩行作用相同
          • 如果我們想要對變量進行自增操作,并且 需要立刻使用自增后的值,那么我們需要使用前置形式:
          • let counter = 0; alert( ++counter ); // 1
          • 如果我們想要將一個數加一,但是我們想使用其自增之前的值,那么我們需要使用后置形式:
          • let counter = 0; alert( counter++ ); // 0

          自增/自減和其它運算符的對比

          ++/-- 運算符同樣可以在表達式內部使用。它們的優先級比絕大部分的算數運算符要高。

          舉個例子:

          let counter = 1;
          alert( 2 * ++counter ); // 4

          與下方例子對比:

          let counter = 1;
          alert( 2 * counter++ ); // 2,因為 counter++ 返回的是“舊值”

          盡管從技術層面上來說可行,但是這樣的寫法會降低代碼的可閱讀性。在一行上做多個操作 —— 這樣并不好。

          當閱讀代碼時,快速的視覺“縱向”掃描會很容易漏掉 counter++,這樣的自增操作并不明顯。

          我們建議用“一行一個行為”的模式:

          let counter = 1;
          alert( 2 * counter );
          counter++;

          位運算符

          位運算符把運算元當做 32 位整數,并在它們的二進制表現形式上操作。

          這些運算符不是 JavaScript 特有的。大部分的編程語言都支持這些運算符。

          下面是位運算符:

          • 按位與 ( & )
          • 按位或 ( | )
          • 按位異或 ( ^ )
          • 按位非 ( ~ )
          • 左移 ( << )
          • 右移 ( >> )
          • 無符號右移 ( >>> )

          這些運算符很少被使用,一般是我們需要在最低級別(位)上操作數字時才使用。我們不會很快用到這些運算符,因為在 Web 開發中很少使用它們,但在某些特殊領域中,例如密碼學,它們很有用。當你需要了解它們的時候,可以閱讀 MDN 上的 位操作符 章節。

          逗號運算符

          逗號運算符 , 是最少見最不常使用的運算符之一。有時候它會被用來寫更簡短的代碼,因此為了能夠理解代碼,我們需要了解它。

          逗號運算符能讓我們處理多個語句,使用 , 將它們分開。每個語句都運行了,但是只有最后的語句的結果會被返回。

          舉個例子:

          let a = (1 + 2, 3 + 4);
          
          alert( a ); // 7(3 + 4 的結果)

          這里,第一個語句 1 + 2 運行了,但是它的結果被丟棄了。隨后計算 3 + 4,并且該計算結果被返回。

          逗號運算符的優先級非常低

          請注意逗號運算符的優先級非常低,比 = 還要低,因此上面你的例子中圓括號非常重要。

          如果沒有圓括號:a = 1 + 2, 3 + 4 會先執行 +,將數值相加得到 a = 3, 7,然后賦值運算符 = 執行 a = 3,然后逗號之后的數值 7 不會再執行,它被忽略掉了。相當于 (a = 1 + 2), 3 + 4。

          為什么我們需要這樣一個運算符,它只返回最后一個值呢?

          有時候,人們會使用它把幾個行為放在一行上來進行復雜的運算。

          舉個例子:

          // 一行上有三個運算符
          for (a = 1, b = 3, c = a * b; a < 10; a++) {
           ...
          }

          這樣的技巧在許多 JavaScript 框架中都有使用,這也是為什么我們提到它。但是通常它并不能提升代碼的可讀性,使用它之前,我們要想清楚。

          任務

          后置運算符和前置運算符

          重要程度: 5

          以下代碼中變量 a、b、c、d 的最終值分別是多少?

          let a = 1, b = 1;
          
          let c = ++a; // ?
          let d = b++; // ?

          解決方案

          賦值結果

          重要程度: 3

          下面這段代碼運行完成后,代碼中的 a 和 x 的值是多少?

          let a = 2;
          
          let x = 1 + (a *= 2);

          解決方案

          類型轉換

          重要程度: 5

          下面這些表達式的結果是什么?

          "" + 1 + 0
          "" - 1 + 0
          true + false
          6 / "3"
          "2" * "3"
          4 + 5 + "px"
          "$" + 4 + 5
          "4" - 2
          "4px" - 2
          "  -9  " + 5
          "  -9  " - 5
          null + 1
          undefined + 1
          " \t \n" - 2

          好好思考一下,把它們寫下來然后和答案比較一下。

          解決方案

          修正加法

          重要程度: 5

          這里有一段代碼,要求用戶輸入兩個數字并顯示它們的總和。

          它的運行結果不正確。下面例子中的輸出是 12(對于默認的 prompt 的值)。

          為什么會這樣?修正它。結果應該是 3。

          let a = prompt("First number?", 1);
          let b = prompt("Second number?", 2);
          
          alert(a + b); // 12

          解決方案

          原因是 prompt 以字符串的形式返回用戶的輸入。

          所以變量的值分別為 "1" 和 "2"。

          let a = "1"; // prompt("First number?", 1);
          let b = "2"; // prompt("Second number?", 2);
          
          alert(a + b); // 12

          我們應該做的是,在 + 之前將字符串轉換為數字。例如,使用 Number() 或在 prompt 前加 +。

          例如,就在 prompt 之前加 +:

          let a = +prompt("First number?", 1);
          let b = +prompt("Second number?", 2);
          
          alert(a + b); // 3

          或在 alert 中:

          let a = prompt("First number?", 1);
          let b = prompt("Second number?", 2);
          
          alert(+a + +b); // 3

          在最新的代碼中,同時使用一元和二元的 +??雌饋砗苡腥ぃ皇菃??


          主站蜘蛛池模板: 一区二区三区高清| 精品国产一区二区三区无码| 一区二区三区四区在线观看视频 | 中文字幕乱码一区二区免费| 波多野结衣精品一区二区三区| 精品国产免费观看一区| 亚洲福利一区二区精品秒拍| 好爽毛片一区二区三区四| 国产综合一区二区| 亚洲AV噜噜一区二区三区| 99精品一区二区三区无码吞精| 韩国福利一区二区美女视频| 一区二区三区免费在线视频| 狠狠色婷婷久久一区二区三区| 国产91久久精品一区二区| 天天爽夜夜爽人人爽一区二区| 秋霞午夜一区二区| 中文字幕一区二区日产乱码| 国产自产对白一区| 精品人无码一区二区三区| 一区二区三区久久精品| 日本国产一区二区三区在线观看| 国产精品一区二区久久不卡 | 97精品一区二区视频在线观看| 日本一区二区三区在线视频| 老熟妇高潮一区二区三区| 精品一区二区三区免费视频| 亲子乱av一区区三区40岁| 无码精品一区二区三区在线| 国产一区二区在线观看app| 国产伦精品一区二区三区免费下载| 亚洲AV综合色区无码一区| 亚洲一区精品伊人久久伊人| 国产在线步兵一区二区三区| 国产精品无码一区二区三区毛片| 中文字幕一区二区区免| 日本一区二区三区中文字幕| 欧美日韩国产免费一区二区三区 | 97久久精品一区二区三区| 国产一区二区电影在线观看| 99精品国产一区二区三区|