call,apply和bind
-
JavaScript 中 call()、apply()、bind() 的用法
轉(zhuǎn)載網(wǎng)址:https://www.runoob.com/w3cnote/js-call-apply-bind.html
先看明白下面:

obj.objAge; // 17
obj.myFun() // 小張年齡 undefined
例2
shows() // 盲僧
比較一下這兩者 this 的差別,第一個(gè)打印里面的 this 指向 obj,第二個(gè)全局聲明的 shows() 函數(shù) this 是 window ;
1,call()、apply()、bind() 都是用來重定義 this 這個(gè)對(duì)象的!

obj.myFun.call(db); // 德瑪年齡 99
obj.myFun.apply(db); // 德瑪年齡 99
obj.myFun.bind(db)(); // 德瑪年齡 99
以上出了 bind 方法后面多了個(gè) () 外 ,結(jié)果返回都一致!
由此得出結(jié)論,bind 返回的是一個(gè)新的函數(shù),你必須調(diào)用它才會(huì)被執(zhí)行。
2,對(duì)比call 、bind 、 apply 傳參情況下

obj.myFun.call(db,'成都','上海'); // 德瑪 年齡 99 來自 成都去往上海
obj.myFun.apply(db,['成都','上海']); // 德瑪 年齡 99 來自 成都去往上海
obj.myFun.bind(db,'成都','上海')(); // 德瑪 年齡 99 來自 成都去往上海
obj.myFun.bind(db,['成都','上海'])(); // 德瑪 年齡 99 來自 成都, 上海去往 undefined
微妙的差距!
從上面四個(gè)結(jié)果不難看出:
call 、bind 、 apply 這三個(gè)函數(shù)的第一個(gè)參數(shù)都是 this 的指向?qū)ο?,第二個(gè)參數(shù)差別就來了:
call 的參數(shù)是直接放進(jìn)去的,第二第三第 n 個(gè)參數(shù)全都用逗號(hào)分隔,直接放到后面 obj.myFun.call(db,'成都', ... ,'string' )。
apply 的所有參數(shù)都必須放在一個(gè)數(shù)組里面?zhèn)鬟M(jìn)去 obj.myFun.apply(db,['成都', ..., 'string' ])。
bind 除了返回是函數(shù)以外,它 的參數(shù)和 call 一樣。
當(dāng)然,三者的參數(shù)不限定是 string 類型,允許是各種類型,包括函數(shù) 、 object 等等!
-
說說bind、call、apply 區(qū)別?
1. call 和 apply 都是為了解決改變 this 的指向。作用都是相同的,只是傳參的方式不同。除了第一個(gè)參數(shù)外,call 可以接收一個(gè)參數(shù)列表,apply 只接受一個(gè)參數(shù)數(shù)組。
2. call和apply立即執(zhí)行并且返回值是你調(diào)用的方法的返回值,若該方法沒有返回值,則返回undefined。bind是改變this后返回一個(gè)新的函數(shù),他不會(huì)立即執(zhí)行。
-
實(shí)現(xiàn)call、apply 、bind函數(shù)?
轉(zhuǎn)載網(wǎng)址:https://zhuanlan.zhihu.com/p/286021449
對(duì)于實(shí)現(xiàn)以下幾個(gè)函數(shù),可以從幾個(gè)方面思考
不傳入第一個(gè)參數(shù),那么默認(rèn)為 window。改變了 this 指向,讓新的對(duì)象可以執(zhí)行該函數(shù)。那么思路是否可以變成給新的對(duì)象添加一個(gè)函數(shù),然后在執(zhí)行完以后刪除?
- 如何實(shí)現(xiàn)一個(gè)call函數(shù)
Function.prototype.myCall = function (context) {
var context = context || window
// 給 context 添加一個(gè)屬性
// getValue.call(a, 'yck', '24') => a.fn = getValue
context.fn = this
// 將 context 后面的參數(shù)取出來
var args = [...arguments].slice(1)
// getValue.call(a, 'yck', '24') => a.fn('yck', '24')
var result = context.fn(...args)
// 刪除 fn
delete context.fn
return result
}
- 如何實(shí)現(xiàn)一個(gè)apply函數(shù)
Function.prototype.myApply = function (context) {
var context = context || window
context.fn = this
var result
// 需要判斷是否存儲(chǔ)第二個(gè)參數(shù)
// 如果存在,就將第二個(gè)參數(shù)展開
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
}
- 如何實(shí)現(xiàn)一個(gè)bind函數(shù)
Function.prototype.myBind = function (context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
var _this = this
var args = [...arguments].slice(1)
// 返回一個(gè)函數(shù)
return function F() {
// 因?yàn)榉祷亓艘粋€(gè)函數(shù),我們可以 new F(),所以需要判斷
if (this instanceof F) {
return new _this(...args, ...arguments)
}
return _this.apply(context, args.concat(...arguments))
}
}