面試中常問到的ES6
技術標籤:面試題ES6javascriptjs
目的
1、熟練使用ES6語言
2、Promise物件
什麼是ES6
ES6:全稱ECMAScript 6.0 ,是JavaScript的下一個版本標準,2015.06發版。
ES6主要是為了解決ES5的先天不足,比如JavaScript裡並沒有類的概念
Let、const和var的區別
Es6新增了let和const來宣告變數,主要是解決var宣告變數所造成的困擾和問題:
- var 不能用於定義常量
- var 可以重複宣告變數
- var 存在變數提升
- var 不支援塊級作用域
let 和const解決了以上問題如下:
- 不可以重複宣告變數
let site = 'itLike';
let site = 'itLike';
console.log(site);
- 不存在變數提升
console.log(site);
let site = 'itLike';
- 可以定義常量
const E = 2.718;
E = 2.71;
console.log(E);
// 引用型別
const LK = {
name:'itLike',
intro: '喜歡IT, 就上撩課(itLike.com)'
};
LK.name = '撩課';
console.log(LK);
- 塊級作用域
如果用var定義變數,變數是通過函式或者閉包擁有作用域;但,現在用let定義變數,不僅僅可以通過函式/閉包隔離,還可以通過塊級作用域隔離。
{let site = 'itLike';}
console.log(site);
if(1){ let str = '04'; }
console.log(str);
解構賦值
解構賦值是對賦值運算的擴充套件
他是一種針對陣列或物件進行模式匹配,然後對其中的變數進行賦值。
在程式碼書寫上簡潔易讀,語義更加清晰明瞭;也方便了複雜物件中資料欄位獲取。
- 構的源,解構賦值表示式的右邊部分。
- 解構的目標,解構賦值表示式的左邊部分。
## 變數解構賦值(陣列解構)
let nameArr = ['撩課', '小撩', '小煤球'];
let name1 = nameArr[0];
let name2 = nameArr[1];
let name3 = nameArr[2];
// 解構寫法
let [name1, name2, name3] = nameArr;
console.log(name1, name2, name3);
## 變數解構賦值(物件解構)
// 寫法1
let {name, age, sex}
= {name: '小煤球', age: 1, sex: '公'};
// 結果: 小煤球 1 公
console.log(name, age, sex);
// 寫法2: 解構重新命名
let {name: lkName, age: lkAge, sex: lkSex}
= {name: '小煤球', age: 1, sex: '公'};
// 結果: 小煤球 1 公
console.log(lkName, lkAge, lkSex);
// 寫法3: 可以設定預設值
let {name, age, sex = '公'}
= {name: '小煤球', age: 1};
console.log(sex); // 公
// 寫法4:省略解構
let [, , sex] = ['小煤球', 1, '公 '];
console.log(sex);
字串、正則、數值、函式、陣列、物件的擴充套件、箭頭函式和普通函式區別
模板字串
模板字串用反引號()包含,變數用${}括起來;在開發中使用是非常靈活的
let name = '小煤球';
let sex = '公';
let result = `我叫 ${name} , 我是 ${sex} 的`;
console.log(result);
字串擴充套件方法
- startsWith()
判斷字串是否以xx開頭;
let url = 'http://www.itlike.com';
console.log(url.startsWith('http')); // true
- endsWith()
判斷字串是否以xx結尾
let file = 'index.html';
console.log(file.endsWith('html')); // true
- includes
判斷字串中是否包含xx;
let str = 'liaoke';
console.log(str.includes('ao')); // true
- repeat()
拷貝n份
let title = '撩課線上';
console.log(title.repeat(100));
- padStart() / padEnd()
padStart()用於頭部補全,
padEnd()用於尾部補全;
第一個引數用來指定字串的最小長度,
第二個引數是用來補全的字串。
// "2030111111"
let y1 = '2030'.padEnd(10, '1');
// "2030-11-22"
let y2 = '11-22'.padStart(10, '2030-MM-DD');
console.log(y1, y2);
延展操作符
- 延展陣列
let arr1 = [ 'a', 'b', 'c'];
let arr2 = [1, 2, 3];
let result = [...arr1, ...arr2];
console.log(result);
// [ "a", "b", "c", 1, 2, 3 ]
- 延展物件
let smallDog = {name:'小煤球', age: 1};
let bigDog = {name: 'Python', age: 2};
let dog = {...smallDog, ...bigDog};
console.log(dog);
// {name: "Python", age: 2}
注意:如果物件中的屬性一致,會被覆蓋
- 開發應用場景
function getMinValue() {
console.log(Math.min(...arguments));
}
getMinValue(1, -99, 22, 10, 9); // -99
數值擴充套件
- 常量
Number.EPSILON ,屬性表示 1 與大於 1 的最小浮點數之間的差。
它的值接近於 2.2204460492503130808472633361816E-16,或者 2-52。
測試數值是否在誤差範圍內:
0.1 + 0.2 === 0.3; // false
// 在誤差範圍內即視為相等
var equal = (Math.abs(0.1 - 0.3 + 0.2) < Number.EPSILON); // true
- 最大安全整數
安全整數:Number.MAX_SAFE_INTEGER
安全整數表示在 JavaScript 中能夠精確表示的整數,安全整數的範圍在 2 的 -53 次方到 2 的 53 次方之間(不包括兩個端點),超過這個範圍的整數無法精確表示。
最大安全整數
安全整數範圍的上限,即 2 的 53 次方減 1 。 - 最小安全整數
安全整數範圍的下限,即 2 的 53 次方減 1 的負數。
Number.MIN_SAFE_INTEGER
Math物件的擴充套件
Es6在Math物件上新增了17個屬性相關的靜態方法,這些方法只能在math中呼叫
- 普通計算
math.cdrt
用於計算一個數的立方根
Math.cbrt(1); // 1
Math.cbrt(0); // 0
Math.cbrt(-1); // -1
// 會對非數值進行轉換
Math.cbrt('1'); // 1
// 非數值且無法轉換為數值時返回 NaN
Math.cbrt('hhh'); // NaN
等等…此處需要自己查百度了 哈哈
函式擴充套件
- 預設引數
基本用法:
function fn(name,age=17){
console.log(name+","+age);
}
fn("Amy",18); // Amy,18
fn("Amy",""); // Amy,
fn("Amy"); // Amy,17
注意點:使用函式預設引數時,不允許有同名引數。
// 不報錯
function fn(name,name){
console.log(name);
}
// 報錯
//SyntaxError: Duplicate parameter name not allowed in this context
function fn(name,name,age=17){
console.log(name+","+age);
}
只有在未傳遞引數,或者引數為 undefined 時,才會使用預設引數,null 值被認為是有效的值傳遞。
function fn(name,age=17){
console.log(name+","+age);
}
fn("Amy",null); // Amy,null
函式引數預設值存在暫時性死區,在函式引數預設值表示式中,還未初始化賦值的引數值無法作為其他引數的預設值。
function f(x,y=x){
console.log(x,y);
}
f(1); // 1 1
function f(x=y){
console.log(x);
}
f(); // ReferenceError: y is not defined
- 不定引數
不定引數用來表示不確定引數個數,刑如, …變數名,由…加上一個具名引數識別符號組成。具名引數只能放在引數組的最後,並且有卻只有一個不定引數。
基本用法:
function f(...values){
console.log(values.length);
}
f(1,2); //2
f(1,2,3,4); //4
箭頭函式
箭頭漢提供了一種更加簡潔的函式書寫方式。基本語法是:
引數=>函式體
function 函式名稱(引數列表){
函式執行體
}
this指標的固化
var函式名稱 = (引數列表)=>{
函式執行體
}
基本用法:
var f = v => v;
//等價於
var f = function(a){
return a;
}
f(1); //1
當箭頭函式沒有引數或者有多個引數,要用()括起來.
var f = (a,b) => a+b;
f(6,2); //8
當箭頭函式函式體有多行語句,用{}包裹起來,表示程式碼塊,當只有一行語句,並且需要返回結果時,可以省略{},結果會自動返回。
var f = (a,b) => {
let result = a+b;
return result;
}
f(6,2); // 8
- 單行語句返回形式
當箭頭函式要返回物件的時候,為了區分於程式碼塊,要用()將物件包裹起來
// 報錯
var f = (id,name) => {id: id, name: name};
f(6,2); // SyntaxError: Unexpected token :
// 不報錯
var f = (id,name) => ({id: id, name: name});
f(6,2); // {id: 6, name: 2}
注意點:沒有 this、super、arguments 和 new.target 繫結。
var func = () => {
// 箭頭函式裡面沒有 this 物件,
// 此時的 this 是外層的 this 物件,即 Window
console.log(this)
}
func(55) // Window
var func = () => {
console.log(arguments)
}
func(55); // ReferenceError: arguments is not defined
箭頭函式體中的 this 物件,是定義函式時的物件,而不是使用函式時的物件。
function fn(){
setTimeout(()=>{
// 定義時,this 繫結的是 fn 中的 this 物件
console.log(this.a);
},0)
}
var a = 20;
// fn 的 this 物件為 {a: 19}
fn.call({a: 18}); // 18
var a = {
a: 18,
fn:function(){
setTimeout(()=>{
// 定義時,this 繫結的是 fn 中的 this 物件
console.log(this.a);
},0)
}
}
// call():
//將該函式的定義放到傳入的物件下
//呼叫
不可以作為建構函式,也就是不能使用 new 命令,否則會報錯
- 箭頭函式適合使用的場景
ES6 之前,JavaScript 的 this 物件一直很令人頭大,回撥函式,經常看到 var self = this 這樣的程式碼,為了將外部 this 傳遞到回撥函式中,那麼有了箭頭函式,就不需要這樣做了,直接使用 this 就行。
// 回撥函式
var Person = {
'age': 18,
'sayHello': function () {
setTimeout(function () {
console.log(this.age);
});
}
};
var age = 20;
Person.sayHello(); // 20
var Person1 = {
'age': 18,
'sayHello': function () {
setTimeout(()=>{
console.log(this.age);
});
}
};
var age = 20;
Person1.sayHello(); // 18
所以,當我們需要維護一個 this 上下文的時候,就可以使用箭頭函式。
陣列擴充套件
- 陣列建立
Array.of()
將引數中所有值作為元素形成陣列
console.log(Array.of(1, 2, 3, 4)); // [1, 2, 3, 4]
// 引數值可為不同型別
console.log(Array.of(1, '2', true)); // [1, '2', true]
// 引數為空時返回空陣列
console.log(Array.of()); // []
- Array.from()
將類陣列物件或可迭代物件轉化為陣列。
// 引數為陣列,返回與原陣列一樣的陣列
console.log(Array.from([1, 2])); // [1, 2]
// 引數含空位
console.log(Array.from([1, , 3])); // [1, undefined, 3]
引數
Array.from(arrayLike[, mapFn[, thisArg]])
返回值為轉換後的陣列。
- arrayLike
想要轉換的類陣列物件或可迭代物件。
console.log(Array.from([1, 2, 3])); // [1, 2, 3]
- mapFn
可選,map 函式,用於對每個元素進行處理,放入陣列的是處理後的元素。
console.log(Array.from([1, 2, 3], (n) => n * 2)); // [2, 4, 6]
- thisArg
可選,用於指定 map 函式執行時的 this 物件。
let map = {
do: function(n) {
return n * 2;
}
}
let arrayLike = [1, 2, 3];
console.log(Array.from(arrayLike, function (n){
return this.do(n);
}),map); // [2, 4, 6]
- 類陣列物件
一個類陣列物件必須含有 length 屬性,且元素屬性名必須是數值或者可轉換為數值的字元。
let arr = Array.from({
0: '1',
1: '2',
2: 3,
length: 3
});
console.log(); // ['1', '2', 3]
// 沒有 length 屬性,則返回空陣列
let array = Array.from({
0: '1',
1: '2',
2: 3,
});
console.log(array); // []
// 元素屬性名不為數值且無法轉換為數值,返回長度為 length 元素值為 undefined 的陣列
let array1 = Array.from({
a: 1,
b: 2,
length: 2
});
console.log(array1); // [undefined, undefined]
- 轉換可迭代物件
轉換map
let map = new Map();
map.set('key0', 'value0');
map.set('key1', 'value1');
console.log(Array.from(map)); // [['key0', 'value0'],['key1',
// 'value1']]
- 轉換set集合
let arr = [1, 2, 3];
let set = new Set(arr);
console.log(Array.from(set)); // [1, 2, 3]
- 轉換字串
let str = 'abc';
console.log(Array.from(str)); // ["a", "b", "c"]
- 擴充套件的方法
查詢
1、find()
查詢陣列中符合條件的元素,若有多個符合條件的元素,則返回第一個元素。
2、findIndex()
查詢陣列中符合條件的元素索引,若有多個符合條件的元素,則返回第一個元素索引。
3、fill()填充
將一定範圍索引的陣列元素內容填充為單個指定的值。
4、entries()遍歷
遍歷鍵值對。
5、keys()
遍歷鍵名。
6、includes()包含
陣列是否包含指定值。
注意:與 Set 和 Map 的 has 方法區分;Set 的 has 方法用於查詢值;Map 的 has 方法用於查詢鍵名
7、flat()巢狀陣列轉一維陣列
8、flatMap()
先對陣列中每個元素進行了的處理,再對陣列執行 flat() 方法。
iterator 和 for …of 迴圈
Iterator 是 ES6 引入的一種新的遍歷機制,迭代器有兩個核心概念:
- 迭代器是一個統一的介面,它的作用是使各種資料結構可被便捷的訪問,它是通過一個鍵為Symbol.iterator 的方法來實現。
- 迭代器是用於遍歷資料結構元素的指標(如資料庫中的遊標)。
迭代器是帶有特殊介面的物件。含有一個next()方法,呼叫返回一個包含兩個屬性的物件,分別是value和done,value表示當前位置的值,done表示是否迭代完,當為true的時候,呼叫next就無效了。
ES5中遍歷集合通常都是 for迴圈,陣列還有 forEach 方法,物件就是 for-in,ES6 中又添加了 Map 和 Set,而迭代器可以統一處理所有集合資料的方法。迭代器是一個介面,只要你這個資料結構暴露了一個iterator的介面,那就可以完成迭代。ES6創造了一種新的遍歷命令for…of迴圈,Iterator介面主要供for…of消費。
for遍歷
const fruits = ['apple','coconut','mango','durian'];
//for迴圈陣列,通過下標取得每一項的值
for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
}
forEach遍歷
//陣列的forEach方法,相對for迴圈語法更簡單
fruits.forEach(fruit => {
console.log(fruit);
})
//forEach有個問題是不能終止迴圈
fruits.forEach(fruit => {
if(fruit === 'mango' ){
break; //Illegal break statement
}
console.log(fruit);
})
for in 遍歷
//for...in迴圈,遍歷陣列物件的屬性,MDN不推薦使用for...in遍歷陣列
//for...in迴圈會打印出非數字屬性
const fruits = ['apple','coconut','mango','durian'];
fruits.fav = 'my favorite fruit';
for(let index in fruits){
console.log(fruits[index]); //...my favorite fruit
}
for of 遍歷
const fruits = ['apple','coconut','mango','durian'];
fruits.fav = 'my favorite fruit';
//ES6中的for...of迴圈,遍歷屬性值
for(let fruit of fruits){
console.log(fruit);
}
//支援終止迴圈,也不會遍歷非數字屬性
for(let fruit of fruits){
if(fruit === 'mango' ){
break;
}
console.log(fruit); //apple coconut durian
}
set和map資料結構
基本用法
set 資料容器 能夠儲存無重複值資料的有序列表
- 通過 new set() 方法建立容器 通過add() 方法新增
- set.size獲取儲存的資料的數量
var set = new Set()
set.add(1);
set.add('1');
console.log(set)
console.log(set.size)
- Set內部使用Object.is()方法來判斷兩個資料項是否相等
- 利用陣列來構造set 且set 構造器不會存在重複的資料
var set1 = new Set([1,2,3,3,3,3,3,2]) // 結果陣列會去重
- 可以使用has()方法來判斷某個值是否存在於Set中
- 使用delete()方法從Set中刪除某個值,或者使用clear()方法從Set中刪除所有值
set1.delete(1)
console.log(set1)
set1.clear()
console.log(set1)
- forEach 遍歷set
set2.forEach(function(value,key){
console.log(value)
console.log(key)
})
- 將陣列轉換成set 直接將陣列放在new Set()引數中
ES6中提供了Map資料結構,能夠存放鍵值對,其中,鍵的去重是通過Object.is()方法進行比較,鍵的資料型別可以是基本型別資料也可以是物件,而值也可以是任意型別資料。
- 建立map
var map = new Map()
- 使用set()方法可以給Map新增鍵值對 ,能夠自動去重,和set原理一樣,新增相同的元素會進行去重處理
var map = new Map()
console.log(map)
map.set('title','baidu')
map.set('year','2018');
- 通過get()方法可以從Map中提取值,size方法同set一樣,獲取陣列長度
console.log(map.get('year')) // 2018
console.log(map.size) // 2
- 同set一樣,也有 has(),delete(),clear() 方法
map.delete('title');
map.clear();
console.log(map.has('year'));
- 通過get()方法可以從Map中提取值,size方法同set一樣,獲取陣列長度
console.log(map.get('year')) // 2018
console.log(map.size) // 2
- forEach 遍歷
map.forEach(function(value,key){
console.log(value) // 值 2018
console.log(key) // 健 year
})
set和map的區別
都是用來儲存資料用的,但是儲存的資料格式不同
set 直接儲存 任意型別資料
map 儲存資料的時候,必須以key,value的形式,
set 使用forEach 遍歷的時候,key和value值是一樣的
而map 遍歷的時候,key就是存進去的物件的key,value就是存在的值
Promise
首先要明白什麼是Promise
Promise:是非同步程式設計的一種解決方法
如果去使用???
-
主要用於非同步計算
首先我們先new一個promise(裡面放入兩個引數 resclve和reject)
-
可以將非同步操作佇列化,按照期望的順序進行
-
可以在物件之間傳遞promise,幫助我們處理佇列化
-
引數分別是:resolve 和 reject
resolve()的作用是,將promise從未完成變為完成,非同步操作成功時呼叫,結果傳遞出去
Reject()作用是,將promise狀態從未完成變為失敗,並將非同步操作的錯誤,傳遞出去
promise 有三個狀態:
1、pending ()是 初始狀態
2、fulfilled ()是 操作成功的狀態
3、Rejected()是 操作失敗的狀態
當 promise 狀態發生改變,就會觸發 then()裡的響應函式處理後續步驟
promise 狀態一經改變,不會再變
使用場景:promise封裝api介面
Promise進行非同步操作
解決問題:1.回撥地域問題2.多個併發請求