> 題目:ES6 箭頭函數中的`this`和普通函數中的有什么不同
### 箭頭函數
箭頭函數是 ES6 中新的函數定義形式,`function name(arg1, arg2) {...}`可以使用`(arg1, arg2) => {...}`來定義。示例如下:
~~~
// JS 普通函數
var arr = [1, 2, 3]
arr.map(function (item) {
console.log(index)
return item + 1
})
// ES6 箭頭函數
const arr = [1, 2, 3]
arr.map((item, index) => {
console.log(index)
return item + 1
})
~~~
箭頭函數存在的意義,第一寫起來更加簡潔,第二可以解決 ES6 之前函數執行中`this`是全局變量的問題,看如下代碼
~~~
function fn() {
console.log('real', this) // {a: 100} ,該作用域下的 this 的真實的值
var arr = [1, 2, 3]
// 普通 JS
arr.map(function (item) {
console.log('js', this) // window 。普通函數,這里打印出來的是全局變量,令人費解
return item + 1
})
// 箭頭函數
arr.map(item => {
console.log('es6', this) // {a: 100} 。箭頭函數,這里打印的就是父作用域的 this
return item + 1
})
}
fn.call({a: 100})
~~~
> 題目:ES6 模塊化如何使用?
### Module
ES6 中模塊化語法更加簡潔,直接看示例。
如果只是輸出一個唯一的對象,使用`export default`即可,代碼如下
~~~
// 創建 util1.js 文件,內容如
export default {
a: 100
}
// 創建 index.js 文件,內容如
import obj from './util1.js'
console.log(obj)
~~~
如果想要輸出許多個對象,就不能用`default`了,且`import`時候要加`{...}`,代碼如下
~~~
// 創建 util2.js 文件,內容如
export function fn1() {
alert('fn1')
}
export function fn2() {
alert('fn2')
}
// 創建 index.js 文件,內容如
import { fn1, fn2 } from './util2.js'
fn1()
fn2()
~~~
> 題目:ES6 class 和普通構造函數的區別
### class
class 其實一直是 JS 的關鍵字(保留字),但是一直沒有正式使用,直到 ES6 。 ES6 的 class 就是取代之前構造函數初始化對象的形式,從語法上更加符合面向對象的寫法。例如:
JS 構造函數的寫法
~~~
function MathHandle(x, y) {
this.x = x;
this.y = y;
}
MathHandle.prototype.add = function () {
return this.x + this.y;
};
var m = new MathHandle(1, 2);
console.log(m.add())
~~~
用 ES6 class 的寫法
~~~
class MathHandle {
constructor(x, y) {
this.x = x;
this.y = y;
}
add() {
return this.x + this.y;
}
}
const m = new MathHandle(1, 2);
console.log(m.add())
~~~
注意以下幾點,全都是關于 class 語法的:
* class 是一種新的語法形式,是`class Name {...}`這種形式,和函數的寫法完全不一樣
* 兩者對比,構造函數函數體的內容要放在 class 中的`constructor`函數中,`constructor`即構造器,初始化實例時默認執行
* class 中函數的寫法是`add() {...}`這種形式,并沒有`function`關鍵字
使用 class 來實現繼承就更加簡單了,至少比構造函數實現繼承簡單很多。看下面例子
JS 構造函數實現繼承
~~~
// 動物
function Animal() {
this.eat = function () {
console.log('animal eat')
}
}
// 狗
function Dog() {
this.bark = function () {
console.log('dog bark')
}
}
Dog.prototype = new Animal()
// 哈士奇
var hashiqi = new Dog()
~~~
ES6 class 實現繼承
~~~
class Animal {
constructor(name) {
this.name = name
}
eat() {
console.log(`${this.name} eat`)
}
}
class Dog extends Animal {
constructor(name) {
super(name)
this.name = name
}
say() {
console.log(`${this.name} say`)
}
}
const dog = new Dog('哈士奇')
dog.say()
dog.eat()
~~~
注意以下兩點:
* 使用`extends`即可實現繼承,更加符合經典面向對象語言的寫法,如 Java
* 子類的`constructor`一定要執行`super()`,以調用父類的`constructor`
> 題目:ES6 中新增的數據類型有哪些?
### Set 和 Map
Set 和 Map 都是 ES6 中新增的數據結構,是對當前 JS 數組和對象這兩種重要數據結構的擴展。由于是新增的數據結構,目前尚未被大規模使用,但是作為前端程序員,提前了解是必須做到的。先總結一下兩者最關鍵的地方:
* Set 類似于數組,但數組可以允許元素重復,Set 不允許元素重復
* Map 類似于對象,但普通對象的 key 必須是字符串或者數字,而 Map 的 key 可以是任何數據類型
**Set**
Set 實例不允許元素有重復,可以通過以下示例證明。可以通過一個數組初始化一個 Set 實例,或者通過`add`添加元素,元素不能重復,重復的會被忽略。
~~~
// 例1
const set = new Set([1, 2, 3, 4, 4]);
console.log(set) // Set(4)?{1, 2, 3, 4}
// 例2
const set = new Set();
[2, 3, 5, 4, 5, 8, 8].forEach(item => set.add(item));
for (let item of set) {
console.log(item);
}
// 2 3 5 4 8
~~~
Set 實例的屬性和方法有
* `size`:獲取元素數量。
* `add(value)`:添加元素,返回 Set 實例本身。
* `delete(value)`:刪除元素,返回一個布爾值,表示刪除是否成功。
* `has(value)`:返回一個布爾值,表示該值是否是 Set 實例的元素。
* `clear()`:清除所有元素,沒有返回值。
~~~
const s = new Set();
s.add(1).add(2).add(2); // 添加元素
s.size // 2
s.has(1) // true
s.has(2) // true
s.has(3) // false
s.delete(2);
s.has(2) // false
s.clear();
console.log(s); // Set(0)?{}
~~~
Set 實例的遍歷,可使用如下方法
* `keys()`:返回鍵名的遍歷器。
* `values()`:返回鍵值的遍歷器。不過由于 Set 結構沒有鍵名,只有鍵值(或者說鍵名和鍵值是同一個值),所以`keys()`和`values()`返回結果一致。
* `entries()`:返回鍵值對的遍歷器。
* `forEach()`:使用回調函數遍歷每個成員。
~~~
let set = new Set(['aaa', 'bbb', 'ccc']);
for (let item of set.keys()) {
console.log(item);
}
// aaa
// bbb
// ccc
for (let item of set.values()) {
console.log(item);
}
// aaa
// bbb
// ccc
for (let item of set.entries()) {
console.log(item);
}
// ["aaa", "aaa"]
// ["bbb", "bbb"]
// ["ccc", "ccc"]
set.forEach((value, key) => console.log(key + ' : ' + value))
// aaa : aaa
// bbb : bbb
// ccc : ccc
~~~
**Map**
Map 的用法和普通對象基本一致,先看一下它能用非字符串或者數字作為 key 的特性。
~~~
const map = new Map();
const obj = {p: 'Hello World'};
map.set(obj, 'OK')
map.get(obj) // "OK"
map.has(obj) // true
map.delete(obj) // true
map.has(obj) // false
~~~
需要使用`new Map()`初始化一個實例,下面代碼中`set``get``has``delete`顧名即可思義(下文也會演示)。其中,`map.set(obj, 'OK')`就是用對象作為的 key (不光可以是對象,任何數據類型都可以),并且后面通過`map.get(obj)`正確獲取了。
Map 實例的屬性和方法如下:
* `size`:獲取成員的數量
* `set`:設置成員 key 和 value
* `get`:獲取成員屬性值
* `has`:判斷成員是否存在
* `delete`:刪除成員
* `clear`:清空所有
~~~
const map = new Map();
map.set('aaa', 100);
map.set('bbb', 200);
map.size // 2
map.get('aaa') // 100
map.has('aaa') // true
map.delete('aaa')
map.has('aaa') // false
map.clear()
~~~
Map 實例的遍歷方法有:
* `keys()`:返回鍵名的遍歷器。
* `values()`:返回鍵值的遍歷器。
* `entries()`:返回所有成員的遍歷器。
* `forEach()`:遍歷 Map 的所有成員。
~~~
const map = new Map();
map.set('aaa', 100);
map.set('bbb', 200);
for (let key of map.keys()) {
console.log(key);
}
// "aaa"
// "bbb"
for (let value of map.values()) {
console.log(value);
}
// 100
// 200
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
// aaa 100
// bbb 200
// 或者
for (let [key, value] of map.entries()) {
console.log(key, value);
}
// aaa 100
// bbb 200
~~~
### Promise
`Promise`是 CommonJS 提出來的這一種規范,有多個版本,在 ES6 當中已經納入規范,原生支持 Promise 對象,非 ES6 環境可以用類似 Bluebird、Q 這類庫來支持。
`Promise`可以將回調變成鏈式調用寫法,流程更加清晰,代碼更加優雅。
簡單歸納下 Promise:**三個狀態、兩個過程、一個方法**,快速記憶方法:**3-2-1**
三個狀態:`pending`、`fulfilled`、`rejected`
兩個過程:
* pending→fulfilled(resolve)
* pending→rejected(reject)
一個方法:`then`
當然還有其他概念,如`catch`、`Promise.all/race`,這里就不展開了。
關于 ES6/7 的考查內容還有很多,本小節就不逐一介紹了,如果想繼續深入學習,可以在線看《[ES6入門](http://es6.ruanyifeng.com/)》。
- 文檔說明
- 大廠面試題
- HTML
- 001.如何遍歷一個dom樹
- 002.為什么操作DOM會很慢
- 003.瀏覽器渲染HTML的步驟
- 004.DOM和JavaScript的關系
- JS
- 001.數組扁平化并去重排序
- 002.高階函數
- 003.sort() 對數組進行排序
- 004.call 、 apply 和bind的區別
- 006.0.1+0.2為什么等于0.30000000000000004
- 011.var、let、const 的區別及實現原理?
- 010.new操作符都做了什么
- 009.a.b.c.d 和 a['b']['c']['d'],哪個性能更高?
- 016.什么是防抖和節流?有什么區別?如何實現?
- 017.['1', '2', '3'].map(parseInt) what & why ?
- 018.為什么 for 循環嵌套順序會影響性能?
- 019.介紹模塊化發展歷程
- 020.push輸出問題
- 021.判斷數組的三個方法
- 022.全局作用域中,用 const 和 let 聲明的變量不在 window 上,那到底在哪里?如何去獲取?
- 023.輸出以下代碼的執行結果并解釋為什么
- 024.ES6 代碼轉成 ES5 代碼的實現思路是什么
- 025.為什么普通 for 循環的性能遠遠高于 forEach 的性能,請解釋其中的原因。
- 026.數組里面有10萬個數據,取第一個元素和第10萬個元素的時間相差多少
- 027.變量類型
- 028.原型和原型鏈
- 029.作用域和閉包
- 030. 異步
- 031.ES6/7 新標準的考查
- 024.事件冒泡/事件代理
- 025.手寫 XMLHttpRequest 不借助任何庫
- 026.什么是深拷貝?
- 0027.克隆數組的方法
- 0028.ES6之展開運算符(...)
- 0029.arguments
- 0030. requestAnimationFrame
- 0031.遞歸爆棧問題與解決
- 021.簡單改造下面的代碼,使之分別打印 10 和 20
- 032.箭頭函數與普通函數
- 033.去除掉html標簽字符串里的所有屬性
- 034.查找公共父節點
- 035.Promise
- 0036.JSON.stringify ()
- CSS
- 001. BFC
- 002.介紹下 BFC、IFC、GFC 和 FFC
- 003.分析比較 opacity: 0、visibility: hidden、display: none 優劣和適用場景
- 004.怎么讓一個 div 水平垂直居中
- 005.重排重繪
- 006.inline/block/inline-block的區別
- 007.選擇器的權重和優先級
- 008.盒模型
- 009.清除浮動
- 010.flex
- 011.nth-child和nth-of-type的區別
- 0012.overflow
- 0013.CSS3中translate、transform和translation的區別和聯系
- 0014.flex
- 0015.px、em、rem
- 0016.width:100%
- 網絡
- 001.講解下HTTPS的工作原理
- 002.介紹下 HTTPS 中間人攻擊
- 003.談談你對TCP三次握手和四次揮手的理解
- 004.A、B 機器正常連接后,B 機器突然重啟,問 A 此時處于 TCP 什么狀態
- 005.簡單講解一下http2的多路復用
- 006. 介紹下 http1.0、1.1、2.0 協議的區別?
- 007.永久性重定向(301)和臨時性重定向(302)對 SEO 有什么影響
- 008.URL從輸入到頁面展示的過程
- 009.接口如何防刷
- 010.http狀態碼?
- 0111.跨域/如何解決?
- 012.cookie 和 localStorage 有何區別?
- 013.Fetch API
- 014.跨域Ajax請求時是否帶Cookie的設置
- 0015.協商緩存和強緩存
- 性能優化
- 001.前后端分離的項目如何seo
- 002.性能優化的方法
- 003.防抖和節流
- React
- 001.React 中 setState 什么時候是同步的,什么時候是異步的?
- 002.Virtual DOM 真的比操作原生 DOM 快嗎?談談你的想法。
- 003.Hooks 的特別之處
- 004.元素和組件有什么區別?
- 005.什么是 Pure Components?
- 006.HTML 和 React 事件處理有什么區別?
- 007.如何將參數傳遞給事件處理程序或回調函數?
- 008.如何創建 refs?
- 009.什么是 forward refs?
- 010.什么是 Virtual DOM?
- 011.什么是受控組件、非受控組件?
- 012.什么是 Fragments ?
- 013.為什么React元素有一個$$typeof屬性?
- 014.如何在 React 中創建組件?
- 015.React 如何區分 Class 和 Function?
- 016.React 的狀態是什么?
- 017.React 中的 props 是什么?
- 018.狀態和屬性有什么區別?
- 019.如何在 JSX 回調中綁定方法或事件處理程序?
- 020.什么是 "key" 屬性,在元素數組中使用它們有什么好處?
- 021.為什么順序調用對 React Hooks 很重要?
- 022.setState如何知道該做什么?
- 023.hook規則?
- 024.Hooks 與 Class 中調用 setState 有不同的表現差異么?
- 025.useEffect
- 026.fiber的作用
- 027.context的作用?
- 028.setState何時同步何時異步?
- 029.react性能優化
- 030.fiber
- 031.React SSR
- 異步
- 001.介紹下promise
- 002.Async/Await 如何通過同步的方式實現異步
- 003.setTimeout、Promise、Async/Await 的區別
- 004.JS 異步解決方案的發展歷程以及優缺點
- 005.Promise 構造函數是同步執行還是異步執行,那么 then 方法呢?
- 006.模擬實現一個 Promise.finally
- 012.簡單手寫實現promise
- 015.用Promise對象實現的 Ajax
- 007.簡單實現async/await中的async函數
- 008.設計并實現 Promise.race()
- 009.Async/await
- 010.珠峰培訓promise
- git
- 001.提交但沒有push
- 002.gitignore沒有作用?
- Node
- 001.用nodejs,將base64轉化成png文件
- Koa
- 001.koa和express的區別
- 數據庫
- redux
- 001.redux 為什么要把 reducer 設計成純函數
- 002.在 React 中如何使用 Redux 的 connect() ?
- 003.mapStateToProps() 和 mapDispatchToProps() 之間有什么區別?
- 004.為什么 Redux 狀態函數稱為 reducers ?
- 005.如何在 Redux 中發起 AJAX 請求?
- 006.訪問 Redux Store 的正確方法是什么?
- 007.React Redux 中展示組件和容器組件之間的區別是什么?
- 008.Redux 中常量的用途是什么?
- 009.什么是 redux-saga?
- 設計模式
- 公司題目
- 001.餓了么
- 001.div垂直水平居中(flex、絕對定位)
- 002.React子父組件之間如何傳值
- 003.Emit事件怎么發,需要引入什么
- 004.介紹下React高階組件,和普通組件有什么區別
- 005.一個對象數組,每個子對象包含一個id和name,React如何渲染出全部的name
- 006.在哪個生命周期里寫
- 007.其中有幾個name不存在,通過異步接口獲取,如何做
- 008.渲染的時候key給什么值,可以使用index嗎,用id好還是index好
- 009.webpack如何配sass,需要配哪些loader
- 010.配css需要哪些loader
- 011.如何配置把js、css、html單獨打包成一個文件
- 012.監聽input的哪個事件,在什么時候觸發
- 013.兩個元素塊,一左一右,中間相距10像素
- 014.上下固定,中間滾動布局如何實現
- 016.取數組的最大值(ES5、ES6)
- 017.apply和call的區別
- 018.ES5和ES6有什么區別
- 019.some、every、find、filter、map、forEach有什么區別
- 020.上述數組隨機取數,每次返回的值都不一樣
- 021.如何找0-5的隨機數,95-99呢
- 022.頁面上有1萬個button如何綁定事件
- 023.如何判斷是button
- 024.頁面上生成一萬個button,并且綁定事件,如何做(JS原生操作DOM)
- 025.循環綁定時的index是多少,為什么,怎么解決
- 026.頁面上有一個input,還有一個p標簽,改變input后p標簽就跟著變化,如何處理
- 瀏覽器相關
- 001.性能優化
- 002.web安全
- 003.獲取瀏覽器大小
- 004.從輸入 URL 到頁面加載完成的過程中都發生了什么事情?
- 后端
- 001.分布式
- zuku
- 字節
- webpack
- webpack的打包原理是什么
- Webpack-- 常見面試題
- webscoket