javascript提高篇


本章簡介

本章內容比較少,有三個分享的知識。你可能都看過了,因為網上也有很多提問和解答,如果沒看過或者沒搞懂,你可以再看看這篇文章。

1. 數組去重方法的演變    --  走向代碼縮短化

2. [] + {} 和 {} + []的返回結果   -- js的代碼規范及隱士類型轉換

3. ++ [[]][+[]] 的運算   -- 還是++問題

講解部分

數組去重方法的演變

1. es5以前:

es5以前我們數組去重的方法顯得有點笨笨的,我的需要創建一個新數組和一個緩存對象,遍歷原來數組,一個個的push到新數組中,如果新數組有當前的元素,就不加了。

var testArray = [1,1,5,76,9,3,2,7,99,3,'a','a']

    var resultArray = null

    function uniqueArray (arr) {
      var newArray = []
      var cache = {}
      var item;
      for (var i = 0; i < arr.length; i++) {
        item = arr[i]
        if (!cache[item] ) {   //  如果緩存中沒有記錄當前元素,意味着新數組中沒有這個元素,可以添加
          cache[item] = 1
          newArray.push(item)
        }
      }
      return newArray;
    }
   // 毫無疑問,去重了,這里就不展示了
    console.log(uniqueArray(testArray)) 

2. es5時代

試問,es5時代來了,你還在用這樣的方法么,答案肯定是不用了,我們該怎么辦呢,用filter方法

resultArray = testArray.filter(function (item, index, arr) {
      return index === arr.indexOf(item)
    })
    // 成功
    console.log(resultArray)

filter方法是es5中對數組新添加的方法,此方法用來過濾return 為 true的。回調函數接收3個參數,分別是當前元素、當前下標、當前數組(相當於this),代碼中我們用arr.indecOf這個es5的方法來取到當前元素的下標再與index比較,達到了過濾重復元素的效果,看以下簡單過程

var arr = [1,2,1]
var arr2 = arr.filter(function (item, index, arr) {
  return index === arr.indexOf(item)
}}

// 以下 = 並未賦值,是數學上的等於意思
// 第一個元素 1: item = 1, index = 0, arr.indexOf(1) = 0,成功加入新數組
// 第二個元素 2: item = 2, index = 1, arr.indexOf(2) = 1, 成功加入新數組
// 第三個元素 1: item = 1, index = 2 , arr.indexOf(1) = 0 ,這里發現indexOf得到的下標並不是2,因為indexOf查找到匹配元素就返回,所以這個元素在之前出現過,因此被屏蔽了。
//最終arr2 = [1,2]

3. es6的問世

es6的出現帶來了許多方便的方法,博主也沒有仔細看es6的文檔,這里介紹兩個演變過程。

1). 箭頭函數

resultArray = testArray.filter((item, index, arr) => index === arr.indexOf(item))
//    成功
console.log(resultArray)

箭頭函數在一定程度上減少了我們的代碼量,因此我們可以更簡潔的完成es5方法的代碼。但這並不是最優的

2). Set結構

Set結構可以接收一個數組,然后把它變成Set表,它會自動屏蔽數組中重復的元素,實現自動過濾

resultArray = [...new Set(testArray)]
// ok
console.log(resultArray)

我們把數組傳入Set中,創建一個Set實例,這樣就自動完成了過濾,但是這樣還不是數組,我們得再把Set結構轉化為數組,這就用到了es6中的解構賦值,如上。詳情可以看阮一峰老是的es6入門系列。

總結: javascript在不斷的變化,不斷的成熟,將來會有更多的實用函數提供給我們程序員使用~~~

[] + {} 和 {} + []的運算結果(可以先去試一下)

這個問題是在《你不知道的javascript  中卷》中提出的,書中詳細介紹了他們的區別和原因,大家可以去看一下。

1. [] + {}

 它返回的是    "[object Object]"   ,是這樣一個字符串,很明顯他就是一個原始對象的toString()結果,下面我們來介紹一下原因:

大家都知道在 + 運算符有 數學運算功能也有字符串拼接功能,在這里是字符串拼接,因為 此表達式 []  和 {} 需要轉化為字符串來進行運算,[]轉化為字符串是空字串,{} 轉化為字符串就是  "[object Object]",所以理所當然的得到了這個結果。

2. {} + []

它返回了數字 0 ,這就奇怪了,按照上面的邏輯,它不應該還是返回 "[object Object]"么?答案是非,這里牽扯到{}的運用。

javascript解析是從左到右, 在[] + {}中,解析成漢語就是  空數字+ 空對象。

但是在 {} + []中,javascript不會這樣解析,因為開始一個{},javascript不認為它是一個空對象,而是把它認為是一個空代碼塊,就像 if 后面跟着的{}一樣,所以javascript解析玩空代碼塊{}后面就是 + [] , 很明顯  ,空數組前面一個+,將數組轉化為數字形式,因此得到的結果就是 0

延伸:代碼塊

在javascript語言{}表示一個代碼塊,類似於c語言,代碼塊中可以放任意行的表達式。如:

// if 代碼塊
if (...) {
  // .. 代碼塊中放代碼      
}

// 普通代碼塊,和沒有一樣的結果

{
  var a = 1;  
}
console.log(a) // 1

// let代碼塊,創建一個塊級作用域
{
  left a = 1;
  console.log(a)  // 1
}
console.log(a)  // 報錯

 ++ [[]][+[]]的運算

這個問題網上也有,在stack overflow 有解答,也有人翻譯成了中文,不過我看到解釋並不好理解。我是在nodejs群看到的,進群問題就是這個,現在每一個進群的人都會問為什么這個結果是 1 ,看到這問題無數遍了~~~。這個運算不難,但是你可能想當然的理解了,並沒有真正的明白,如果你並沒有真正的明白,請看這一節。

首先 [+[]]中  + [] 的結果 是 0 ,沒有疑問吧,

[[]][0] 這不就是取一個數組的第一個元素么? 然后我們運算出來得到[]

現在變成了  ++ [], 糟糕!報錯了,為什么,因為 ++ 不能直接對一個值進行,他需要用變量來做個中轉站。之前基礎篇已經講過++了,這里再次深入一下。

var a = 1;

a++ // 1

1++ //報錯,左值無效

 以游戲模式通過計算路線圖講解原因:

 a++ , a角色的丹田內原先有1點經驗,他又吃了1點經驗的經驗丹, 這樣a角色丹田升級為2點經驗。

 1++, 同樣的 某個角色丹田有1點經驗,這個角色背包游1點經驗的經驗丹,但是角色沒有吃,那么它的丹田依舊1點經驗,丹田1 + 背包經驗丹1沒有結果,所以報錯,他們只是兩量存在並沒有權利升級。

結論: ‘值’ 不能作用於 ++, 因為他們無法變化, 1數字存在於一個內存中, 2數字存在於另一個內存, 1++ 不能將自身內存中的1變為2,數組也一樣。

然而變量則是引用了值的量詞,變量 ++ ,是 在變量+ 1 的前提下,使變量升級引用比原先值大1的值。

好,++ [] 在這里 也是 []只是個值,並不是個變量,想給自己升級一下,是不可能的,引擎會報錯。這個運算流程終結。看正確的流程。

++ [[]][0] 這個體系,是一體的,看下面的問答:

問: [[]][0] 是不是等於 [] 這個值?

答: 是

問: 上面示例a++ 中  a 是不是等於 1 這個值?

答: 是

問: 那么,將a這個變量變成他引用的值也就是1, ++1成立么?

答: 不成立,報錯

問: 既然這樣,為啥 ++ [[]][0] 你不能當成 一體計算,非要先算 [[]][0]呢, a引用了1, 你算 a++, [[]][0] 只是換了個方式引用[],為啥你非要算++ [],而不是++ [[]][0] 

答: 哦,我明白了,這個 [[]][0] 和 a是一樣的,都是引用了一個值,然后自增1.所以他的結果就是空數組自增1,空數組轉化為Number是0,自增1就等於1了。

問答完了,你應該也懂了吧,廢話很多,是因為更詳細的介紹出來。

到這里,善於嘗試的同學可能會有了一個問題:我在谷歌控制台執行  1 = 1+ 1報錯, 但是 [] = [] + 1為啥沒報錯返回了'1'

那我只能說你很好學,很喜歡動手。

這個問題是為什么呢?那是因為es6的緣故,es6的解構賦值語法,使得[] 在左側成為了一個合法的值。不信你在其他瀏覽器試試。

解構賦值也很簡單: 

[a, b] = [1,2]
a //1
b // 2

//也可以用字符串

[c,d] = '12'

c //1
d// 2

明白這個問題后,再看  [] = [] + 1, 右邊 [] 會變成字符串'', 理所當然得到了 '1', 左邊是空的數組,僅僅是沒有賦值變量而已,整個表達式返回的就是右邊的值‘1’。

 結語

語言組織能力差,可能有些地方的語句很糟糕,諒解。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM