摘要:上篇說了一些中數組操作的常見誤區,這次來總結一下初學者常見的其他易錯點。小心它的精度問題。這就是存在的唯一意義。而包括在內所有瀏覽器所以對于日期字符串,請注意字符串中是使用橫杠還是斜杠。考慮到負數時區的問題,不推薦將小時數清零的做法。
上篇說了一些 JS 中數組操作的常見誤區,這次來總結一下初學者常見的其他易錯點。
寫立即執行函數時前置 void立即執行函數(IIFE)在 JS 非常常用,作用就是構造一個函數級的變量作用域。常見的寫法如下:
(function () { // code })();
這樣寫可能會被 JS 理解成為一個函數調用
var a = 1 (function () { // Uncaught TypeError: 1 is not a function })()
從今天改變習慣,這樣寫:
void function () { // code }();
有些人喜歡以 ! 打頭,個人習慣問題。
在 standardjs 規范日益流行的今天,忽略行尾分號成為了主流(但是筆者不喜歡),更要改變這個習慣
注:standardjs 本身禁止行首括號(https://standardjs.com/readme...)
檢查一個變量是否為對象之前,首先判斷其值是否為 null雖然不愿承認,JS 標準說:
typeof null === "object" // true
毋庸置疑的,null 不具備作為對象類型的基本特征,是原始類型。這是一個廣為人知的 JS 的 bug,,它從 JS 誕生開始就存在,從未、而且永遠不會被修復
我們不必去探究它的黑歷史,但是我們寫代碼時判斷一個變量的類型時,首先需要判斷它是否為 null
if (someVal !== null && typeof someVal === "object") { // someVal 是一個對象 }做數值計算時,注意 JS 數值類型的精度
在 JS 里,所有的 number 原始值都是一個雙精度浮點數,對應 Java 的 double 類型,對應標準 IEEE754。小心它的精度問題。
做整數處理時,注意數值的大小JS 最大可存儲的安全整數(不存在精度問題)為 9007199254740991 (16位,Number.MAX_SAFE_INTEGER ),注意比 Java 的 long 類型最大整數 9223372036854775807 (19位) 小幾個數量級,所以有時 JS 的 number 類型是不能精確存儲 Java 的整數的(當然通常情況下不是問題)。
問題通常出在前后端數據傳輸上。數據庫中的主鍵通常是一個自增長的長整型數,有可能會超出 JS 的安全整數范圍,這時請考慮使用字符串傳輸。
做小數計算時,注意浮點數的精度問題例如:0.1+0.2 => 0.30000000000000004,0.4-0.3 => 0.10000000000000003
將小數轉化為字符串時,永遠記得使用 toFixed 取小數點后若干位數字:
(0.1 + 0.2).toFixed(2) === "0.30"
比較小數相等時,切記不要直接使用 ===,而要使用相減取絕對值的方式(表示兩數相差在一定范圍內即認為他們相等)。
0.1+0.2 === 0.3 // false Math.abs(0.1+0.2 - 0.3) <= 1e-10 // trueNaN !== NaN
NaN 之所以 NB,因為它有一個獨一無二的特性。對!獨一無二!那就是:
NaN === NaN // false var a = NaN; a === a // false
NaN 不等于它自己。你可以使用這個特性判斷一個變量是否為 NaN,一個變量如果不等于它自己,這個變量一定是 NaN。
還有一個方式是使用 Number.isNaN。注意如果不已知這個變量的類型是數字時,不要使用 isNaN 做判斷,因為 isNaN 有個很詭異的特性:它會先將待判斷的變量轉換為數值類型。
isNaN("abc") // true isNaN("123") // false isNaN("") // false isNaN([]) // false isNaN({}) // true
永遠不要寫 someVal === NaN
正確使用 parseInt首先parseInt接受兩個參數,第一個參數為待parse的字符串(如果不是字符串則會首先轉換為字符串);第二個參數為使用的進制數。
如果不傳第二個參數,則進制由第一個參數決定。什么意思呢?比如以 0x 開頭的字符串,會被解析為16進制數。
我們知道以數字 0 開頭的數字為8進制數(非嚴格模式),比如 011 === 9,0 本身也是8進制數。那么問題來了, parseInt("011") = ?
答案是看瀏覽器。目前絕大多數瀏覽器都會作為10進制數解析,結果為11。但是還有一些老舊的瀏覽器以8進制數解析(例如IE8和一批老Android瀏覽器)
所以如果你非要用 parseInt:
parseInt 使用規則一:請傳入第二個參數回到 parseInt 本身的含義。顧名思義這個函數是在parse,被parse的一定是個字符串。如果第一個參數不是字符串,那么會首先被轉換為字符串。
問:parseInt(0.0000000008) =?
答:
String(0.0000000008) => "8e-10"
parseInt("8e-10") => 8
自己打開調試器去試
parseInt使用規則二:永遠不要使用parseInt給小數取整建議對于數值轉換一概使用強制轉換函數 Number,如果你JS用6了可以使用 +(正號)。
如果需要對某個數字取整,建議使用 Math.trunc。如果你能確定數值在 32 位以內,可以使用 x | 0 或 ~~x 等方式
parseInt的用處在于轉換一些CSS里帶單位的值:parseInt("10px", 10) => 10。但這里建議使用parseFloat,可以解析小數又沒有進制問題。
除了用于比較 null 或 undefined,永遠不要使用非嚴格相等 ==絕不要簡單的把非嚴格相等 == 理解為兩者表示的數字一樣,它有一套非常復雜的轉換規則:它會先將 %% 轉換為 @@,然后把 !! 轉換為 **,如果 %% 是 ?? 類型,還會 xx 一把……
看不懂對吧,我相信你就算看懂了也記不住的。不然請問:
"true" == true // => false "true" == false // => false [] == {} // => false [] == [] // => false
關于非嚴格相等,你只需要記住這個規則:
null == null // => true undefined == undefined // => true null == undefined // => true undefined == null // => true x == null // => false (x 非 null 或 undefined) x == undefined // => false (x 非 null 或 undefined)
簡言之:
x == null // 或 x == undefined
是最簡單的判斷 x 為 null 或 undefined 的方式,相對應的
x != null // 或 x != undefined
是最簡單的判斷 x 非 null 和 undefined 的方式。這就是 == 存在的唯一意義。
日期處理 new Date(year, month, day) 注意其參數的數值范圍由于可能的歷史傳承原因,JS 內置對象 Date 的構造函數比較特殊。
如果 year 是 0 ~ 99 之間,year 默認加 1900。比如 1 代表公元 1901 年,99 代表公元 1999 年,100 代表公元 100 年。(你問 -1 是幾?公元前 1 年。。。)
month 從 0 開始算。0 代表一月,1 代表二月,以此類推。12 代表下一年的一月(自動進位)
第一點不知道也沒什么,畢竟一般不會操作公元 99 年之前的時間。但第二點就很容易出錯,切記它是以 0 開始的數字。
這樣得到的日期對象是本地時間(采用客戶端時區)
new Date(dateString) 注意瀏覽器時區問題以及瀏覽器兼容性時常有后端接口返回一個日期字符串的情況:
new Date("2018-01-01") // => "2018/1/1 08:00:00" 新版瀏覽器,IE 11 new Date("2018-01-01") // => "2018/1/1 00:00:00" 某些舊版安卓 new Date("2018-01-01") // => "Invalid Date" IE 8(這個忽略。。。)
可以看到,瀏覽器基本都是把日期字符串當做 UTC 時間處理的。而
new Date("2018/01/01") // => "2018/1/1 00:00:00" 包括 IE 8 在內所有瀏覽器
所以對于日期字符串,請注意字符串中是使用橫杠還是斜杠。對于橫杠可以考慮將 - 替換成 /,或者補全完整的帶時區的 ISO8601 字符串。考慮到負數時區的問題,不推薦將小時數清零的做法。
PS:將日期對象取當天 0 點為 date.setHours(0, 0, 0, 0)
PS2:取當前時間的 Unix 時間戳可以 Date.now()
這反而是 JS 老鳥更容易犯的錯誤。給用戶傳入的對象填充默認值是很常見的行為,他們總是隨手就寫:
config.prop1 = config.prop1 || 233; config.prop2 = config.prop2 || "balabala";
expr1 || expr2 的意思是:如果expr1能轉換成true則返回expr1,否則返回expr2
expr1 || expr2 <=> Boolean(expr1) ? expr1 : expr2
哪些值不能轉換為 true 呢?
null
undefined
NaN
0 !!!
空字符串("") !!!
如果用戶指定了傳入參數的值為 0 或者是空字符串的配置項,它的值就會被強制替換為默認值,然而實際上只有 undefined 應該被認為是用戶沒有指定其值(語義上可以這樣理解:null 表示 用戶讓你給他把這個位置空著;而 undefined 表示 用戶沒發表意見)
所以就應該是這樣:
config.prop1 = config.prop1 !== undefined ? config.prop1 : 233; config.prop2 = config.prop2 !== undefined ? config.prop2 : "balabala";
很長。。。你可以搞個全局的函數簡化這一操作,或者考慮使用 lodash 的 defaults 方法
完歡迎補充
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90724.html
摘要:使用遍歷數組有三點問題遍歷順序不固定引擎不保證對象的遍歷順序。作為原生函數,和自身操作字符串的速度是很快的。由于沒有返回值返回,所以它的回調函數通常是包含副作用的,否則這個寫了毫無意義。接受一個回調函數,你可以提前,相當于手寫循環中的。 不要用 for_in 遍歷數組 這是 JavaScript 初學者常見的誤區。for_in 用于遍歷對象中包括原型鏈上的所有可枚舉的(enumerab...
摘要:由于內容較多,計劃分四篇,大致內容分布如下基礎篇介紹基礎。接下來讓我們補全這一部分在第行我們引入了模塊中函數,可以理解為當事件發生時,它會輸出一個消息。我們有了數據,具備行為的視圖,按行為改變數據的邏輯,卻沒有將它們粘合成一個應用。 簡介 Elm 是一門專注于Web前端的純函數式語言。你可能沒聽說過它,但一定聽說過Redux,而Redux的核心reducer就是受到了Elm的啟發。 隨...
摘要:給初學者的印象總是那么的雜而亂,相信很多初學者都在找輕松學習的途徑。通常學了很久的基礎之后,變量函數對象你也都略知一二,但一到公司開發項目的時候,卻又難以下手。 Js給初學者的印象總是那么的雜而亂,相信很多初學者都在找輕松學習Js的途徑。在這里給大家總結一些學習Js的經驗,希望能給后來的學習者探索出一條輕松學習Js之路。Js給人那種感覺的原因多半是因為它如下的特點:A:本身知識很抽象、...
摘要:手把手教你做個人火的時候,隨便一個都能賺的盆滿缽滿,但是,個人沒有服務端,沒有美工,似乎就不能開發了,真的是這樣的嗎秘密花園經典的中文手冊。涵蓋前端知識體系知識結構圖書推薦以及入門視頻教程,全的簡直不要不要的了。 JavaScript 實現點擊按鈕復制指定區域文本 html5 的 webAPI 接口可以很輕松的使用短短的幾行代碼就實現點擊按鈕復制區域文本的功能,不需要依賴 flash。...
摘要:代碼托管這個倉庫。假設現在我們需要實現一個點贊取消點贊的功能。如果你對前端稍微有一點了解,你就順手拈來點贊為了現實當中的實際情況,所以這里特易把這個的結構搞得稍微復雜一些。這里非常暴力地使用了,把兩個按鈕粗魯地插入了當中。 作者:胡子大哈原文鏈接:http://huziketang.com/blog/posts/detail?postId=58aea515204d50674934c3a...
閱讀 1446·2021-09-22 15:43
閱讀 2161·2019-08-30 15:54
閱讀 1162·2019-08-30 10:51
閱讀 2087·2019-08-29 18:35
閱讀 433·2019-08-26 11:58
閱讀 2481·2019-08-26 11:38
閱讀 2439·2019-08-23 18:35
閱讀 3633·2019-08-23 18:33