call apply bind都有著改變this指向的功能,什么叫改變this指向呢?this:當(dāng)前作用域的頂層對象。某個方法內(nèi)可能引用了他當(dāng)前作用域的對象的屬性,改變this指向就是把他的this更換為其他對象。這么做的意義是什么呢?話不多說,上代碼。
const Animal = {
name: '動物',
say() {
console.log(`大家好,我是${this.name}`)
}
}
const Cat = {
name: '大貍貓'
}
Animal.say.call(Cat)
// 大家好,我是大貍貓
Animal.say.apply(Cat)
// 大家好,我是大貍貓
Animal.say.bind(Cat)()
// 大家好,我是大貍貓
上圖三個方法都能通過傳參改變
Animal.say方法中的this。call apply bind都是Function.prototype上的方法,通過傳參的方式把內(nèi)部this替換為參數(shù)中的對象。來看區(qū)別,為什么bind后面還跟了個括號?括號表示調(diào)用,逆向思考可以得知,bind方法返回了一個新的函數(shù),手動執(zhí)行才能調(diào)用。call和apply都是直接調(diào)用。bind寫法雖然看上去麻煩點,但如果你此時不想調(diào)用而是在未來的某一刻調(diào)用,這個時候就可以賦值給一個變量,等到需要的時候再調(diào)用了
const Animal = {
name: '動物',
say(food, sport) {
console.log(`大家好,我是${this.name}, 我喜歡吃${food},我喜歡的運(yùn)動是${sport}`)
}
}
const Cat = {
name: '大貍貓'
}
Animal.say.call(Cat, '貓草', '抓老鼠')
// 大家好,我是大貍貓, 我喜歡吃貓草,我喜歡的運(yùn)動是抓老鼠
Animal.say.apply(Cat, ['貓草', '抓老鼠'])
// 大家好,我是大貍貓, 我喜歡吃貓草,我喜歡的運(yùn)動是抓老鼠
Animal.say.bind(Cat)('貓草', '抓老鼠')
// 大家好,我是大貍貓, 我喜歡吃貓草,我喜歡的運(yùn)動是抓老鼠
可以看出,額外參數(shù)都緊跟在第一個參數(shù)之后,
call和bind參數(shù)以散列形式,apply參數(shù)以數(shù)組形式,并推理出apply擁有打散數(shù)組的功能
const Animal = {
name: '動物',
say(food, sport) {
console.log(`大家好,我是${this.name}, 我喜歡吃${food},我喜歡的運(yùn)動是${sport}`)
}
}
const Cat = {
name: '大貍貓'
}
Animal.say.bind(Cat)('貓草', '抓老鼠')
// 大家好,我是大貍貓, 我喜歡吃貓草,我喜歡的運(yùn)動是抓老鼠
Animal.say.bind(Cat, '貓草1')('貓草', '抓老鼠')
// 大家好,我是大貍貓, 我喜歡吃貓草1,我喜歡的運(yùn)動是貓草
Animal.say.bind(Cat, '貓草1', '抓老鼠1')('貓草', '抓老鼠')
// 大家好,我是大貍貓, 我喜歡吃貓草1,我喜歡的運(yùn)動是抓老鼠1
以上代碼可以看出,
bind方法產(chǎn)數(shù)傳遞,如果bind方法內(nèi)有參數(shù)以bind方法內(nèi)參數(shù)為主。
實際應(yīng)用
import React from 'react'
export default class App extends React.component {
state = {
age: 24
}
constructor() {
super()
this.checkAdult = this.checkAdult.bind(this)
}
checkAdult() {
console.log(this.state.age >= 18 ? '成年了' : '未成年')
}
render() {
return (
<button onClick={this.checkAdult}>檢測</button>
)
}
}
在
react中,我們在可以在構(gòu)造函數(shù)內(nèi)實現(xiàn)this綁定(當(dāng)然我們也可以使用箭頭函數(shù)或者public class fields語法(stage 2)直接在class內(nèi)賦值)
react相關(guān)this指向相關(guān)問題
Math.max.apply(Math, [5, 2, 6, 9, 20, 12])
數(shù)組的求最大值(也可以使用es6的擴(kuò)展運(yùn)算符
Math.max(...arr))
繼承
function Animal(sound) {
this.sound = sound
this.say = function() {
console.log(this.sound)
}
}
function Dog() {
Animal.apply(this, arguments)
}
const dog = new Dog('wang wang')
dog.say()
// wang wang
在構(gòu)造函數(shù)
Dog內(nèi)使用call或者apply,此時Animal的所有屬性和方法都被在此聲明,實現(xiàn)繼承
偽數(shù)組轉(zhuǎn)換成數(shù)組
偽數(shù)組也稱類數(shù)組。像arguments 或者 獲取一組元素返回的集合都是偽數(shù)組。
(arguments,NodeList)
const imgArr = Array.prototype.slice.call(document.querySelectorAll('img'))
function Dog() {
const ages = Array.prototype.slice.call(arguments)
}
當(dāng)然也可以用ES6簡單寫法
const arg = Array.from(arguments);
const arg = [...arguments]
console.log(arg instanceof Array)
// true
Array.from()能將類數(shù)組(arguments,NodeList),可迭代對象(Set,Map),字符串(String)轉(zhuǎn)換成數(shù)組
Array.prototype.slice.call()能將類數(shù)組(arguments,NodeList),字符串(String)轉(zhuǎn)換成數(shù)組
總結(jié)
-
call apply bind都有著改變this指向的作用,并且第一個參數(shù)都是目標(biāo)this對象,bind返回一個新的函數(shù) - 額外參數(shù)下,
call和bind的參數(shù)都以散列形式,apply以數(shù)組形式
在不破壞原對象的情況下,使用這幾個方法是最好的選擇。但隨著新版es的出現(xiàn),他們的大部分功能都已能被新的語法糖替代。不過對于開發(fā)者來說,但還是應(yīng)該要了解的,這些知識經(jīng)常出現(xiàn)在面試題中,況且只有了解原理才能更熟練的掌握新語法的用法,小到api,大到框架,腳踏實地,才能走得更高。