以下題目是根據(jù)網(wǎng)上多份面經(jīng)收集而來(lái)的鸠姨,題目相同意味著被問(wèn)的頻率比較高叙甸,有問(wèn)題歡迎留言討論钉迷,喜歡可以點(diǎn)贊關(guān)注出皇。
1.let const var比較區(qū)別,ES6中l(wèi)et塊作用域是怎么實(shí)現(xiàn)的
https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/133
先說(shuō)說(shuō)這三者的區(qū)別吧:
可以結(jié)合http://www.reibang.com/p/47b49d7bdfc2中的第一節(jié)來(lái)看堂竟。
(一)var
- var 命令會(huì)發(fā)生“變量提升”現(xiàn)象魂毁,即變量可以在聲明之前使用,值為 undefined
- 內(nèi)層變量可能覆蓋外層變量
- 用來(lái)計(jì)數(shù)的循環(huán)變量泄露為全局變量
(二)let
- 聲明的全局變量不會(huì)掛在頂層對(duì)象下面
- 所聲明的變量一定要在聲明后使用出嘹,否則報(bào)錯(cuò)席楚,報(bào)錯(cuò) ReferenceError
- 暫時(shí)性死區(qū),只要塊級(jí)作用域內(nèi)存在 let 命令税稼,它所聲明的變量就“綁定”( binding )這個(gè)區(qū)域烦秩,不再受外部的影響,在代碼塊內(nèi)娶聘,使用 let 命令聲明變量之前闻镶,該變量都是不可用的甚脉。
- 不允許重復(fù)聲明
(三)const
- 聲明的全局變量不會(huì)掛在頂層對(duì)象下面
- const 聲明之后必須馬上賦值丸升,否則會(huì)報(bào)錯(cuò)
- const 簡(jiǎn)單類型一旦聲明就不能再更改,復(fù)雜類型(數(shù)組牺氨、對(duì)象等)指針指向的地址不能更改狡耻,內(nèi)部數(shù)據(jù)可以更改。
- const 一旦聲明變量猴凹,就必須立即初始化夷狰,不能留到以后賦值。
- const 命令聲明的常量也是不提升郊霎,同樣存在暫時(shí)性死區(qū)沼头,只能在聲明的位置后面使用
如 const 聲明了一個(gè)復(fù)合類型的常量,其存儲(chǔ)的是一個(gè)引用地址书劝,不允許改變的是這個(gè)地址进倍,而對(duì)象本身是可變的。
// const arr 數(shù)組可以賦值
const arr = ['apple', 'banana']
arr.push('orange')
console.log(arr)//["apple", "banana", "orange"]
然后是原理购对,原理確實(shí)沒(méi)認(rèn)真研究過(guò)猾昆,在網(wǎng)上翻了一番資料,結(jié)合自己的理解簡(jiǎn)單說(shuō)下(純屬個(gè)人愚見(jiàn)骡苞,高手輕噴)
變量與內(nèi)存之間的關(guān)系垂蜗,主要由三個(gè)部分組成:
- 變量名
- 內(nèi)存地址
- 內(nèi)存空間
JS 引擎在讀取變量時(shí)楷扬,先找到變量綁定的內(nèi)存地址,然后找到地址所指向的內(nèi)存空間贴见,最后讀取其中的內(nèi)容烘苹。當(dāng)變量改變時(shí),JS 引擎不會(huì)用新值覆蓋之前舊值的內(nèi)存空間(雖然從寫代碼的角度來(lái)看片部,確實(shí)像是被覆蓋掉了)螟加,而是重新分配一個(gè)新的內(nèi)存空間來(lái)存儲(chǔ)新值,并將新的內(nèi)存地址與變量進(jìn)行綁定吞琐,JS 引擎會(huì)在合適的時(shí)機(jī)進(jìn)行 GC捆探,回收舊的內(nèi)存空間。
const 定義變量(常量)后站粟,變量名與內(nèi)存地址之間建立了一種不可變的綁定關(guān)系黍图,阻隔變量地址被改變,當(dāng) const 定義的變量進(jìn)行重新賦值時(shí)奴烙,根據(jù)前面的論述助被,JS 引擎會(huì)嘗試重新分配新的內(nèi)存空間,所以會(huì)被拒絕切诀,便會(huì)拋出異常揩环。
var的話會(huì)直接在棧內(nèi)存里
預(yù)分配內(nèi)存空間
,然后等到實(shí)際語(yǔ)句執(zhí)行的時(shí)候幅虑,再存儲(chǔ)對(duì)應(yīng)的變量丰滑,如果傳的是引用類型,那么會(huì)在堆內(nèi)存里開(kāi)辟一個(gè)內(nèi)存空間存儲(chǔ)實(shí)際內(nèi)容倒庵,棧內(nèi)存會(huì)存儲(chǔ)一個(gè)指向堆內(nèi)存的指針
ES6中l(wèi)et塊作用域是怎么實(shí)現(xiàn)的
let的話褒墨,是
不會(huì)在棧內(nèi)存里預(yù)分配內(nèi)存空間
,而且在棧內(nèi)存分配變量時(shí)擎宝,做一個(gè)檢查郁妈,如果已經(jīng)有相同變量名存在就會(huì)報(bào)錯(cuò)
。也就是暫時(shí)性死區(qū)绍申,只要塊級(jí)作用域內(nèi)存在 let 命令噩咪,它所聲明的變量就“綁定”( binding )這個(gè)區(qū)域,不再受外部的影響极阅,在代碼塊內(nèi)胃碾,使用 let 命令聲明變量之前,該變量都是不可用的涂屁。
const的話书在,
也不會(huì)預(yù)分配內(nèi)存空間
,在棧內(nèi)存分配變量時(shí)也會(huì)做同樣的檢查拆又。不過(guò)const存儲(chǔ)的變量是不可修改的
儒旬,對(duì)于基本類型來(lái)說(shuō)你無(wú)法修改定義的值栏账,對(duì)于引用類型來(lái)說(shuō)你無(wú)法修改棧內(nèi)存里分配的指針
,但是你可以修改指針指向的對(duì)象里面的屬性
2.反引號(hào)(`)標(biāo)識(shí)(模板字符串)
https://blog.csdn.net/zwt_guiji/article/details/81979299
模板字符串是在ES6中興起
用法
// 普通字符串
`In JavaScript '\n' is a line-feed.`
// 多行字符串
`In JavaScript this
isnot legal.`
// 字符串中嵌入變量
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?` // Hello Bob, how are you today?
模板字符串都是用反引號(hào)表示栈源,如果在模板字符串中需要使用反引號(hào)挡爵,則前面需要用反斜杠轉(zhuǎn)義。
如果使用模板字符串表示多行字符串甚垦,則所有的空格茶鹃、縮進(jìn)和換行都會(huì)被保留在輸出中。
比如<ul>
標(biāo)簽前面會(huì)有一個(gè)換行艰亮。如果想把行首和行尾的換行闭翩、空格等去掉,則使用trim方法即可迄埃。
模板字符串中嵌入變量疗韵,要將變量名寫在${}
之中。大括號(hào)內(nèi)可以放入任意的JavaScript表達(dá)式侄非,可以進(jìn)行運(yùn)算蕉汪,以及引入對(duì)象屬性。
模板字符串之中還可以調(diào)用函數(shù)逞怨。
如果大括號(hào)中的值不是字符串者疤,則將按照一般的規(guī)則轉(zhuǎn)換為字符串。如叠赦,若大括號(hào)中是一個(gè)對(duì)象驹马,則將默認(rèn)調(diào)用對(duì)象的toString方法,把對(duì)象轉(zhuǎn)換為字符串眯搭。
如果模板字符串中的變量沒(méi)有聲明窥翩,則會(huì)報(bào)錯(cuò)。
// 變量place沒(méi)有聲明
var msg = `Hello, ${place}`;
// ReferenceError: place is not defined
模板字符串之間還可以進(jìn)行嵌套鳞仙。
標(biāo)簽?zāi)0?/h3>
模板字符串的功能,不僅是上面那些笔时,它還可以緊跟在一個(gè)函數(shù)后面棍好,該函數(shù)將被調(diào)用來(lái)處理這個(gè)模板字符串,這種稱為“標(biāo)簽?zāi)0濉惫δ?Tagged template)允耿。
alert`123`// 等同于alert(123)
標(biāo)簽?zāi)0迤渌且环N特殊的函數(shù)調(diào)用形式借笙,“標(biāo)簽”指的就是函數(shù),緊跟在后面的模板字符串就是它的參數(shù)较锡。
var a = 1, b = 2;
tag`Helo ${a + b} world ${a * b}`;
上面代碼中业稼,模板字符串前面有一個(gè)標(biāo)識(shí)名tag,它是一個(gè)函數(shù)蚂蕴。整個(gè)表達(dá)式的返回值就是tag函數(shù)處理模板字符串后的返回值低散。
函數(shù)tag依次會(huì)接收到多個(gè)參數(shù)俯邓。
tag函數(shù)的第一個(gè)參數(shù)是一個(gè)數(shù)組,該數(shù)組的成員是模板字符串中那些沒(méi)有變量替換的部分熔号,也就是說(shuō)稽鞭,變量替換只發(fā)生在數(shù)組的第一個(gè)成員與第二個(gè)成員之間、第二個(gè)成員與第三個(gè)成員之間引镊,以此類推朦蕴。tag函數(shù)的其他參數(shù),都是模板字符串各個(gè)變量被替換的值弟头。本例中吩抓,模板字符串含有兩個(gè)變量,因此tag會(huì)接收到value1和value2兩個(gè)參數(shù)赴恨。
tag函數(shù)所有參數(shù)的實(shí)際值如下:
- 第一個(gè)參數(shù): [‘Hello ‘, ’ world’, ”]
- 第二個(gè)參數(shù): 3
- 第三個(gè)參數(shù): 2
也就是說(shuō)琴拧,tag函數(shù)實(shí)際上是用下面的形式調(diào)用:
tag(['Hello ',' world', ''], 3, 2);
String對(duì)象的raw方法
String.raw方法用來(lái)充當(dāng)模板字符串的處理函數(shù),返回一個(gè)除表達(dá)式和變量會(huì)被替換嘱支,其它都保持原樣的字符串蚓胸。
String.raw方法可以作為處理模板字符串的基本方法,它會(huì)將所有變量替換除师,而且對(duì)斜杠進(jìn)行轉(zhuǎn)義沛膳,方便下一步作為字符串來(lái)使用。
3.函數(shù)默認(rèn)參數(shù)和剩余(rest)參數(shù)
1. 函數(shù)默認(rèn)參數(shù)
function show({x=0,y=0}={}){
console.log(x,y);
}
show()
2. 函數(shù)參數(shù)默認(rèn)已經(jīng)定義了汛聚,不能再使用let锹安,const聲明
function show(a=18){
let a = 101; //錯(cuò)誤
console.log(a);
}
show()
擴(kuò)展運(yùn)算符、Reset運(yùn)算符:
...
展開(kāi)數(shù)組
... :
[1,2,3,4] -> ... [1,2,3,4] -> 1,2,3,4,5
...:
1,2,3,4,5 -> ...1,2,3,4,5 -> [1,2,3,4,5]
剩余參數(shù): 必須放到最后
rest參數(shù)和 arguments對(duì)象的區(qū)別
4.箭頭函數(shù)this指向問(wèn)題倚舀,箭頭函數(shù)與普通函數(shù)的區(qū)別叹哭,你說(shuō)箭頭函數(shù)沒(méi)有自己的this,那(()=>{}).bind(this)可以么?
https://juejin.im/post/5b14d0b4f265da6e60393680
六沒(méi)
1痕貌、沒(méi)有this
箭頭函數(shù)沒(méi)有 this风罩,所以需要通過(guò)查找作用域鏈來(lái)確定 this 的值。這就意味著如果箭頭函數(shù)被非箭頭函數(shù)包含舵稠,this 綁定的就是最近一層非箭頭函數(shù)的 this超升。,因?yàn)榧^函數(shù)沒(méi)有 this哺徊,所以也不能用 call()室琢、apply()、bind() 這些方法改變 this 的指向落追,可以看一個(gè)例子:
var value = 1;
var result = (() => this.value).bind({value: 2})();
console.log(result); // 1
2盈滴、沒(méi)有arguments
箭頭函數(shù)沒(méi)有自己的 arguments 對(duì)象,這不一定是件壞事轿钠,因?yàn)榧^函數(shù)可以訪問(wèn)外圍函數(shù)的巢钓。通過(guò)命名參數(shù)或者 rest 參數(shù)的形式訪問(wèn)參數(shù)
3病苗、沒(méi)有new關(guān)鍵字調(diào)用
箭頭不能被用作構(gòu)造函數(shù),如果通過(guò) new 的方式調(diào)用竿报,會(huì)報(bào)錯(cuò)
var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor
4铅乡、沒(méi)有new.target
因?yàn)椴荒苁褂?new 調(diào)用,所以也沒(méi)有 new.target 值烈菌。關(guān)于 new.target阵幸,可以參考 es6.ruanyifeng.com/#docs/class…
5、沒(méi)有原型
由于不能使用 new 調(diào)用箭頭函數(shù)芽世,所以也沒(méi)有構(gòu)建原型的需求挚赊,于是箭頭函數(shù)也不存在 prototype 這個(gè)屬性。
var Foo = () => {};
console.log(Foo.prototype); // undefined
6济瓢、沒(méi)有super
連原型都沒(méi)有荠割,自然也不能通過(guò) super 來(lái)訪問(wèn)原型的屬性,所以箭頭函數(shù)也是沒(méi)有 super 的旺矾,不過(guò)跟 this蔑鹦、arguments、new.target 一樣箕宙,這些值由外圍最近一層非箭頭函數(shù)決定嚎朽。
5.屬性簡(jiǎn)寫
1.對(duì)象的方法簡(jiǎn)寫
const o = {
method() {
return "Hello!";
}
};
// 等同于
const o = {
method: function() {
return "Hello!";
}
};
let birth = '2000/01/01';
const Person = {
name: '張三',
//等同于birth: birth
birth,
// 等同于hello: function ()...
hello() { console.log('我的名字是', this.name); }
};
2.對(duì)象的屬性簡(jiǎn)寫
const a= 'a';
const b= {a};
b// {a: "a"}
// 等同于
const b= {a: a}; //前面的a是對(duì)象屬性的名字,后面的a代表變量a
實(shí)際應(yīng)用:
function f(x, y) {
return {x, y};
}
// 等同于
function f(x, y) {
return {x: x, y: y};
}
f(1, 2) // {x: 1, y: 2}
3.擴(kuò)展
import App from './App.vue'
new Vue({
router,
store,
render: h => h(App)
})
等同于
new Vue({
router:router,
store:store,
render:function(h){
return h(App);
}
})
6.方法簡(jiǎn)寫
同上
7.Object.keys()方法柬帕,獲取對(duì)象的所有屬性名或方法名
一哟忍、語(yǔ)法
Object.keys(obj)
參數(shù):要返回其枚舉自身屬性的對(duì)象
返回值:一個(gè)表示給定對(duì)象的所有可枚舉屬性的字符串?dāng)?shù)組
二、處理對(duì)象陷寝,返回可枚舉的屬性數(shù)組
let person = {name:"張三",age:25,address:"深圳",getName:function(){}}
Object.keys(person) // ["name", "age", "address","getName"]
三锅很、處理數(shù)組,返回索引值數(shù)組
let arr = [1,2,3,4,5,6]
Object.keys(arr) // ["0", "1", "2", "3", "4", "5"]
四凤跑、處理字符串爆安,返回索引值數(shù)組
let str = "saasd字符串"
Object.keys(str) // ["0", "1", "2", "3", "4", "5", "6", "7"]
五、常用技巧
let person = {name:"張三",age:25,address:"深圳",getName:function(){}}
Object.keys(person).map((key)=>{
person[key] // 獲取到屬性對(duì)應(yīng)的值饶火,做一些處理
})
六鹏控、Object.values()和Object.keys()是相反的操作,把一個(gè)對(duì)象的值轉(zhuǎn)換為數(shù)組
8.Object.assign ()原對(duì)象的屬性和方法都合并到了目標(biāo)對(duì)象
http://www.reibang.com/p/f9ec860ecd81
Object.assign(): 用來(lái)合并對(duì)象
let 新的對(duì)象 = Object.assign(目標(biāo)對(duì)象, source1, srouce2....)
function ajax(options){ //用戶傳
let defaults={
type:'get',
header:
data:{}
....
};
let json = Object.assign({}, defaults, options);
.....
}
用途:
1. 復(fù)制一個(gè)對(duì)象
2. 合并參數(shù)
let json = { a: 3, b: 4 };
let json2 = { ...json };
console.log(json2 === json)//false
console.log(Object.assign({}, json) === json)//false
console.log(Object.assign(json) === json)//true
注意:
1.如果目標(biāo)對(duì)象中的屬性具有相同的鍵肤寝,則屬性將被源對(duì)象中的屬性覆蓋。后面的源對(duì)象的屬性將類似地覆蓋前面的源對(duì)象的屬性
2.Object.assign 方法只會(huì)拷貝源對(duì)象自身的并且可枚舉的屬性到目標(biāo)對(duì)象抖僵。該方法使用源對(duì)象的[[Get]]和目標(biāo)
對(duì)象的[[Set]]鲤看,所以它會(huì)調(diào)用相關(guān) getter 和 setter。因此耍群,它分配屬性义桂,而不僅僅是復(fù)制或定義新的屬性找筝。如
果合并源包含getter,這可能使其不適合將新屬性合并到原型中慷吊。為了將屬性定義(包括其可枚舉性)復(fù)制到
原型袖裕,應(yīng)使用Object.getOwnPropertyDescriptor()和Object.defineProperty() 。
9.for...of 循環(huán)
http://www.reibang.com/p/2e6dd8906e97
一個(gè)數(shù)據(jù)結(jié)構(gòu)只要部署了Symbol.iterator屬性溉瓶,就被視為具有 iterator 接口急鳄,就可以用for...of循環(huán)遍歷它的成員。也就是說(shuō)堰酿,for...of循環(huán)內(nèi)部調(diào)用的是數(shù)據(jù)結(jié)構(gòu)的Symbol.iterator方法疾宏。for...of循環(huán)可以使用的范圍包括數(shù)組、Set 和 Map 結(jié)構(gòu)触创、某些類似數(shù)組的對(duì)象(比如arguments對(duì)象坎藐、DOM NodeList 對(duì)象)、Generator 對(duì)象哼绑,以及字符串岩馍。
for...of 遍歷 非 Iterator 的類數(shù)組對(duì)象
并不是所有類似數(shù)組的對(duì)象都具有 Iterator 接口,一個(gè)簡(jiǎn)便的解決方法抖韩,就是使用Array.from方法將其轉(zhuǎn)為數(shù)組蛀恩。
let arrayLike = { length: 2, 0: 'a', 1: 'b' };
// 報(bào)錯(cuò)
for (let x of arrayLike) {
console.log(x);
}
// 正確
for (let x of Array.from(arrayLike)) {
console.log(x);
}
for...of 遍歷 對(duì)象
對(duì)于普通的對(duì)象,for...of結(jié)構(gòu)不能直接使用帽蝶,會(huì)報(bào)錯(cuò)赦肋。使用 for...in 可以遍歷對(duì)象的鍵名。
let obj = {
a: 1,
b: 2,
c: 3
}
for (let e in obj) {
console.log(e); // 'a' 'b' 'c'
}
總之励稳,for...in循環(huán)主要是為遍歷對(duì)象而設(shè)計(jì)的佃乘,不適用于遍歷數(shù)組。
一種解決方法是驹尼,使用Object.keys方法將對(duì)象的鍵名生成一個(gè)數(shù)組趣避,然后再用 for...of 遍歷這個(gè)數(shù)組。
for(let key of Object.keys(obj)) {
console.log(key + ': ' + obj[key]);
}
另一個(gè)方法是使用 Generator 函數(shù)將對(duì)象重新包裝一下新翎。
function* entries(obj) {
for(let key of Object.keys(obj)) {
yield [key, obj[key]];
}
}
for(let [key, value] of entries(obj)) {
console.log(key, '->', value);
}
9程帕、for...of 可以與 break / continue / return 配合使用
for (var n of arr) {
if (n > 10) {
break;
}
console.log(n);
}
10.import和export,CommonJS 中的 require/exports 和 ES6 中的 import/export 區(qū)別地啰?
1愁拭、CommonJS模塊輸出的是一個(gè)值的拷貝,一旦輸出一個(gè)值亏吝,模塊內(nèi)部的變化就影響不到這個(gè)值岭埠。
ES6模塊輸出的是值的引用,JS引擎對(duì)腳本靜態(tài)分析的時(shí)候,遇到模塊加載命令import惜论,就會(huì)生成一個(gè)只讀引用许赃。等到腳本真正執(zhí)行時(shí),在根據(jù)引用到被加載的那個(gè)模塊里面去取值馆类。ES6模塊是動(dòng)態(tài)引用混聊,并且不會(huì)緩存運(yùn)行結(jié)果,而是動(dòng)態(tài)的去被加載的模塊取值乾巧,模塊里面的變量綁定其所在的模塊句喜。
2、CommonJS模塊是運(yùn)行時(shí)加載卧抗,ES6模塊是編譯時(shí)輸出接口(ES6可以在編譯時(shí)就完成模塊加載藤滥,效率要比CommonJS模塊的加載方式高)。
- ES6模塊是通用的社裆,同一個(gè)模塊不用修改拙绊,就可以用在瀏覽器
4、require/exports是CommonJS在Node中實(shí)現(xiàn)的泳秀。
import/export是ES6的模塊标沪,對(duì)ES6只要使用babel就可以了
5、ES6模塊的設(shè)計(jì)思想嗜傅,是盡量靜態(tài)化金句,使得編譯時(shí)就能確定模塊的依賴關(guān)系以及輸入和輸出的變量。export命令用于規(guī)定模塊的對(duì)外接口吕嘀,import命令用于輸入其他模塊提供的功能违寞。
12.解構(gòu)賦值
非常有用,特別在做數(shù)據(jù)交互 ajax
let [a,b,c] =[12,5, 6];
注意: 左右兩邊偶房,結(jié)構(gòu)格式要保持一致
// let [a, b, c] = [12, 3, 'k']
// console.log(a, b, c)//12 3 "k"
// 屬性名稱要一一對(duì)應(yīng)
// let { name, age, job, f, arr } = {
// name: 'Strive',
// age: 18,
// job: '碼畜',
// arr: [
// { name: 'liu' },
// { name: 'zhao' }
// ]
// };
// console.log(name, age, job, f)//Strive 18 碼畜 undefined
// console.log(name, age, job, arr)//Strive 18 碼畜 (2) [{…}, {…}]
// let json = {
// name: 'Strive',
// age: 18,
// job: '碼畜',
// arr: [
// { name: 'liu' },
// { name: 'zhao' }
// ]
// };
// let { name: n, age: g, job: f, arr } = json;
// console.log(n, g, f, arr)//Strive 18 碼畜 (2) [{…}, {…}]
// let [a, b, c] = ['a', 'b']
// console.log(a, b, c)//a b undefined
// 傳undefined和上面不傳參數(shù)是一樣的 傳null和‘’都是有值
// let [a, b, c] = ['a', 'b', undefined]
// console.log(a, b, c)//a b undefined
// let [a, b, c = 'no-data'] = ['a', 'b']
// console.log(a, b, c)//a b no-data
// let a;
// //先用let定義沒(méi)有賦值 要用小括號(hào)括起來(lái) 不然大括號(hào)直接暴露在外面 會(huì)起到塊級(jí)作用域的
// ({ a } = { a: 'apple', b: 'banana' });
// console.log(a)
// a,b相互賦值 不用找中間值
// let a = 12;
// let b = 10;
// [a, b] = [b, a]
// console.log(a)//10
// function fn() {
// return {
// leftVal: 10,
// topVal: 20
// }
// }
// let { leftVal, topVal: t } = fn();
// console.log(leftVal, t)//10 20
function fn({ a, b = '默認(rèn)值' }) {
console.log(a)//1
}
fn({
a: 1,
b: undefined
})
13.set數(shù)據(jù)結(jié)構(gòu)(可用于快速去重)
set數(shù)據(jù)結(jié)構(gòu):
類似數(shù)組趁曼,但是里面不能有重復(fù)值
let arr = ['a','b','a'];
let arr = new Array();
set用法:
let setArr = new Set(['a','b']);
setArr.add('a'); 往setArr里面添加一項(xiàng)
setArr.delete('b'); 刪除一項(xiàng)
setArr.has('a') 判斷setArr里面有沒(méi)有此值
setArr.size 個(gè)數(shù)
setArr.clear(); 清空
14.Spread Operator 展開(kāi)運(yùn)算符(...)
... [1,2,3,4] -> 1,2,3,4,5
... 1,2,3,4,5 -> [1,2,3,4,5]
15.字符串新增方法
https://www.cnblogs.com/weimingmei/p/11488458.html
1、String.fromCodePoint()
2棕洋、String.raw()
3挡闰、codePointAt()
4、normalize()
5掰盘、includes(), startsWith(), endsWith()
6摄悯、repeat()
7、padStart()愧捕,padEnd()
8奢驯、trimStart(),trimEnd()
9次绘、matchAll()
關(guān)于字符串一些東西:
字符串查找:
str.indexOf(要找的東西) 返回索引(位置) 叨橱,沒(méi)找到返回-1
str.includes(要找的東西) 返回值 true/false
判斷瀏覽器: includes
http://www.xxx.xx
字符串是否以誰(shuí)開(kāi)頭:
str.startsWith(檢測(cè)東西)
檢測(cè)地址
字符串是否以誰(shuí)結(jié)尾:
str.endsWith(檢測(cè)東西)
.png
重復(fù)字符串:
str.repeat(次數(shù));
填充字符串:
str.padStart(整個(gè)字符串長(zhǎng)度, 填充東西) 往前填充
str.padEnd(整個(gè)字符串長(zhǎng)度, 填充東西) 往后填充
str.padStart(str.length+padStr.length, padStr)
16.聲明類與繼承:class典蜕、extend断盛,ES6 class與ES5 function區(qū)別及聯(lián)系
區(qū)別
https://blog.csdn.net/u012657197/article/details/77542404
17.symbol應(yīng)用
數(shù)據(jù)類型:
number罗洗、string、boolean钢猛、Object伙菜、undefined、function
用typeof檢測(cè)出來(lái)數(shù)據(jù)類型: symbol
new Number(12)
new String()
new Array()
symbol 使用情況一般
定義:
let syml = Symbol('aaa');
注意:
1. Symbol 不能new
2. Symbol() 返回是一個(gè)唯一值坊間傳說(shuō), 做一個(gè)key命迈,定義一些唯一或者私有一些東
3. symbol是一個(gè)單獨(dú)數(shù)據(jù)類型贩绕,就叫 symbol, 基本類型
4. 如果symbol作為key,用for in循環(huán)壶愤,出不來(lái)
5.Symbol值作為對(duì)象屬性時(shí)淑倾,不能使用點(diǎn)運(yùn)算符。
json -> for in
18.es6和es7中新增加了什么
ES2016(es7)添加了兩個(gè)小的特性來(lái)說(shuō)明標(biāo)準(zhǔn)化過(guò)程:
數(shù)組includes()方法征椒,用來(lái)判斷一個(gè)數(shù)組是否包含一個(gè)指定的值娇哆,根據(jù)情況,如果包含則返回true勃救,否則返回false碍讨。
a ** b指數(shù)運(yùn)算符,它與 Math.pow(a, b)相同蒙秒。
19.ES6怎么編譯成ES5,css-loader原理,過(guò)程
Babel 是一個(gè) JavaScript 編譯器勃黍,Babel 是一個(gè)工具鏈,主要用于將 ECMAScript 2015+ 版本的代碼轉(zhuǎn)換為向后兼容的 JavaScript 語(yǔ)法晕讲,以便能夠運(yùn)行在當(dāng)前和舊版本的瀏覽器或其他環(huán)境中覆获。Webpack也有自動(dòng)編譯轉(zhuǎn)換能力。
①引入腳本babel庫(kù)②如下
css-loader原理,過(guò)程
loader 用于對(duì)模塊的源代碼進(jìn)行轉(zhuǎn)換瓢省。loader 可以使你在 import 或"加載"模塊時(shí)預(yù)處理文件弄息。因此,loader 類似于其他構(gòu)建工具中“任務(wù)(task)”净捅,并提供了處理前端構(gòu)建步驟的強(qiáng)大方法疑枯。css-loader是分析各個(gè)css文件的關(guān)系并合并成一個(gè)css。
關(guān)于es6及以上的js編譯成es5
20.ES6轉(zhuǎn)成ES5的常見(jiàn)例子
https://www.cnblogs.com/slongs/p/11238574.html
21.使用解構(gòu)蛔六,實(shí)現(xiàn)兩個(gè)變量的值的交換
let [a,b]=[b,a]
22.利用數(shù)組推導(dǎo)荆永,計(jì)算出數(shù)組 [1,2,3,4] 每一個(gè)元素的平方并組成新的數(shù)組
var arr1 = [1, 2, 3, 4];
var arr2 = arr1.map(i => i * i)
console.log(arr2);
23.map和set有沒(méi)有用過(guò),如何實(shí)現(xiàn)一個(gè)數(shù)組去重国章,map數(shù)據(jù)結(jié)構(gòu)有什么優(yōu)點(diǎn)具钥?ES6的Set內(nèi)部實(shí)現(xiàn)
Map 對(duì)象
Map 對(duì)象保存鍵值對(duì)。任何值(對(duì)象或者原始值) 都可以作為一個(gè)鍵或一個(gè)值液兽。
Maps 和 Objects 的區(qū)別
1骂删、一個(gè) Object 的鍵只能是字符串或者 Symbols掌动,但一個(gè) Map 的鍵可以是任意值。
2宁玫、Map 中的鍵值是有序的(FIFO 原則)粗恢,而添加到對(duì)象中的鍵則不是。
3欧瘪、Map 的鍵值對(duì)個(gè)數(shù)可以從 size 屬性獲取眷射,而 Object 的鍵值對(duì)個(gè)數(shù)只能手動(dòng)計(jì)算。
4佛掖、Object 都有自己的原型妖碉,原型鏈上的鍵名有可能和你自己在對(duì)象上的設(shè)置的鍵名產(chǎn)生沖突。
for…of
var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
// 將會(huì)顯示兩個(gè) log芥被。 一個(gè)是 "0 = zero" 另一個(gè)是 "1 = one"
for (var [key, value] of myMap) {
console.log(key + " = " + value);
}
for (var [key, value] of myMap.entries()) {
console.log(key + " = " + value);
}
/* 這個(gè) entries 方法返回一個(gè)新的 Iterator 對(duì)象欧宜,它按插入順序包含了 Map 對(duì)象中每個(gè)元素的 [key, value] 數(shù)組。 */
// 將會(huì)顯示兩個(gè)log拴魄。 一個(gè)是 "0" 另一個(gè)是 "1"
for (var key of myMap.keys()) {
console.log(key);
}
/* 這個(gè) keys 方法返回一個(gè)新的 Iterator 對(duì)象冗茸, 它按插入順序包含了 Map 對(duì)象中每個(gè)元素的鍵。 */
// 將會(huì)顯示兩個(gè)log羹铅。 一個(gè)是 "zero" 另一個(gè)是 "one"
for (var value of myMap.values()) {
console.log(value);
}
/* 這個(gè) values 方法返回一個(gè)新的 Iterator 對(duì)象蚀狰,它按插入順序包含了 Map 對(duì)象中每個(gè)元素的值。 */
forEach()
var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
// 將會(huì)顯示兩個(gè) logs职员。 一個(gè)是 "0 = zero" 另一個(gè)是 "1 = one"
myMap.forEach(function(value, key) {
console.log(key + " = " + value);
}, myMap)
Map 與 Array的轉(zhuǎn)換
var kvArray = [["key1", "value1"], ["key2", "value2"]];
// Map 構(gòu)造函數(shù)可以將一個(gè) 二維 鍵值對(duì)數(shù)組轉(zhuǎn)換成一個(gè) Map 對(duì)象
var myMap = new Map(kvArray);
// 使用 Array.from 函數(shù)可以將一個(gè) Map 對(duì)象轉(zhuǎn)換成一個(gè)二維鍵值對(duì)數(shù)組
var outArray = Array.from(myMap);
Set 對(duì)象
Set 對(duì)象允許你存儲(chǔ)任何類型的唯一值麻蹋,無(wú)論是原始值或者是對(duì)象引用。
Set 中的特殊值
Set 對(duì)象存儲(chǔ)的值總是唯一的焊切,所以需要判斷兩個(gè)值是否恒等扮授。有幾個(gè)特殊值需要特殊對(duì)待:
+0 與 -0 在存儲(chǔ)判斷唯一性的時(shí)候是恒等的,所以不重復(fù)专肪;
undefined 與 undefined 是恒等的刹勃,所以不重復(fù);
NaN 與 NaN 是不恒等的嚎尤,但是在 Set 中只能存一個(gè)荔仁,不重復(fù)。
let mySet = new Set();
mySet.add(1); // Set(1) {1}
mySet.add(5); // Set(2) {1, 5}
mySet.add(5); // Set(2) {1, 5} 這里體現(xiàn)了值的唯一性
mySet.add("some text");
// Set(3) {1, 5, "some text"} 這里體現(xiàn)了類型的多樣性
var o = {a: 1, b: 2};
mySet.add(o);
mySet.add({a: 1, b: 2});
// Set(5) {1, 5, "some text", {…}, {…}}
// 這里體現(xiàn)了對(duì)象之間引用不同不恒等芽死,即使值相同乏梁,Set 也能存儲(chǔ)
類型轉(zhuǎn)換
// Array 轉(zhuǎn) Set
var mySet = new Set([“value1”, “value2”, “value3”]);
// 用…操作符,將 Set 轉(zhuǎn) Array
var myArray = […mySet];
String
// String 轉(zhuǎn) Set
var mySet = new Set('hello'); // Set(4) {"h", "e", "l", "o"}
// 注:Set 中 toString 方法是不能將 Set 轉(zhuǎn)換成 String
數(shù)組去重
var mySet = new Set([1, 2, 3, 4, 4]);
[...mySet]; // [1, 2, 3, 4]
map優(yōu)點(diǎn)
Map保存[key-value]值关贵,value可多值遇骑。
ES6的Set內(nèi)部實(shí)現(xiàn)
https://www.cnblogs.com/hui-fly/p/9459152.html
24.取數(shù)組的最大值(ES5、ES6)
// ES5 的寫法
Math.max.apply(null, [14, 3, 77, 30]);
// ES6 的寫法
Math.max(...[14, 3, 77, 30]);
// reduce
[14,3,77,30].reduce((accumulator, currentValue)=>{
return accumulator = accumulator > currentValue ? accumulator : currentValue
});
25.const obj 的屬性如何不可變
const定義的基本數(shù)據(jù)類型的變量確實(shí)不能修改揖曾。
因?yàn)閷?duì)象是引用類型的落萎,保存的僅是對(duì)象的指針亥啦,這就意味著,const僅保證指針不發(fā)生改變练链,修改對(duì)象的屬性不會(huì)改變對(duì)象的指針翔脱,所以是被允許的。也就是說(shuō)const定義的引用類型只要指針不發(fā)生改變兑宇,其他的不論如何改變都是允許的碍侦。我們?cè)囍薷囊幌轮羔槪孭指向一個(gè)新對(duì)象隶糕,結(jié)果如下圖:
即使對(duì)象的內(nèi)容沒(méi)發(fā)生改變,指針改變也是不允許的站玄。
26.ES6新的特性有哪些枚驻?x4
1、let const命令
2株旷、解構(gòu)賦值
3再登、字符串方法模板字符串
4、默認(rèn)函數(shù)晾剖、剩余函數(shù)锉矢、箭頭函數(shù)
5、Symbol
6齿尽、Set和Map
7沽损、模塊化
8、promise
9循头、class繼承
10绵估、數(shù)組的擴(kuò)展
27.Promise對(duì)象
28.用es6 promise實(shí)現(xiàn)封裝XMLHttpRequest
只需創(chuàng)建一個(gè)Promise對(duì)象,調(diào)用它的resolve()和reject()以及then()方法卡骂,then()里面也可以寫箭頭函數(shù)国裳;
function verifyIdCard(idCardOptions) {
let options = {
// url: config.idCardKey.idCardHost + '?idCard=' + idCardOptions.idCard + '&name=' + idCardOptions.name,
url: 'https://idcert.market.alicloudapi.com/idcard',
method: 'GET',
qs: {
idCard: idCardOptions.idCard,
name: idCardOptions.name
},
headers: {
'cache-control': 'no-cache',
Authorization: 'APPCODE ' + config.idCardKey.idCardAppCode,
'Content-Type': 'application/json'
},
json: true
};
console.info(options)
return new Promise((resolve, reject) => {
request(options, (error, response, body) => {
if (!error && (response.statusCode === 200 || response.statusCode === 304)) {
let IdCardInfo = {
reqInfo: idCardOptions,
resInfo: body
}
console.info(IdCardInfo)
let idCardModel = new IdCardModel(IdCardInfo);
idCardModel.save();
resolve(body);
} else {
reject(error);
}
})
})
}
29.generator(異步編程、yield全跨、next()缝左、await 、async)
Generator 函數(shù)浓若,可以通過(guò) yield 關(guān)鍵字渺杉,把函數(shù)的執(zhí)行流掛起,為改變執(zhí)行流程提供了可能七嫌,從而為異步編程提供解決方案少办。Generator 有兩個(gè)區(qū)分于普通函數(shù)的部分:一是在 function 后面,函數(shù)名之前有個(gè) * 诵原;函數(shù)內(nèi)部有 yield 表達(dá)式英妓。其中 * 用來(lái)表示函數(shù)為 Generator 函數(shù)挽放,yield 用來(lái)定義函數(shù)內(nèi)部的狀態(tài)。
function* sendParameter(){
console.log("strat");
var x = yield '2';
console.log("one:" + x);
var y = yield '3';
console.log("two:" + y);
console.log("total:" + (x + y));
}
var sendp1 = sendParameter();
sendp1.next();
// strat
// {value: "2", done: false}
sendp1.next();
// one:undefined
// {value: "3", done: false}
sendp1.next();
// two:undefined
// total:NaN
// {value: undefined, done: true}
var sendp2 = sendParameter();
sendp2.next(10);
// strat
// {value: "2", done: false}
sendp2.next(20);
// one:20
// {value: "3", done: false}
sendp2.next(30);
// two:30
// total:50
// {value: undefined, done: true}
}
一般情況下蔓纠,next 方法不傳入?yún)?shù)的時(shí)候辑畦,yield 表達(dá)式的返回值是 undefined 。當(dāng) next 傳入?yún)?shù)的時(shí)候腿倚,該參數(shù)會(huì)作為上一步y(tǒng)ield的返回值纯出。yield* 表達(dá)式表示 yield 返回一個(gè)遍歷器對(duì)象,用于在 Generator 函數(shù)內(nèi)部敷燎,調(diào)用另一個(gè) Generator 函數(shù)暂筝。
async
async 是 ES7 才有的與異步操作有關(guān)的關(guān)鍵字,和 Promise 硬贯, Generator 有很大關(guān)聯(lián)的焕襟。async 函數(shù)返回一個(gè) Promise 對(duì)象,可以使用 then 方法添加回調(diào)函數(shù)饭豹。
async function helloAsync(){
return "helloAsync";
}
console.log(helloAsync()) // Promise {<resolved>: "helloAsync"}
helloAsync().then(v=>{
console.log(v); // helloAsync
})
await
await 操作符用于等待一個(gè) Promise 對(duì)象, 它只能在異步函數(shù) async function 內(nèi)部使用鸵赖。返回 Promise 對(duì)象的處理結(jié)果。如果等待的不是 Promise 對(duì)象拄衰,則返回該值本身它褪。如果一個(gè) Promise 被傳遞給一個(gè) await 操作符,await 將等待 Promise 正常處理完成并返回其處理結(jié)果翘悉。
function testAwait (x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
async function helloAsync() {
var x = await testAwait ("hello world");
console.log(x);
}
helloAsync ();
// hello world
正常情況下茫打,await 命令后面是一個(gè) Promise 對(duì)象,它也可以跟其他值镐确,如字符串包吝,布爾值,數(shù)值以及普通函數(shù)源葫。await針對(duì)所跟不同表達(dá)式的處理方式:Promise 對(duì)象:await 會(huì)暫停執(zhí)行诗越,等待 Promise 對(duì)象 resolve,然后恢復(fù) async 函數(shù)的執(zhí)行并返回解析值息堂。非 Promise 對(duì)象:直接返回對(duì)應(yīng)的值嚷狞。