在JS中,這三者都是用來改變函數(shù)的this對(duì)象的指向的,他們有什么樣的區(qū)別呢。
在說區(qū)別之前還是先總結(jié)一下三者的相似之處:
- 都是用來改變函數(shù)的this對(duì)象的指向的。
- 第一個(gè)參數(shù)都是this要指向的對(duì)象。
- 都可以利用后續(xù)參數(shù)傳參。
那么他們的區(qū)別在哪里的,先看一個(gè)例子。
var xw = {
name : "小王",
gender : "男",
age : 24,
say : function() {
alert(this.name + " , " + this.gender + " ,今年" + this.age);
}
}
var xh = {
name : "小紅",
gender : "女",
age : 18
}
xw.say();
那么如何用xw的say方法來顯示xh的數(shù)據(jù)呢。
對(duì)于call可以這樣:
xw.say.call(xh);
對(duì)于apply可以這樣:
xw.say.apply(xh);
而對(duì)于bind來說需要這樣:
xw.say.bind(xh)();
總之:bind與apply、call最大的區(qū)別就是:bind不會(huì)立即調(diào)用,其他兩個(gè)會(huì)立即調(diào)用,apply與call的區(qū)別是apply第二個(gè)是參數(shù)組,但是在確定的參數(shù)下,還是最好用call,call的效果會(huì)更高,但是在函數(shù)的延展性上使用apply更好
手寫一個(gè)call方法
考慮兩點(diǎn)
第一個(gè)參數(shù)為undefined或null的時(shí)候,那么會(huì)轉(zhuǎn)變?yōu)閣indow
改變了this執(zhí)行,讓新的對(duì)象可以執(zhí)行該函數(shù)。
Function.prototype.myCall = function(context) {
// 判斷是否是undefined和null
if (typeof context === 'undefined' || context === null) {
context = window
}
context.fn = this
let args = [...arguments].slice(1)
let result = context.fn(...args)
delete context.fn
return result
}
apply的實(shí)現(xiàn)
Function.prototype.myApply = function(context) {
if (typeof context === 'undefined' || context === null) {
context = window
}
context.fn = this
let args = arguments[1]
let result
if (args) {
result = context.fn(...args)
} else {
result = context.fn()
}
delete context.fn
return result
}
bind實(shí)現(xiàn)
這里需要注意下,因?yàn)閎ind轉(zhuǎn)換后的函數(shù)可以作為構(gòu)造函數(shù)使用,此時(shí)this應(yīng)該指向構(gòu)造出的實(shí)例,而bind函數(shù)綁定的第一個(gè)參數(shù)。
Function.prototype.myBind = function(context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
let _this = this
let args = [...arguments].slice(1)
return function F() {
// 判斷是否被當(dāng)做構(gòu)造函數(shù)使用
if (this instanceof F) {
return _this.apply(this, args.concat([...arguments]))
}
return _this.apply(context, args.concat([...arguments]))
}
}