年前年後跳槽季,準備從面試內容入手看看前端相關知識點,旨在探究一個系列知識點,能力範圍以內的深刻探究一下。重在實踐,針對初級前端和準備面試的同窗,爭取附上實際的代碼例子以及相關試題~系列名字就用【禿破前端面試】—— 由於圈內你們共識,技術與髮量成正比。😄但願你們早日 禿 破瓶頸前端
關於面試題或者某個知識點的文章太多了,這裏筆者只是想把我的的總結用代碼倉庫的形式記錄下來並輸出文章,畢竟理論不等於實踐,知其然也要知其因此然,實踐用過才能真正理解~ react
相關係列文章:git
說實話,ES6+ 新特性被寫成文章已經爛大街了,寫得好的有不少,因此若是你看過別人寫的很是好的新特性文章,就能夠不看這篇,我只是爲了完整性就對應着寫一下,簡單的將各類 API 經過代碼使用一下。由於新前端三劍客 HTML5 和 CSS3 都寫完了,就不差這一個了。es6
ES6+ 新特性就是指 ES6(也叫 ES2015) 之後更新的全部 JavaScript 標準規範新增的 API。由於 ES6 是一個劃時代的更新,而且 ES6 以後每次迭代更新內容都比較少,因此就統稱爲 ES6+ 了。相對的 ES5 就是本來的 JS 語法,而現今不少框架設計也都是使用 ES6 標準語法進行書寫,ES6+ 語法能夠經過 babel 編譯成 ES5 語法。github
目前,ES6+ 已經更新到最新的 ES10 草案。面試
這兩個關鍵字對應一個名詞,也就是塊級做用域。ES5 以前是沒有塊級做用域這個概念的,而且定義變量也都是經過var
來進行聲明。var
生命的變量是函數級做用域。編程
函數做用域含義:屬於這個函數的所有變量均可以在整個函數的範圍內使用及複用(在嵌套的做用域中也可使用)。redux
var a = 1;
var b = 1;
function foo () {
var a = 2;
console.log('foo:', a, b); // 2, 1
}
console.log('windoiw:', a, b); // 1, 1
複製代碼
{
let c = 1;
let d = 1;
console.log('scope:', c, d); // 1, 1
}
function foo2 () {
let c = 2;
let d = 2;
console.log('foo2:', c, d); // 2, 2
}
foo2();
console.log('window:', c, d); // undefined, undefined
複製代碼
const aa = 1;
aa = 2; // Uncaught TypeError: Assignment to constant variable.
const bb = {};
bb.a = 1;
console.log(bb);
const cc = [];
cc.push(1);
console.log(cc);
const dd = null;
dd = 1;
console.log(dd); // Uncaught TypeError: Assignment to constant variable.
複製代碼
const 的用法與 let 基本一致,只不過 const 定義的是常量,不能被修改。而若是const 定義的是對象或者數組,則仍是能夠改的,由於兩者屬於引用類型,存儲的是地址指針,也就是說 const 表明的是變量地址不能被修改。const 定義一個 null 值也是不能被更改的,由於還沒被分配內存地址。數組
var 定義的變是函數做用域,沒有塊的概念,能夠跨塊訪問, 不能跨函數訪問。bash
let 定義的變量是塊級做用域,只能在塊做用域裏訪問,不能跨塊訪問,也不能跨函數訪問。
const 用來定義常量,使用時必須初始化(即必須賦值),只能在塊做用域裏訪問,並且不能修改。
常用 React 的同窗應該很是的瞭解,class 用來聲明類組件。而 class 就是 ES6 的語法。而 class 其實也能夠換種說法是 ES5 繼承的一個語法糖,class 特性可使用 ES5 語法所有實現,只不過 class 更爲便捷。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
say() {
const sayStr = `Hello, my name is ${this.name}, ${this.age} years old! I'm Person`; console.log(sayStr); } } class Chinese extends Person { constructor(name, age) { super(name, age); this.country = 'Chinese'; } say() { const sayStr = `Hello, my name is ${this.name}, ${this.age} years old! I'm ${this.country} Person`;
console.log(sayStr);
}
}
/* ES6 class */
const person = new Person('luffy', 28);
const chinesePerson = new Chinese('周', 33);
person.say();
chinesePerson.say();
複製代碼
這裏有個注意點就是,若是是子類繼承父類,那麼子類的constructor
內部必須有super()
,不然會報錯,以下圖:
箭頭函數,ES6 最有特色的一個特性,讓代碼看起來簡潔了不少,而且也解決了 this 指針的問題。
() => console.log(1);
const a = () => 1;
const add = (a, b) => a + b;
const resFunc = (a, b) => () => a + b; // 返回一個函數
複製代碼
var scope = 'window';
var obj = {
scope: 'obj',
funcScope: function() {
console.log('當前做用域:', this.scope);
},
arrayFuncScope: () => console.log('當前做用域:', this.scope)
}
var obj2 = {
scope: 'obj2'
}
obj.funcScope(); // obj
obj.arrayFuncScope(); // window
obj.funcScope.call(obj2); // obj2
obj.arrayFuncScope.call(obj2); // window
複製代碼
能夠看到,箭頭函數與建立調用它的代碼所在做用域共享一個 this,上面代碼箭頭函數在調用的時候在第2個和第4個都是在 window 環境下,所以 this 就是 window。
關於模板字符串就是很簡單了,以下兩段代碼就很是的清晰。
/* 字符串 */
var name = 'luffyZh';
var es5Str = 'Hello ' + name;
const es6Str = `Hello ${name}`;
複製代碼
由上面代碼可知,ES5 使用符號進行拼接,而 ES6 的模板字符串能夠將變量嵌入字符串內,很是方便。
解構賦值也是 ES6 新特性中被使用很是頻繁的一個,而且在實際開發過程當中用處很大。
// 對象解構
const obj = { name: 'luffy', email: 'luffy@163.com' };
const { name, email, age } = obj;
console.log(name, email, age); // luffy luffy@163.com undefined
複製代碼
// 數組解構
let [a, b, c] = [1, 2, 3];
console.log(a, b, c); // 1, 2, 3
let [aa, bb, cc] = [1, [2 , 3], [4, 5, 6]];
console.log(aa, bb, cc); // 1 [2, 3] [4, 5, 6]
複製代碼
// 解構應用 —— 一行代碼交換 a b 的值
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b); // 2, 1
複製代碼
這個也算是一個小語法糖吧,方便開發的時候快速簡潔。
var name = 'luffyzh';
var email = 'luffyzh@163.com';
var person = {
name,
email
};
console.log(person); // {name: 'luffyzh', email: 'luffyzh@163.com'}
複製代碼
ES6 爲咱們提供了新的模塊導入/導出規範。
import React from 'react';
import { useState } from 'react';
import * as Sentry from 'sentry';
複製代碼
export const foo = () => 1; // 引入的時候須要帶 {}
export default foo = () => 2; // 引入的時候不須要帶 {}
複製代碼
關於 Promise 的詳細介紹,能夠去另外一篇文章去查閱~禿破前端面試 —— Promise && Async/Await
ES6 的 Generator 也是一種異步編程解決方案,當初學的時候也是不理解,爲啥 ES6 要提供兩種異步方案,一個是 Promise 一個是 Generator,不過呢二者確實也都是被應用的十分普遍,各有千秋吧。
Generator 是一個迭代器生成函數,它被調用並不會當即執行,而是返回一個迭代器,而後能夠進行異步調用,同時還能夠掛起操做,很是的牛X可是使用起來也相對複雜。它有兩個特性:
function* testGenerator() {
yield 'a';
yield 'b';
return 'c';
}
var g = testGenerator();
複製代碼
如上圖所示,調用 Generator 函數它返回的是一個迭代器對象,而後經過調用此對象的方法.next()
來一步一步執行函數內部的狀態,每個 yield 關鍵字對應着一個狀態,而 yield 關鍵字則是表示在此處暫停執行的意思 (直到使用 next 調用),每一個狀態是一個對象有兩個屬性{value: 此狀態的值, done: 迭代器函數是否結束}
。
很是流行的 redux 異步處理方案 redux-saga 採用的就是 Generator 實現的。
dva 框架內置處理redux 異步也是使用 Generator 來進行處理的。
Set 對象是 ES6 爲咱們提供的一個新的數據結構,它是以鍵值對兒的形式存在,相似於 Map,可是區別在於 Set 對象具備自動去重的功能。
var setObj = new Set([1, 1, 2, 3, 4, 4]);
console.log(setObj); // {1, 2, 3, 4}
setObj.add(1); // {1, 2, 3, 4}
setObj.add(5); // {1, 2, 3, 4, 5}
setObj.keys(); // {1, 2, 3, 4, 5}
複製代碼
var arr = [1, 3, 3, 4, 5];
function uniqueArr(arr) {
return [...new Set(arr)];
// return Array.from(new Set(arr));
}
複製代碼
從上面能夠看出來以下幾點:
第一:Set 對象的構造函數能夠接收一個數組,而後主動去重。
第二:Set 對象返回的是一個對象,能夠經過Array.from
方法轉換成數組。
Symbol 是 ES6 新增的一種基礎數據類型,ES5 的時候,基礎類型只有五種,它們是:Number
、String
、Boolean
、null
和undefined
。而 ES6 新增了 Symbol
,因此 ES6 的時候,基本數據類型就變成了 6 種。
強調一下,Object 屬於複雜類型,並非基礎類型。
var a = 1;
var b = '2';
var c = false;
var d = {};
var e = null;
var f = undefined;
var g = Symbol();
console.log(typeof a); // number
console.log(typeof b); // string
console.log(typeof c); // boolean
console.log(typeof d); // object
console.log(typeof e); // object
console.log(typeof f); // undefined
console.log(typeof g); // symbol
複製代碼
Symbol 是用來建立惟一性變量的,使用 Symbol 能夠爲程序建立惟一性的 ID,在建立的時候能夠爲其新增參數描述該變量,即便參數相同兩個 Symbol 也是不一樣的。
var s1 = Symbol()
var s2 = Symbol('another symbol')
var s3 = Symbol('another symbol')
s1 === s2 // false
s2 === s3 // false
複製代碼
具體來講它的應用有以下幾種:
定義私有化方法頗有趣,咱們都知道,ES5 以前 JS 並無私有化方法,類的屬性和方法都是能夠被訪問的,之前也就是經過一些約定來實現,好比_
下劃線定義的是內部的,外部不要訪問,可是也不是不能訪問。而經過 symbol 和模塊化機制,就能夠實現私有化方法,由於類內部屬性/方法經過 symbol 聲明,在外部是沒法新建一個同樣的,這就是 symbol 惟一性的應用。
ES6 擴展運算符能夠將數組對象轉化成逗號分隔的參數序列,這一樣也是很是便捷的 API。
var arr = [1, 2, 3];
console.log(arr);
console.log(...arr); // 等價於 console.log(1, 2, 3);
複製代碼
var arr = [1, 2, 3];
// ES5
var arrCopy = JSON.parse(JSON.stringify(arr));
console.log(arrCopy2 !== arr); // true
// ES6
var arrCopy2 = [...arr];
console.log(arrCopy2 !== arr); // true
複製代碼
function foo(name = 'luffy') {
console.log(name);
}
foo(); // luffy
複製代碼
Array.prototype.from
用來將類數組(僞數組對象轉換成數組的)。
var objLikeArr = {
0: 'aaa',
1: 'bbb',
2: 'ccc',
length: 3
}
console.log(Array.from(objLikeArr)); // ['aaa', 'bbb', 'ccc']
複製代碼
一般咱們接觸過的僞數組對象有,arguments、NodeList以及 Set 對象等等,均可以經過此函數進行數組的轉化。
Array.prototype.isArray
此函數用來判斷對象是不是數組。
// ES5判斷
Object.prototype.toString.call([1, 2, 3]); // "[object Array]"
// ES6 判斷
Array.isArray({a: 1, b: 2}); // false
Array.isArray(Array.from([1, 2, 3])); // true
複製代碼
var nan;
isNaN(nan + 1); true
nan + 1 === NaN; false
複製代碼
NaN 與 NaN 也不相等。
includes 函數是 String 和 Array 共有的一個函數,他們都是用來判斷子元素是否在一個對象(字符串/數組)內部。
// String
'aaabbbccc'.includes('bbb'); // true
'aaabbbccc'.includes('ddd'); // false
複製代碼
// Array
[1, 2, 3, 4].includes(1); // true
[1, 2, 3, 4].includes(5); // false
[1, 2, NaN].indexOf(NaN); // -1
[1, 2, NaN].incldes(NaN); // true
複製代碼
能夠看到,includes 與以前的 indexOf 的區別有兩點:
這裏就是一個語法糖。
// ES5 求冪
Math.pow(3, 2); // 9
// ES7 求冪
3 ** 2; // 9
複製代碼
關於 Async/Await 的詳細介紹,能夠去另外一篇文章去查閱~禿破前端面試 —— Promise && Async/Await
之因此匯老是由於我的以爲除了 Async/Await 算是大塊更新外,其餘的都是某個小 API 或者語法糖,所以就簡單說明一下。
這個算是一個簡化需求吧,以前咱們想獲取對象的value值,只能經過以下方法。
var obj = {
name: 'luffyzh',
email: 'luffyzh@163.com'
}
// ES5
Object.keys(obj).map((key) => obj[key]);
複製代碼
如今,不只能直接獲取到 values,還能把 key-value 一塊兒返回。
// ES8
Object.values(obj);
Object.entries(obj);
複製代碼
字符串填充,新增了兩個有關填充字符串的方法String.prototype.padStart
和String.prototype.padEnd
,容許將空字符串或其餘字符串添加到原始字符串的開頭或結尾。。
targetLength:當前字符串須要填充到的目標長度。若是這個數值小於當前字符串的長度,則返回當前字符串自己。
padString:(可選)填充字符串。若是字符串太長,使填充後的字符串長度超過了目標長度,則只保留最左側的部分,其餘部分會被截斷,此參數的缺省值爲 " ",注意,缺省值並非空字符串,而是一個空格字符串。
var str = '0.0';
console.log(str.padStart(4, '10'));
console.log(str.padStart(4));
console.log(str.padEnd(10, 'x'));
console.log(str.padEnd(10));
複製代碼
用來返回一個對象的全部自身屬性/方法的描述符,若是沒有任何自身屬性,則返回空對象。
var obj = {
name: 'luffyzh',
email: 'luffyzh@163.com',
say() {
console.log(this.name);
}
}
Object.getOwnPropertyDescriptors(obj);
複製代碼
這兩個放在一塊兒來講是由於比較新,並且實際用到的我的感受不是特別多,就把我的以爲可能會用到的列出來了。
ES6 出現了擴展運算符,可是隻是給數組準備的,而擴展運算符很是好用,ES9 所以就擴展到了對象,如今對象也可使用擴展運算來進行便捷操做。
var obj = {
name: 'aaa',
email: 'luffyzh@163.com'
}
var obj2 = {...obj};
console.log(obj2);
console.log(obj2 !== obj);
var obj3 = { age: 20, ...obj2 };
複製代碼
關於 Promise 的詳細介紹,能夠去另外一篇文章去查閱~禿破前端面試 —— Promise && Async/Await
這個 API 我的感受出現的有些晚了,由於匹配全部是一個很常見的需求,可是原來只能匹配第一個。
var str = '11223344113311';
console.log(str.match('11')); // 返回一個數組
console.log(str.matchAll('11')); // 返回一個迭代器
複製代碼
能夠看到,matchAll 是經過 Generator 來實現的。
這兩個方法就很簡單明瞭了,就是去除字符串前面和後面的空格。很是簡單,就不作介紹了。
因此如今基礎類型就變成了:String、Number、Boolean、Null、Undefined、Symbol、BigInt 七種了。
ES5 - 五種 ES6 - 新增 Symbol,六種 ES10 - 新增 BigInt,七種
var bi = BigInt(1111111111);
console.log(bi);
console.log(typeof bi);
複製代碼
bigint 在控制檯會呈現綠色,number 則是藍色,而且 bigint 後面會攜帶一額字符 n。若是不初始化還會報錯,從報錯能夠看出 bigint 會在內部有一個轉換。
至此,ES6+ 新特性基本上也就寫完了,很粗淺,由於是全部特性的簡單介紹,因此當面試官面試的時候,你能夠回答上來基本用法就能夠了。不過每個特性都是值得深刻研究的,感興趣的能夠去查閱官方文檔以及源碼實現,這樣可以加理解。
相關代碼地址:禿破前端面試系列代碼