apply()
方法接收一個指定的this
值和一個包含多個參數的數組來調用一個函數。javascript
call()
方法接收一個指定的 this
值和一個參數列表來調用一個函數。前端
bind()
方法建立一個新的函數,在 bind()
被調用時,這個新函數的 this
被指定爲 bind()
的第一個參數,而其他參數將做爲新函數的參數,供調用時使用java
使用 call
和 apply
函數的時候要注意,若是傳遞給 this
的值不是一個對象,JavaScript 會嘗試使用內部 ToObject
操做將其轉換爲對象。所以,若是傳遞的值是一個原始值好比 7
或 'foo'
,那麼就會使用相關構造函數將它轉換爲對象,因此原始值 7
會被轉換爲對象,像 new Number(7)
這樣,而字符串 'foo'
轉化成 new String('foo')
這樣,例如:數組
function bar() {
console.log(Object.prototype.toString.call(this));
}
//原始值 7 被隱式轉換爲對象
bar.call(7); // [object Number]
bar.call('foo'); // [object String]
複製代碼
func.apply(thisArg, [argsArray])
閉包
thisArg
必選的。在 func
函數運行時使用的 this
值。若是這個函數處於非嚴格模式下,則指定爲 null
或 undefined
時會自動替換爲指向全局對象,原始值會被包裝。func
函數。Function.prototype.Apply = function (thisArg, args = Symbol.for('args')) {
//Apply 函數老是被咱們想改變this的函數調用,所以本函數內this老是指代調用函數
//生成一個Symbol類型的惟一符號,用於將調用apply的函數掛載到指定對象上
const fn = Symbol('fn')
thisArg[fn] = this
//經過對象調用函數,並傳參
args === Symbol.for('args') ? thisArg[fn]() : thisArg[fn](...args)
//刪除掛載到指定對象上的方法
delete thisArg[fn]
}
// 聲明全局變量
var position = 'global'
var name = 'window'
function func(name) {
console.log(this.position)
console.log(name)
}
const obj = {
name: 'object',
position: 'obj',
}
func.Apply(obj,[obj.name,null]) // obj object
// 其中,Apply內this指向func
func.Apply(obj,[name,null]) // obj window
// func中 name 只受傳參影響
複製代碼
Symbol.for(key)
會根據給定的鍵key
,來從運行時的 symbol 註冊表中找到對應的 symbol,若是找到了,則返回它,不然,新建一個與該鍵關聯的 symbol,並放入全局 symbol 註冊表中。app
Function.prototype.Call = function (thisArg, ...args) {
//這裏this爲這個方法的調用者
const fn = Symbol('fn')
thisArg[fn] = this || globalThis
//經過對象調用函數,並傳參
args.length ? thisArg[fn](...args) : thisArg[fn]()
//刪除掛載到指定對象上的方法
delete thisArg[fn]
}
func.Call(obj) // obj undefined
func.Call(obj, 'test') // obj test
複製代碼
這裏不使用
arguments
對象獲取傳入參數。arguments
不是一個Array
,除了length屬性和索引元素以外沒有任何Array
屬性。函數使用剩餘參數
...args
能夠精簡代碼post
bind() 函數會建立一個新的綁定函數,它包裝了原函數對象。調用綁定函數一般會致使執行包裝函數。ui
簡單版本this
Function.prototype.Bind = function(thisArg, ...args){
let self = this;
let fBound = function(...args1){
return self.apply(thisArg, [...args, ...args1]);
}
return fBound;
}
複製代碼
使用閉包保存了第一次綁定時的this值,同時使後續的綁定無效
Function.prototype.Bind = function(thisArg, ...args){
let self = this;
let fBound = function(...args1){
//若是當前this爲fBound的實例,表示是執行了new,指向this,不然指向bind對象
return self.apply(this instanceof fBound ? this : thisArg, [...args, ...args1]);
}
//修改返回函數的 prototype 爲綁定函數的 prototype,new出實例對象就能夠繼承綁定函數的原型中的成員
fBound.prototype = this.prototype;
return fBound;
}
複製代碼
這裏補充了綁定的函數爲構造函數時的狀況
function foo(age, height) {
console.log(this.name) // obj
console.log(age) // 3
console.log(height) // 2
}
const obj = {
name: 'obj',
age: 3
}
foo.Bind(obj, obj.age)(2) // 綁定bind時同時傳遞一個參數
複製代碼
若是你收穫了新知識,請給做者點個贊吧~