數組的擴展
1.Array.from()
Array.from方法用于將兩類對象轉為真正的數組:類似數組的對象(array-like object:本質特征只有一點,即必須有length屬性)和可遍歷(iterable)的對象
實際應用中類似數組的對象式DOM操作返回的NodeList集合,以及函數內部的arguments對象,有點難以理解吧,請看實例
下面這張圖片說明,字符串和Set結構都具有Iterator(可遍歷)接口,因此可以被Array.from轉化為真正的數組
對于還沒有部署該方法的瀏覽器,可以用Array.prototype ,slice方法替代
Array.from還可以接受第二個參數,作用類似于數組的map方法,用來對每個元素進行處理,就昂處理后的值放入返回的數組
Array.from()的另一個應用是,將字符串轉為數組,然后返回字符串的長度。因為它能正確處理各種Unicode字符,可以避免js將大于\uFFFF的Unicode字符算作兩個字符的bug
2、Array.of()
Array.of()方法用于將一組值,轉換為數組
Array.of基本上可以用來替代Array()或new Array(),并且不存在由于參數不同而導致的重載
3、數組實例的copyWithin(),它的作用是將指定位置的成員復制到其他位置(會覆蓋原有成員),然后返回當前數組。也就是說,使用這個方法,會修改當前數組
它接收三個參數
-target 必需(從該誒之開始替換數據)
-start (可選):從該位置開始讀取數據,默認為0,負數表示倒數
-end(可選):到該位置前停止讀取數據,默認等于數組長度。
4、數組實例的find()和findIndex()
數組find()用于找出第一個符合條件的數組成員,它的參數是一個回調函數,所有數組成員依次執行該回調函數,直到找出第一個返回值為true的成員,然后返回該成員。如果沒有符合條件的成員,則返回undefined
find方法的回調函數可以接受三個參數,依次為當前的值value、當前的位置index和原數組arr
findIndex與find()方法非常類似,返回第一個符合條件的數組成員的位置,如果所有的成員都不符合條件,則返回-1
這兩方法都可以發現NaN,彌補了數組的IndexOf方法的不足
5、數組的實例fill()
fill方法使用給定值,填充一個數組
fill方法還可以接受第二個和第三個參數,用于指定填充的起始位置和結束位置
6、數組實例的entries、keys()、values()
這三個新的方法都返回一個遍歷器對象,它們的區別keys()是對鍵名的遍歷,entries()是對鍵值對的遍歷,values是對鍵值的遍歷
7、數組實例的includes()
Array.prototype.includes方法返回一個布爾值,表示某個數組是否包含給定的值,與字符串的includes方法類似
沒有該方法之前,我們通常使用數組的indexof方法,檢查是否包含某個值。但是indexof有兩個缺點,一是不夠語義化,而是,它內部使用楊哥相等運算符(===)進行判斷,這會導致對NaN的誤判
8、數組的空位
數組的空位值,數組的某一個位置沒有任何值。空位不是undefined,一個位置的值等于undefined,依然是有值的。空位時沒有任何值,in運算符可以說明這一點
函數的擴展
參數已經聲明,所以不能再用let或者const再次聲明
函數的length屬性
指定了默認值以后,函數的length屬性,將返回沒有指定默認值得參數的個數,也就是說,指定了默認值參數,length屬性將失真
如果設置了默認值得參數不是尾參數,那么length屬性也不再計入后面的參數了
作用域
一旦設置了參數的默認值,參數會形成一個單獨的作用域,等到初始化結束,這個作用域就會消失(如果不設置參數默認值,是不會出現的)
如果參數的默認值是一個函數,該函數的作用域也遵守這個規則
注意下區別
reset函數(形式為“...”變量名)
它的作用是獲取函數的多余參數,這樣就不需要使用arguments對象了,rest參數搭配的變量是一個數組,該變量將多余的參數放入數組中
rest參數中的變量代表一個數組(...變量名)好奇怪的寫法
注意reset參數之后不能再有其他參數(即只能是最后一個參數),否則會報錯
函數lenght屬性,不包括rest參數
擴展運算符(spread...)
它的作用好比reset參數的逆運算,將一個數組轉為用逗號分隔的參數序列
這里小結下,reset是多余的參數中放入到數組中,而擴展運算符是將數組轉為用逗號分隔的參數序列
替代數組的apply方法
由于擴展運算符可以展開數組,所以不再需要apply方法,將數組轉為函數的參數了
看看這個例子,之前不明白ES5的寫法為什么一定要加上apply的方法,現在明白了,是因為push方法的參數不能是數組,所以只好通過apply方法變通使用push方法
擴展運算符的應用
1)合并數組
2)與解構賦值結合
擴展運算符用于數組賦值,只能放在參數的最后一位
3)函數的返回值
擴展運算符可以返回多個值
4)字符串
擴展運算符還可以經字符串轉為真正的數組
5)實現了遍歷接口的對象
var nodelist = document.querySelectorAll('div');
var array = [...nodeList];
但是對于沒有不熟遍歷接口類似數組的對象,可以使用Array.from方法獎arrayLike轉為整整的數組
6)Map和Set結構,Generator函數
反正只要有遍歷接口,都可以使用擴展運算符
name屬性,返回該函數的函數名
注意:1)如果將一個匿名函數賦給一個便令,ES5的name屬性,返回空字符串,而ES6的name屬性會返回實際的函數名
2)如果將一個具名函數賦值給一個變量,則ES5和ES6的那么屬性都返回這個具名函數原本的名字
3)Function構造函數返回的函數實例,那么屬性的值為anonymous,bind返回的函數,name 屬性值會加上bound前綴
箭頭函數
之前我是不太明白這種寫法的,現在一看就明白了,=>這個后面是返回值的意思
如果返回值是一個對象的話,那么使用括號
再看看幾個例子
簡化回調函數
注意點:函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象
setTimeout函數的this指向window,所以結果是21;而setTimeout的參數是一個箭頭函數,this指向函數定義生效時所在的對象(本例是{id:42}),所以結果是42
上面的Timer函數內部設置了兩個定時器,分別使用了箭頭函數和普通函數,前者的this綁定定義所在的作用域(timer函數),后者的this指向運行時所在的作用域(即全局對象)
this指向的固定化,并不是因為箭頭函數內部有綁定this的機制,實際原因是箭頭函數更笨沒有自己的this,導致內部的this就是外層代碼塊的this.正式因為他沒有this,所以也就不能用作構造函數
除了this,arguments\super\new.target在箭頭函數之中也是不存在的,所以當然也不用call()、apply()、bind()這些方法去改變this的指向
綁定this(Es7提出了函數綁定運算符,但是Babel轉碼器已經支持)
函數綁定運算符并排的兩個冒號(::),雙冒號左邊是一個對象,右邊是一個函數,該運算符會自動將左邊的對象,作為上下文環境,綁定到右邊的函數上面
尾調用:是函數式變成的一個重要改變,就是只某個函數的最后一步是調用另一個函數
只有第四種屬于尾部調用,第三種和第五種是一樣的意思