apply和call
在js中,apply和call都是用來改變函數(shù) 執(zhí)行時上下文 的,也就是改變 this 的指向。
js中上下文分為定義時上下文,執(zhí)行時上下文,且上下文this的指向是可以改變的。
舉一個栗子??
new 一個人 叫nathan,為黃皮膚
function Preson (name) {
this.name = name
}
Preson.prototype.skinColor = 'yellow'
Preson.prototype.say = function () {
console.log('Hello World, My name is ' + this.name + ' and my skin color is ' + this.skinColor)
}
let nathan = new Person('nathan')
nathan.say() // Hello World, My name is nathan and my skin color is 'yellow'
當存在另一個黑人,需要從nathan的口中說出他的膚色
let mike = {
skinColor: 'black',
name: 'mike'
}
nathan.say.apply(mike) // Hello World, My name is mike and my skin color is black
nathan.say.call(mike) // Hello World, My name is mike and my skin color is black
nathan.say() // Hello World, My name is nathan and my skin color is yellow
可以看出 apply 和 call 都改變了 this 中的 ** skinColor** 和 name 對應的值,但是當我再使用 nathan 的 say() 方法時,nathan 說的還是和之前的結果是一樣的
這樣就可以形象的看作是,mike 讓 nathan 說了話,而不是 mike 直接變成了 nathan
apply和call區(qū)別
兩者的區(qū)別就是傳參的方式不同
function Preson (name) {
this.name = name
}
Preson.prototype.skinColor = 'yellow'
Preson.prototype.say = function (old, sex) {
console.log('Hello World, My name is ' + this.name + ' and my skin color is ' + this.skinColor + '. I\'m a ' + sex + ' and I ' + old + 'years old')
}
let nathan = new Preson('nathan')
nathan.say(12, 'boy')
let mike = {
skinColor: 'black',
name: 'mike'
}
let detail = [20, 'girl']
nathan.say.apply(mike, detail)
nathan.say.call(mike, ...detail)
apply除了第一個傳入的改變this內(nèi)的參數(shù)之外,函數(shù)本身的參數(shù)使用數(shù)組的形式傳入,而call則是按順序傳入
在toString()方法沒有被重寫的前提下:我寫了以下的工具函數(shù)來判斷數(shù)據(jù)類型,這里只寫了判斷數(shù)組的,還可以寫String object
function isArray (data, type) {
let t = ''
if (arguments.length === 2) {
t = type.toLowerCase()
} else {
t = 'array'
}
if (t === 'array') {
if (!Array.isArray) {
Array.isArray = function (arg) {
return Object.prototype.toString.call(arg) === '[object Array]'
}
}
return ArrayisArray(data)
}
}
bind
在函數(shù)后面鏈式使用bind(),第一個參數(shù)是改變函數(shù)內(nèi)部的this為這個參數(shù),后面的參數(shù)是在調(diào)用目標函數(shù)時,預先添加到綁定函數(shù)的參數(shù)
var module = {
x: 42,
getX: function(a) {
if (a) {
console.log(a);
}
return this.x;
}
}
var unboundGetX = module.getX;
console.log(unboundGetX());// output: undefined
var boundGetX = unboundGetX.bind(module, 'arg1');
console.log(boundGetX());
// ouput: arg1
// output: 42
然后多次綁定bind是無效的。
三者之間的區(qū)別
當你需要在函數(shù)改變上下文之后不是馬上執(zhí)行,在回調(diào)時執(zhí)行,使用bind
apply和call會立即執(zhí)行函數(shù)
我是看了 此人 的文章之后,按照自己的理解再次寫的這篇文章,使自己記憶深刻,然后有一些話也做了簡單的自己理解的義譯,歡迎評論提錯
peace~
author: nathan[圖片上傳中...(IMG_6061.JPG-daecac-1594702430431-0)]