此文包含
數(shù)值的擴(kuò)展
响迂、函數(shù)的擴(kuò)展
热监,總結(jié)了一些我認(rèn)為有可能會(huì)用到的堪置,而去除了一些稍稍復(fù)雜一時(shí)難以去學(xué)習(xí)理解且目前不想去研究去總結(jié)的知識(shí)點(diǎn)呼胚。
一茄唐、數(shù)值的擴(kuò)展
0.二進(jìn)制和八進(jìn)制表示法
ES6 提供了二進(jìn)制和八進(jìn)制數(shù)值的新的寫(xiě)法,分別用前綴
0b
(或0B)和0o
(或0O)表示蝇更。
1.Number.isFinite(), Number.isNaN()
S6 在Number對(duì)象上沪编,新提供了
Number.isFinite()
和Number.isNaN()
兩個(gè)方法呼盆。
Number.isFinite()
用來(lái)檢查一個(gè)數(shù)值是否為有限的(finite),即不是Infinity
漾抬。Number.isNaN()
用來(lái)檢查一個(gè)值是否為NaN
宿亡。
2.Number.parseInt(), Number.parseFloat()
ES6 將全局方法parseInt()和parseFloat(),移植到Number對(duì)象上面纳令,行為完全保持不變挽荠。這樣做的目的,是逐步減少全局性方法平绩,使得語(yǔ)言逐步模塊化圈匆。
3.Number.isInteger()
Number.isInteger()用來(lái)判斷一個(gè)數(shù)值是否為整數(shù)。
4.Math 對(duì)象的擴(kuò)展
0??捏雌、Math.trunc()
Math.trunc
方法用于去除一個(gè)數(shù)的小數(shù)部分跃赚,返回整數(shù)部分。也就是說(shuō)正數(shù)的話相當(dāng)于Math.floor
方法性湿,負(fù)數(shù)的話相當(dāng)于Math.ceil
方法纬傲。
1??、Math.sign()
Math.sign方法用來(lái)判斷一個(gè)數(shù)到底是正數(shù)肤频、負(fù)數(shù)叹括、還是零。對(duì)于非數(shù)值宵荒,會(huì)先將其轉(zhuǎn)換為數(shù)值汁雷。
2??、雙曲函數(shù)方法
ES6 新增了 6 個(gè)雙曲函數(shù)方法报咳。
Math.sinh(x)
返回x的雙曲正弦(hyperbolic sine)
Math.cosh(x)
返回x的雙曲余弦(hyperbolic cosine)
Math.tanh(x)
返回x的雙曲正切(hyperbolic tangent)
Math.asinh(x)
返回x的反雙曲正弦(inverse hyperbolic sine)
Math.acosh(x)
返回x的反雙曲余弦(inverse hyperbolic cosine)
Math.atanh(x)
返回x的反雙曲正切(inverse hyperbolic tangent)
5.指數(shù)運(yùn)算符
ES2016 新增了一個(gè)指數(shù)運(yùn)算符()侠讯,需要注意的是:這個(gè)運(yùn)算符的一個(gè)特點(diǎn)是右結(jié)合,而不是常見(jiàn)的左結(jié)合暑刃。多個(gè)指數(shù)運(yùn)算符連用時(shí)厢漩,是從最右邊開(kāi)始計(jì)算的。
例如:2 ** 3 ** 2 相當(dāng)于2(3**2)=2的9次方 = 512
二岩臣、函數(shù)的擴(kuò)展
0.函數(shù)參數(shù)的默認(rèn)值
0??袁翁、基本用法
ES6 之前,不能直接為函數(shù)的參數(shù)指定默認(rèn)值婿脸,只能采用變通的方法粱胜。ES6 允許為函數(shù)的參數(shù)設(shè)置默認(rèn)值,即直接寫(xiě)在參數(shù)定義的后面狐树。且注意:參數(shù)變量是默認(rèn)聲明的焙压,所以不能用
let
或const
再次聲明。
1??、與解構(gòu)賦值默認(rèn)值結(jié)合使用 §
2??涯曲、參數(shù)默認(rèn)值的位置
通常情況下野哭,定義了默認(rèn)值的參數(shù),應(yīng)該是函數(shù)的尾參數(shù)幻件。因?yàn)檫@樣比較容易看出來(lái)拨黔,到底省略了哪些參數(shù)。
3??绰沥、函數(shù)的 length 屬性
指定了默認(rèn)值以后篱蝇,函數(shù)的length屬性,將返回沒(méi)有指定默認(rèn)值的參數(shù)個(gè)數(shù)徽曲。也就是說(shuō)零截,指定了默認(rèn)值后,length屬性將失真秃臣。即:函數(shù)length屬性的返回值涧衙,等于函數(shù)的參數(shù)個(gè)數(shù)減去指定了默認(rèn)值的參數(shù)個(gè)數(shù)。
特別注意:如果設(shè)置了默認(rèn)值的參數(shù)不是尾參數(shù)奥此,那么length屬性也不再計(jì)入后面的參數(shù)了弧哎。
4??、作用域
ar x = 1;
function f(x, y = x) {
console.log(y);
}
f(2) // 2
上面代碼中稚虎,參數(shù)y的默認(rèn)值等于變量x撤嫩。調(diào)用函數(shù)f時(shí),參數(shù)形成一個(gè)單獨(dú)的作用域祥绞。在這個(gè)作用域里面非洲,默認(rèn)值變量x指向第一個(gè)參數(shù)x鸭限,而不是全局變量x蜕径,所以輸出是2。
5??败京、應(yīng)用
利用參數(shù)默認(rèn)值兜喻,可以指定某一個(gè)參數(shù)不得省略,如果省略就拋出一個(gè)錯(cuò)誤赡麦。
1.rest 參數(shù)
ES6 引入 rest 參數(shù)(形式為...變量名)朴皆,用于獲取函數(shù)的多余參數(shù),這樣就不需要使用arguments對(duì)象了泛粹。rest 參數(shù)搭配的變量是一個(gè)數(shù)組遂铡,該變量將多余的參數(shù)放入數(shù)組中。
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
下面是一個(gè) rest 參數(shù)代替arguments變量的例子晶姊。
// arguments變量的寫(xiě)法
function sortNumbers() {
return Array.prototype.slice.call(arguments).sort();
}
// rest參數(shù)的寫(xiě)法
const sortNumbers = (...numbers) => numbers.sort();
注意扒接,rest 參數(shù)之后不能再有其他參數(shù)(即只能是最后一個(gè)參數(shù)),否則會(huì)報(bào)錯(cuò)。
// 報(bào)錯(cuò)
function f(a, ...b, c) {
// ...
}
函數(shù)的length屬性钾怔,不包括 rest 參數(shù)碱呼。
2.嚴(yán)格模式
從 ES5 開(kāi)始,函數(shù)內(nèi)部可以設(shè)定為嚴(yán)格模式宗侦。ES2016 做了一點(diǎn)修改愚臀,規(guī)定只要
函數(shù)參數(shù)
使用了默認(rèn)值
、解構(gòu)賦值
矾利、或者擴(kuò)展運(yùn)算符
姑裂,那么函數(shù)內(nèi)部就不能顯式設(shè)定為嚴(yán)格模式
,否則會(huì)報(bào)錯(cuò)
梦皮。
原因是:函數(shù)內(nèi)部嚴(yán)格模式炭分,同時(shí)適用函數(shù)體和函數(shù)參數(shù),而在執(zhí)行的時(shí)候先執(zhí)行的是參數(shù)剑肯,而在函數(shù)體內(nèi)才知道是不是嚴(yán)格模式捧毛,這樣是不合理的。
兩種方法可以規(guī)避這種限制让网。第一種是設(shè)定全局性的嚴(yán)格模式呀忧,這是合法的。
'use strict';
function doSomething(a, b = a) {
// code
}
第二種是把函數(shù)包在一個(gè)無(wú)參數(shù)的立即執(zhí)行函數(shù)里面溃睹。
const doSomething = (function () {
'use strict';
return function(value = 42) {
return value;
};
}());
3.箭頭函數(shù)
- 如果箭頭函數(shù)的代碼塊部分多于一條語(yǔ)句而账,就要使用大括號(hào)將它們括起來(lái),并且使用return語(yǔ)句返回因篇。
- 由于大括號(hào)被解釋為代碼塊泞辐,所以如果箭頭函數(shù)直接返回一個(gè)對(duì)象,必須在對(duì)象外面加上括號(hào)竞滓,否則會(huì)報(bào)錯(cuò)咐吼。
- 箭頭函數(shù)的一個(gè)用處是簡(jiǎn)化回調(diào)函數(shù)。
- 函數(shù)體內(nèi)的this對(duì)象商佑,就是定義時(shí)所在的對(duì)象锯茄,而不是使用時(shí)所在的對(duì)象。
- 不可以當(dāng)作構(gòu)造函數(shù)茶没,也就是說(shuō)肌幽,不可以使用new命令,否則會(huì)拋出一個(gè)錯(cuò)誤抓半。
- 不可以使用arguments對(duì)象喂急,該對(duì)象在函數(shù)體內(nèi)不存在。如果要用笛求,可以用 rest 參數(shù)代替廊移。
- 不可以使用yield命令讥蔽,因此箭頭函數(shù)不能用作 Generator 函數(shù)。
關(guān)于this作用域的問(wèn)題画机,下面給出一個(gè)例子:
function Timer() {
this.s1 = 0;
this.s2 = 0;
// 箭頭函數(shù)
setInterval(() => this.s1++, 1000);
// 普通函數(shù)
setInterval(function () {
this.s2++;
}, 1000);
}
var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0
解析:上面代碼中,Timer函數(shù)內(nèi)部設(shè)置了兩個(gè)定時(shí)器步氏,分別使用了箭頭函數(shù)和普通函數(shù)。前者的this綁定定義時(shí)所在的作用域(即Timer函數(shù))荚醒,后者的this指向運(yùn)行時(shí)所在的作用域(即全局對(duì)象)。所以界阁,3100 毫秒之后,timer.s1被更新了 3 次泡躯,而timer.s2一次都沒(méi)更新贮竟。
再來(lái)一個(gè)例子:
var handler = {
id: '123456',
init: function() {
document.addEventListener('click',
event => this.doSomething(event.type), false);
},
doSomething: function(type) {
console.log('Handling ' + type + ' for ' + this.id);
}
};
上面代碼的init方法中咕别,使用了箭頭函數(shù),這導(dǎo)致這個(gè)箭頭函數(shù)里面的this惰拱,總是指向handler對(duì)象。否則啊送,回調(diào)函數(shù)運(yùn)行時(shí),this.doSomething這一行會(huì)報(bào)錯(cuò)馋没,因?yàn)榇藭r(shí)this指向document對(duì)象。
接著來(lái)一個(gè)例子披泪,請(qǐng)問(wèn)下面的代碼之中有幾個(gè)this搬瑰?
function foo() {
return () => {
return () => {
return () => {
console.log('id:', this.id);
};
};
};
}
var f = foo.call({id: 1});
var t1 = f.call({id: 2})()(); // id: 1
var t2 = f().call({id: 3})(); // id: 1
var t3 = f()().call({id: 4}); // id: 1
上面代碼之中,只有一個(gè)this泽论,就是函數(shù)foo的this艾少,所以t1、t2翼悴、t3都輸出同樣的結(jié)果缚够。因?yàn)樗械膬?nèi)層函數(shù)都是箭頭函數(shù)幔妨,都沒(méi)有自己的this,它們的this其實(shí)都是最外層foo函數(shù)的this.
長(zhǎng)期以來(lái)谍椅,JavaScript 語(yǔ)言的this對(duì)象一直是一個(gè)令人頭痛的問(wèn)題误堡,在對(duì)象方法中使用this,必須非常小心雏吭。箭頭函數(shù)”綁定”this锁施,很大程度上解決了這個(gè)困擾。
不適用場(chǎng)合
由于箭頭函數(shù)使得this從“動(dòng)態(tài)”變成“靜態(tài)”杖们,下面兩個(gè)場(chǎng)合不應(yīng)該使用箭頭函數(shù)。
第一個(gè)場(chǎng)合是定義函數(shù)的方法,且該方法內(nèi)部包括this簿透。
const cat = {
lives: 9,
jumps: () => {
this.lives--;
}
}
上面代碼中羹令,cat.jumps()方法是一個(gè)箭頭函數(shù),這是錯(cuò)誤的孝治。調(diào)用cat.jumps()時(shí)列粪,如果是普通函數(shù),該方法內(nèi)部的this指向cat谈飒;如果寫(xiě)成上面那樣的箭頭函數(shù)篱竭,使得this指向全局對(duì)象,因此不會(huì)得到預(yù)期結(jié)果步绸。
第二個(gè)場(chǎng)合是需要?jiǎng)討B(tài)this的時(shí)候掺逼,也不應(yīng)使用箭頭函數(shù)。
var button = document.getElementById('press');
button.addEventListener('click', () => {
this.classList.toggle('on');
});
上面代碼運(yùn)行時(shí)瓤介,點(diǎn)擊按鈕會(huì)報(bào)錯(cuò)吕喘,因?yàn)閎utton的監(jiān)聽(tīng)函數(shù)是一個(gè)箭頭函數(shù),導(dǎo)致里面的this就是全局對(duì)象刑桑。如果改成普通函數(shù)氯质,this就會(huì)動(dòng)態(tài)指向被點(diǎn)擊的按鈕對(duì)象。
另外祠斧,如果函數(shù)體很復(fù)雜闻察,有許多行,或者函數(shù)內(nèi)部有大量的讀寫(xiě)操作琢锋,不單純是為了計(jì)算值辕漂,這時(shí)也不應(yīng)該使用箭頭函數(shù),而是要使用普通函數(shù)吴超,這樣可以提高代碼可讀性钉嘹。