作用.
apply.call.bind 都是爲了改變函數運行時上下文(this指向)而存在的。
區別:
- 三者的第一個參數都是this的指向
- apply的第二個參數是個數組,而call與bind的第二個以及之後的參數都是函數的入參
- bind不是立即執行,而call和apply會
call的簡單模擬實現
思路:
- 函數定義在哪裏?
因爲是對全局有效的,所以定義至Function的原型對象中 - 參數接收參數?
綁定函數被調用接收第二個以及之後的參數 - 如何顯式綁定this
如果被調用的函數,被指定對象所擁有,那麼函數內部的this,應該指向的是該對象
代碼上一盤:
Function.prototype.bind = function(context) {
let ctx = context || window
// 讓函數的this指向context
ctx.func = this
console.log(this, '------this')
// 獲取參數
let args = Array.from(arguments).slice(1)
// 爲什麼下面的還要判斷傳入的數組長度?
// const res = args.length ? ctx.func(...args) : ctx.func()
const res = ctx.func(...args)
delete ctx.func
//爲什麼返回?不返回也是OK的
return res
}
let name = '全局的'
function sayName() {
console.log(this.name)
}
let obj = {
name: '我是某個對象的'
}
sayName.bind(obj)
apply的簡單模擬實現
apply的實現和call是一樣的,只不過是改變傳參的方式而已
Function.prototype.apply = function(context) {
let ctx = context || window
ctx.func = this
let args = arguments[1]
let isArray = Array.isArray(args)
if (!isArray) {
alert('-------第二個傳參不是數組喲')
return
}
let res = args ? ctx.func(...args) : ctx.func()
delete ctx.func
return res
}
let name = '全局的'
function sayName() {
console.log(this.name)
}
let obj = {
name: '我是某個對象的'
}
sayName.apply(obj, [12])
bind的模擬實現
思路:
- 函數定義在哪裏?
因爲是對全局有效的,所以定義至Function的原型對象中 - 參數接收參數?
bind函數返回一個綁定函數,最終調用需要傳入函數實參和綁定函數的實參!! - 如何顯式綁定this
如果被調用的函數,被指定對象所擁有,那麼函數內部的this,應該指向的是該對象
Function.prototype.bind = function(context) {
// 對對象進行深拷貝,防止污染原有對象
let ctx = JSON.parse(JSON.stringify(context)) || window
ctx.func = this
let args = Array.from(arguments).slice(1)
return function() {
return args.length ? ctx.func(...args) : ctx.func()
}
}
let name = '全局的'
function sayName() {
console.log(this.name)
}
let obj = {
name: '我是某個對象的'
}
// sayName.bind(obj)
// sayName.apply(obj, [12])
sayName.bind(obj)()