1.下面的代碼將輸出什么?
for (var i = 0; i < 5; i++) {
setTimeout(function() { console.log(i); }, i * 1000 );
}
閉包在這里能起什么作用畅哑?
上面的代碼不會按預(yù)期顯示值0肴楷,1,2荠呐,3阶祭,和4绷杜,
而是會顯示5,5濒募,5,5圾结,和5瑰剃。
原因是,在循環(huán)中執(zhí)行的每個函數(shù)將整個循環(huán)完成之后被執(zhí)行筝野,
因此晌姚,將會引用存儲在 i中的最后一個值,那就是5歇竟。
閉包可以通過為每次迭代創(chuàng)建一個唯一的范圍挥唠,
存儲范圍內(nèi)變量的每個唯一的值,
來防止這個問題焕议,
如下:
for (var i = 0; i < 5; i++) {
(function(x) {
setTimeout(function() { console.log(x); }, x * 1000 );
})(i);
}
這就會按預(yù)期輸出0宝磨,1,2盅安,3唤锉,和4到控制臺。
2.ES5别瞭、ES6和ES2015有什么區(qū)別?
ES2015特指在2015年發(fā)布的新一代JS語言標(biāo)準(zhǔn)窿祥,
ES6泛指下一代JS語言標(biāo)準(zhǔn),
包含ES2015蝙寨、ES2016晒衩、ES2017、ES2018等墙歪。
現(xiàn)階段在絕大部分場景下听系,
ES2015默認等同ES6。
ES5泛指上一代語言標(biāo)準(zhǔn)箱亿。
ES2015可以理解為ES5和ES6的時間分界線跛锌。
3.Iterator是什么,有什么作用届惋?
Iterator是ES6中一個很重要概念髓帽,
它并不是對象,
也不是任何一種數(shù)據(jù)類型脑豹。
因為ES6新增了Set郑藏、Map類型,
他們和Array瘩欺、Object類型很像必盖,Array拌牲、Object都是可以遍歷的,
但是Set歌粥、Map都不能用for循環(huán)遍歷塌忽,
解決這個問題有兩種方案,
一種是為Set失驶、Map單獨新增一個用來遍歷的API土居,
另一種是為Set、Map嬉探、Array擦耀、Object新增一個統(tǒng)一的遍歷API,
顯然涩堤,
第二種更好眷蜓,
ES6也就順其自然的需要一種設(shè)計標(biāo)準(zhǔn),
來統(tǒng)一所有可遍歷類型的遍歷方式胎围。
Iterator正是這樣一種標(biāo)準(zhǔn)吁系。或者說是一種規(guī)范理念痊远。
就好像JavaScript是ECMAScript標(biāo)準(zhǔn)的一種具體實現(xiàn)一樣垮抗,
Iterator標(biāo)準(zhǔn)的具體實現(xiàn)是Iterator遍歷器。
Iterator標(biāo)準(zhǔn)規(guī)定碧聪,所有部署了key值為[Symbol.iterator]冒版,
且[Symbol.iterator]的value是標(biāo)準(zhǔn)的Iterator接口函數(shù)(標(biāo)準(zhǔn)的Iterator接口函數(shù):
該函數(shù)必須返回一個對象,
且對象中包含next方法逞姿,
且執(zhí)行next()能返回包含value/done屬性的Iterator對象)的對象辞嗡,
都稱之為可遍歷對象,
next()后返回的Iterator對象也就是Iterator遍歷器滞造。
obj就是可遍歷的续室,
因為它遵循了Iterator標(biāo)準(zhǔn),
且包含[Symbol.iterator]方法谒养,
方法函數(shù)也符合標(biāo)準(zhǔn)的Iterator接口規(guī)范挺狰。
//obj.[Symbol.iterator]()
就是Iterator遍歷器
let obj =
{
data: [ 'hello', 'world' ], [Symbol.iterator]()
{ const self = this; let index = 0;
return { next() {
if (index < self.data.length) {
return { value: self.data[index++], done: false
};
} else {
return { value: undefined, done: true }; } } }; }
};
ES6給Set、Map买窟、Array丰泊、String都加上了[Symbol.iterator]方法,
且[Symbol.iterator]方法函數(shù)也符合標(biāo)準(zhǔn)的Iterator接口規(guī)范始绍,
所以Set瞳购、Map、Array亏推、String默認都是可以遍歷的学赛。
//Array let array = ['red', 'green', 'blue']; array[Symbol.iterator]()
//Iterator遍歷器 array[Symbol.iterator]().next()
//{value: "red", done: false} //String let string = '1122334455'; string[Symbol.iterator]()
//Iterator遍歷器 string[Symbol.iterator]().next()
//{value: "1", done: false}
//set let set = new Set(['red', 'green', 'blue']); set[Symbol.iterator]()
//Iterator遍歷器
set[Symbol.iterator]().next()
{value: "red", done: false}
Map let map = new Map();
let obj= {map: 'map'};
map.set(obj, 'mapValue');
map[Symbol.iterator]().next()
{value: Array(2), done: false}
4.module年堆、export、import是什么盏浇,有什么作用变丧?
module、export绢掰、import
是ES6用來統(tǒng)一前端模塊化方案的設(shè)計思路和實現(xiàn)方案锄贷。
export、import的出現(xiàn)統(tǒng)一了前端模塊化的實現(xiàn)方案曼月,
整合規(guī)范了瀏覽器/服務(wù)端的模塊化方法,
用來取代傳統(tǒng)的AMD/CMD柔昼、requireJS哑芹、seaJS、commondJS等等一系列前端模塊不同的實現(xiàn)方案捕透,
使前端模塊化更加統(tǒng)一規(guī)范聪姿,
JS也能更加能實現(xiàn)大型的應(yīng)用程序開發(fā)。
import引入的模塊是靜態(tài)加載(編譯階段加載)
而不是動態(tài)加載(運行時加載)乙嘀。
import引入export導(dǎo)出的接口值是動態(tài)綁定關(guān)系末购,
即通過該接口,可以取到模塊內(nèi)部實時的值虎谢。
5.日常前端代碼開發(fā)中盟榴,有哪些值得用ES6去改進的編程優(yōu)化或者規(guī)范?
1婴噩、常用箭頭函數(shù)來取代var self = this;的做法擎场。
2、常用let取代var命令几莽。
3迅办、常用數(shù)組/對象的結(jié)構(gòu)賦值來命名變量,結(jié)構(gòu)更清晰章蚣,語義更明確站欺,可讀性更好。
4纤垂、在長字符串多變量組合場合矾策,用模板字符串來取代字符串累加,能取得更好地效果和閱讀體驗洒忧。
5蝴韭、用Class類取代傳統(tǒng)的構(gòu)造函數(shù),來生成實例化對象熙侍。
6榄鉴、在大型應(yīng)用開發(fā)中履磨,要保持module模塊化開發(fā)思維,分清模塊之間的關(guān)系庆尘,常用import剃诅、export方法。