1. JavaScript程序是用Unicode字符集編寫的.javascript
let s = '你好' // true console.log(s === '你好') // 你好 console.log(s)
2. JavaScript區分大小寫, 而HTML不區分大小寫.(我的推薦命名JS變量, 使用駝峯式命名)java
3. JavaScript會忽略程序中標識之間的空格, 可是良好的代碼風格相當重要.web
4. JavaScript支持"//"和/*...*/兩種註釋, 可是註釋中不可嵌套註釋.正則表達式
5. 直接量: 程序中直接使用的數據值, 可簡單理解爲"直接分配內存地址的變量", 例如數值, 字符串, 布爾型和正則表達式直接量(/javascript/gi).數組
6. JavaScript的標識符必須以字母, 下劃線或者美圓符號開始, 後續跟字母, 數字, 下劃線或者美圓符號.函數
7. JavaScript中關於填補分號的規則: 只要在缺乏了分號就沒法正確解析代碼的時候, JavaScript纔會填補分號. 我的習慣爲不加分號(在ES6的語法下)spa
JavaScript的數據類型分爲兩類: 原始類型和對象類型. JavaScript的原始類型包括數字, 字符串和布爾值. 而對象是屬性的集合, 每一個屬性都由"名/值對"組成.指針
咱們一般會判斷一個變量是否爲數字,字符串,布爾值, 函數或者對象. 最簡單的一個方法是使用typeof:code
// "number" console.log(typeof 1) // "string" console.log(typeof 'hello') const f = () => {} // function console.log(typeof f) // object console.log(typeof [])
但使用typeof沒法判斷數組, 這時候咱們須要使用Array.isArray:對象
// true console.log(Array.isArray([]))
存在一種特殊的狀況, 不管傳進來的參數是什麼, 咱們須要的是一個數值. 這時候通常使用parseInt/parseFloat進行轉換後, 不可以使用typeof來判斷(typeof NaN === "number"), 應該使用isNaN()來判斷是否爲NaN.
而針對對象, 因爲是無序哈希集合, 則工做中常常會碰到以下狀況:
1) 獲取全部的keys: 使用Object.keys():
const dst = { name: 'xx', age: 33, } // ['name', 'age'] console.log(Object.keys(dst))
2) 對對象進行遍歷, 可以使用in, 若是須要對可迭代對象進行變量, 則須要使用of:
function* foo() { yield 1 yield 2 } let f = foo() // 1 // 2 for (let k of f) { console.log(k) }
3) 對一個變量進行深層次的獲取, 可能會寫出這樣的代碼:
dst.country && dst.country.province && dst.country.province.name
這時候, 要麼定義一個函數來獲取, 要麼須要一層層判斷.
JavaScript中有兩個特殊的原始值: null和undefined, 它們不是數字,字符串和布爾值. 它們一般分別表明了各自特殊類型的惟一的成員.原始類型, null和undefined均爲不可變類型.
針對null和undefined, 存在以下的坑:
let a = undefined let b = null a = a + '' b = b + '' // string undefined console.log(typeof a, a) // string null console.log(typeof b, b)
這可能並不是咱們的本意. 實際項目中不多會糾結於null/undefined, 通常將它們當作false便可.
數組是特殊的集合, 它的下標索引即爲key值, 而對象的key爲字符串.
let arr = [11, 22, 33] // 0 -- 11 // 1 -- 22 // 2 -- 33 for (let k in arr) { console.log(k, '--', arr[k]) } // true console.log(arr['1'] === arr[1])
函數是對象, 而箭頭函數的引入, 則方便了函數做爲參數進行使用:
const f1 = (num) => ++num const f2 = (num) => () => f1(num) // 2 console.log(f2(1)())
JavaScript解釋器有本身的內存管理機制, 能夠自動對內存進行垃圾回收.
ES6中引入塊級做用域, 儘可能使用let/const, 放棄var.
let x = 0.3 - 0.2 let y = 0.2 - 0.1 x == y -->false x == 0.1-->false y == 0.1-->true
字符串的使用
let s = "hello world" s.charAt(0) ==> "h": 第一個字符 s.charAt(s.length - 1) ==> "d": 最後一個字符 s.substring(1, 4) ==> "ell": 第2~4個字符 s.slice(1, 4) ==> "ell": 同上 s.slice(-3) ==> "rld": 最後三個字符 s.indexOf("l") ==> 2: 字符l首次出現的位置 s.lastIndexOf("l") ==> 9: 字符l最後出現的位置 s.indexOf("l", 3) ==> 3: 在位置3及以後首次出現字符l的位置. s.split(" ") ==> ["hello", "world"]: 分割字符串 s.replace("h", "H") ==> "Hello world": 替換 s.toUpperCase() ==> "HELLO WORLD": 轉換成大寫
轉換爲false的變量: undefined, null, NaN, 0, -0, ""
在工做中, 常常犯以下的錯誤, 例如判斷一個變量是否爲false:
if (a) {}
但有時候沒考慮到a爲空數組/空對象的狀況. 因此, 針對數組來講, 應該這樣判斷:
if (Array.isArray(a) && a.length === 0) {}
但空對象並很差判斷, 若是咱們僅僅判斷:
if (typeof a === 'object' && Object.keys(a).length === 0) {}
須要考慮到萬一a繼承了某個類的屬性怎麼辦? 因此更好的方法應該判斷某個屬性是否在a中:
if ('name' in a) {}
null表明空指針, 一般用來表示數字, 字符串和對象的"無值狀態"
undefined表明未初始化.
全局屬性: 好比undefined, Infinity和NaN
全局函數: 好比isNaN(), parseInt()和eval()
構造函數: 好比Date(), RegExp(), String(), Object()和Array()
全局對象: 好比Math和JSON
對於字符串, 如下代碼是正確的:
let s = "hello world" let word = s.substring(1, 4)
既然字符串不是對象, 它爲何會有substring方法呢? 由於引用字符串s的屬性, JavaScript就會將字符串經過調用new String(s)的方式裝換成對象, 一旦屬性引用結束, 這個新建立的對象就會銷燬(同理於Number()和Boolean()):
let s = "test" s.len = 4 let t = s.len t ==> undefined
而:
"hello" == new String("hello") ==> true "hello" === new String("hello") ==> false
原始值: undefined, null, 數字, 布爾值, 字符串. 它們均不可改變.
對象: 數組和函數, 可改變.
比較兩個變量, 除非特地, 不然儘可能使用"==="來進行比較. 而對象的比較毫無心義.
let a = 1 let b = '1' // true console.log(a == b) // false console.log(a === b)
對象的引用是一個大問題, 例如咱們可能會寫以下的代碼:
let arr = [1, 2] let b = arr b.push(3) // [1, 2, 3] console.log(arr)
咱們須要的是一個副本, 而非引用. 這時候, 應該使用Object.assign:
let arr = [1, 2] let b = Object.assign([], arr) b.push(3) // [1, 2 ] console.log(arr)
JavaScript的類型轉換本質是: 解釋器須要什麼類型, 則將根據須要將變量轉換爲其類型.
值 | 字符串 | 數字 | 布爾值 | 對象 |
undefined null |
"undefined" "null" |
NaN 0 |
false false |
throws TypeError throws TypeError |
true false |
"true" "false" |
1 0 |
new Boolean(true) new Boolean(false) |
|
"" "1.2" "one" |
0 1.2 NaN |
false true true |
new String("") new String("1.2") new String("one") |
|
0 -0 NaN Infinity -Infinity 1 |
"0" "0" "NaN" "Infinity" "-Infinity" "1" |
false false false true true true |
new Number(0) new Number(-0) new Number(NaN) new Number(Infinity) new Number(-Infinity) new Number(1) |
|
{} [] [9] ['a'] function(){} |
後面解釋 "" "9" 使用join方法 後面解釋 |
後面解釋 0 9 NaN NaN |
true true true true true |
轉換和相等性
進行"=="判斷時, JavaScript會進行類型轉換.
null == undefined ==> true "0" == 0 ==> true
這裏類型轉換表明的意思是: a == b, 則a轉換爲b類型, 或者b轉換爲a類型, 再次進行比較. 因此對於null == undefined, 本質上是undefined轉換爲一個Object, 而後在和null進行比較.
而"0" == 0, 是將數字0轉換爲字符串"0", 而後再進行比較.
但能夠成功進行類型轉換, 不必定表示它們相等, 如undefined可轉換爲false, 但undefined == false的結果爲false.
在比較時候, 儘可能使用"==="而非"==".
顯示類型轉換
JavaScript在須要字符串狀況下, 會將變量轉換爲字符串; 其次, 在須要數字狀況下, 會將變量轉換爲數字.
Number類定義的toString()方法能夠接收表示轉換基數的可選參數. 若是不指定此參數, 轉換規則將是基於十進制:
let n = 17 n.toString() ==> "17" n.toString(2) ==> "10001" n.toString(8) ==> "21" n.toString(16) ==> "11"
toFixed(): 根據小數點後的指定位數將數字轉換爲字符串, 它從不使用指數計數法.
toExponential(): 使用指數計數法將數字轉換爲指數形式的字符串, 其中小數點前只有一位, 小數點後的位數則由參數指定.
toPrecision(): 根據指定的有效數字位數將數字轉換成字符串. 若是有效數字的位數少於數字部分的位數, 則轉爲爲指數形式.
let n = 123456.789 n.toFixed(0) ==> "123457" n.toFixed(2) ==> "123456.79" n.toFixed(5) ==> "123456.78900" n.toExponential(1) ==> "1.2e+5" n.toExponential(3) ==> "1.235e+5" n.toPrecision(4) ==> "1.235e+5" n.toPrecision(7) ==> "123456.8" n.toPrecision(10) ==> "123456.7890"
parseInt(): 儘量的將字符串轉換爲整數, 可接收第二個可選參數, 這個參數指定數字轉換的基數.
parseFloat(): 儘量的將字符串轉換爲浮點數.
對象轉換爲原始值
toString(): 返回一個反映這個對象的字符串.
valueOf(): 若是存在任意原始值, 它就默認將對象轉換爲表示它的原始值.
JavaScript中對象到字符串的轉換經歷如下步驟:
對象到數字的轉換經歷如下步驟:
因爲ES6中class的引入, 再也不使用函數當作一個對象來建立實例了. 而函數僅僅單純起到函數的做用, 而且將函數當作一個變量進行調用:
const func = () => console.log('hello world') func()
若是存在相似class的需求, 例如用到繼承, 實例等, 可考慮引入class:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes
1. JavaScript運算符一般會根據操做數進行類型轉換, 因此"3" * "5"是合法的, 爲數字15.
若是想獲取一個數組的最大值, 最小值和平均值, 有個通用的寫法爲:
const arr = ['1', '3', 2, '44', 5, '222'] const max = arr.reduce((x, y) => x - y > 0 ? x : y) const min = arr.reduce((x, y) => x - y > 0 ? y : x) const avg = arr.reduce((x, y) => parseInt(x) + parseInt(y)) / arr.length // 222 1 46.17 console.log(max, min, avg.toFixed(2))
備註: web開發中常常遇到字符串型數值.
這裏之因此使用x - y > 0是由於"-"會進行數值運算.
2. 一般使用"+"來將數組轉換爲字符串, 或者將字符串數值轉換爲數值:
let arr = [1, 2, 3] // 1,2,3 console.log(arr + '') // number console.log(typeof +"3")
3. in用於判斷屬性是否存在與對象實例+原型中:
let point = { x: 1, y: 2, } // true console.log('x' in point) // true console.log('toString' in point) // false console.log('xx' in point)
4. instanceof用於判斷左邊對象是否爲右邊類的實例.
const d = new Date() // true console.log(d instanceof Date) // true console.log(d instanceof Object) // false console.log(d instanceof RegExp)
5. typeof運算符用於判斷對象的類型:
x |
typeof x |
undefined |
"undefined" |
null |
"object" |
true或false |
"boolean" |
任意數字或NaN | "number" |
任意字符串 | "string" |
任意函數 | "function" |
任意內置對象(非函數) | "object" |
任意宿主對象 | 由編譯器自身決定 |
6. delete用於刪除一個對象的屬性, 對數組來講至關於賦值undefined:
let o = {x: 1, y:2} delete o.x o ==> Object {y: 2} let arr = [11, 12, 13] delete arr[1] arr ==> [11, undefined × 1, 13]