1.es5和es6的區別,說一下你所知道的es6
ECMAScript5,即ES5,是ECMAScript的第五次修訂,於2009年完成標准化
ECMAScript6,即ES6,是ECMAScript的第六次修訂,於2015年完成,也稱ES2015
ES6是繼ES5之后的一次改進,相對於ES5更加簡潔,提高了開發效率
ES6新增的一些特性:
1)let聲明的變量和const聲明的常量,兩個都有塊級作用域ES5中是沒有塊級作用域的,並且var有變量提升,在let中
使用的變量一定要進行聲明。
2)箭頭函數ES6中的函數定義不再使用關鍵字function(),而利用了()=>來進行定義
3)模板字符串是增強版的字符串,用(`)標識,可以當做普通字符串使用,也可以用來定義多行字符串
4)解構賦值ES6中允許按照一定模式,從數組和對象中提取值,對變量進行賦值。
5)for of 循環和for ...of 循環可以遍歷數組、Set和Map結構、某些類似數組的對象、對象,以及字符串。
6)import、export導入導出ES6標准中,JS原生支持模塊(module)。將JS代碼分隔成不同功能的小塊進行模塊化,
將不同功能的代碼分別寫在不同的文件中,各模塊只需導出公共接口的部分,然后通過模塊的導入的方式可以在其他地方使用。
7)set數據結構,類似數組。所有的數據都是唯一的,沒有重復的值。他本身就是一個構造函數。
8)...展開符可以將數組或對象里面的值展開;還可以將多個值收集為一個變量。
9)修飾器@decorator是一個函數,用來修改類甚至方法的行為,修飾器本質就是編譯時執行的函數
10)class類的繼承ES6中不再像ES5一樣使用原型鏈實現繼承,而是引入Class這個概念。
11)async、await使用async/await,搭配promise,可以通過編寫形似同步的代碼來處理異步流程,提高代碼的簡潔性和可讀性async用於聲明一個function是異步的,而await用於等待一個異步方法執行完成。
12)promise是異步編程的一種解決方案,比傳統的解決方案(回調函數和事件)更合理、強大。
13)Symbol是一種基本類型。Symbol通過調用symbol函數產生,他接收一個可選的名字參數,該函數返回的symbol是唯一的。
14)Proxy代理使用代理(Proxy)監聽對象的操作,然后可以做一些相應的事情。
2.var、let、const之間的區別
var 聲明的變量可以重復聲明,而let不可以重復聲明。
var 是不受限於塊級的,而let是受限於塊級的。
var 會與window相映射(會掛一個屬性),而let不與window相映射。
var 可以在聲明的上面訪問變量,而let有暫存死區,在聲明的上面訪問變量會報錯。
const和let一樣不會與window相映射,支持塊級作用域、在聲明的上面訪問變量會報錯。
3.使用箭頭函數應注意什么?
(1)用了箭頭函數,this就不是指向window,而是父級(指向是可變的)。
(2)不能使用arguments對象。
(3)不能用作構造函數,這就是說不能夠使用new命令,否則會拋出一個錯誤。
(4)不可以使用yield命令,因此箭頭函數不能用作Generator函數
4.ES6的模板字符串有哪些新特性?並實現一個類模板字符串的功能。
基本的字符串格式化。將表達式嵌入字符串中進行拼接。用${}來界定。
在ES5時我們通過反斜杠()來做多行字符串或者字符串一行行拼接。ES6反引號(``)就能解決。
類模板字符串的功能
let name='web';
let age=10;
let str=`你好,${name}已經${age}歲了`
str=str.replace(/\$\{([^}]*)\}/g,function(){
return eval(arguments[1]);
})
console.log(str);//你好,web已經10歲了
5.介紹下Set、Map的區別?
應用場景Set用於數據重組,Map用於數據存儲。
Set:
(1)成員不能重復
(2)鍵值沒有鍵名,類似數組(3)可以遍歷,方法有add,delete,has
Map:
(1)本質上是鍵值對的集合,類似集合
(2)可以遍歷,可以跟各種數據格式轉換。
6.ECMAScript 6怎么寫calss,為何會出現class?
ES6的class可以看做是一個語法糖,他的絕大部分功能ES5都可以做到。新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法。
//定義類
class Point{
constructor(x,y){
//構造方法
this.x=x;//this關鍵字代表實例對象
this.y=y;
} toString(){
return '(' +this.x + ',' +this.y + ')';
}
}
7.Promise構造函數時同步執行還是異步執行,那么then方法呢?
promise構造函數時同步執行的,then方法是異步執行的
8.setTimeout、Promise、Async/Await的區別?
事件循環中分為宏任務隊列和微任務隊列
其中setTimeout的回調函數放到宏任務隊列里,等到執行棧清空以后執行。
promise.then里的回調函數會放到相應宏任務的微任務隊列里,等宏任務里面的同步代碼執行完再執行。
async函數表示函數里面可能會有異步方法,await后面跟一個表達式。
async方法執行時,遇到await會立即執行表達式,然后把表達式后面的代碼放到微任務隊列里,讓出執行棧讓同步代碼先執行。
9.promise有幾種狀態,什么時候會進入catch?
三個狀態:pending、fulfilled、reject
兩個過程:pedding->fulfilled、pedding->rejected
當pending為rejected時,會進入catch
10.下面的輸出結果是多少?
const promise =new Promise((resolve,reject)=>{
console.log(1);
resolve();
console.log(2);
})
promise.then(()=>{
console.log(3);
})
console.log(4);
Promise新建后立即執行,所以會先輸出1,2而Promise.then()內部的代碼在當次事件循環的結尾立刻執行,所以會繼續輸出4,最后輸出3
11.使用結構賦值,實現兩個變量的值的交換。
let a=1; let b=2;
[a,b] =[b,a];
12.設計一個對象,鍵名的類型至少包含一個symbol類型,並且實現遍歷所有key
let name=Symbol('name');
let product={
[name]:"洗衣機",
"price":799
};
Reflect.ownKeys(product);
13.下面Set結構,打印出來的size值是多少
let s=newSet();
s.add([1]);
s.add([1]);
console.log(s.size);
答案:2
兩個數組[1]並不是同一個值,他們分別定義的數組,在內存中分別對應着不同的存儲地址,因此並不是相同的值。
都能存儲到Set結構中,所以size為2。
14.Promise中reject和catch處理上有什么區別?
reject是用來拋出異常的,catch是用來處理異常。
reject是Promise的方法,而catch是Promise實例的方法。
reject后的東西,一定會進入then中的第二個回調,如果then中沒有寫第二個回調,則進入catch
網絡異常(比如斷網),會直接進入catch而不會進入then的第二個回調。
15.使用class手寫一個Promise
//創建一個Promise的類
class Promise{
constructor(executer){//構造函數constructor里面是個執行器
this.status='pending';//默認的狀態 pending
this.value=undefined //成功的值默認undefined
this.reason=undefined //失敗的值默認undefined
//狀態只有在pending時候才能改變
let resolveFn= value =>{
//判斷只有等待時才能resolve成功
if(this.status==pending){
this.status='resolve';
this.value=value;
}
}
try{
//把resolve和reject兩個函數傳給執行器executer
executer(resolve,reject);
}.catch(e){
reject(e);//失敗的話進catch
}
}
then(onFufilled.onReject){
//如果狀態成功回調用onFufilled
if(this.status='resolve'){
onFufilled(this.value);
}
//如果狀態失敗調用onReject
if(this.status = 'reject' ){
onReject(this.reason);
}
}
}
16.如何使用Set去重
let arr=[12,43,23,43,68,12];
let item=[...new Set(arr)];
console.log(item);//[12,43,23,68]
17.將下面for循環改成for of 形式
let arr=[11,22,33,44,55];
let sum=0;
for(let i=0;i<arr.length;i++){
sum+=arr[i];
}
答案:
let arr=[11,22,33,44,55];
let sum=0;
for(value of arr){
sum+=value;
}
18.理解async/await以及對Generator的優勢
async await是用來解決異步的,async函數是Generator函數的語法糖
使用關鍵字async來表示,在函數內部使用await來表示異步。
async函數返回一個Promise對象,可以使用then方法添加回調函數
當函數執行的時候,一旦遇到await就會先返回,等到異步操作完成,再接着執行函數體內后面的語句
async較Generator優勢:
(1)內置執行器,Generator函數的執行必須依靠執行器,而Aysnc函數自帶執行器,調用方式跟普通函數的調用一樣。
(2)更好的語義。async和await相較於*和yield更加語義化
(3)更廣的適用性。yield命令后面只能是Thunk函數或Promise對象,async函數的await后面可以是Promise也可以是原始類型的值
(4)返回值是Promise,async函數返回的是Promise對象,比Generator函數返回的lterator對象方便,可以直接使用then()方法進行調用。
19.forEach、for in、for of 三者區別
forEach更多的用來遍歷數組
for in 一般用來遍歷對象或json
for of 數組對象都可以遍歷,遍歷對象需要通過和Object.keys()
for in 循環出的是key,for of 循環的是value
20.說一下es6的導入導出模塊
導入通過import關鍵字
//導入通過import關鍵字
import {sum} from "./example.js"
//導入多個
import {sum.multiply.time} from "./exportExample.js"
//導入一整個模塊
import * as example from "./exportExample.js"
//導出通過export關鍵字
//可以將export放在任何變量,函數或類聲明的前面
export var firstName ='Michael';
export var lastName='Jackson';
export var year=1958;
//也可以使用大括號指定所要輸出的一組變量
var firstName='Michael';
var lastName='Jackson';
var year=1958;
export {firstName,lastName,year};
//使用export default時,對應的import語句不需要使用大括號
let bosh=function crs( ){ }
export default bosh;
import crc from 'crc';
//不使用export default 時,對應的import語句不需要使用大括號
let bosh=function crs( ){ }
export bosh;
import {crc} from 'crc';