做用:javascript
call() 方法就是在使用一個指定 this 值和若干個指定的參數值的前提下調用某個函數或者方法。
var foo = { value : 1 } function bar() { console.log(this.value) } // 若是不對this進行綁定執行bar() 會返回undefined bar.call(foo) // 1
也就是說call()
改變了 this
的指向到了 foo
。java
試想當調用 call 的時候,也就是相似於數組
var foo = { value: 1, bar: function() { console.log(this.value) } } foo.bar() // 1
這樣就把 this 指向到了 foo 上,可是這樣給 foo 對象加了一個屬性,有些瑕疵,不過沒關係,執行完刪除這個屬性就能夠完美實現了。app
也就是說步驟能夠是這樣:函數
下面就試着去實現一下:this
Function.prototype.call2 = function(context) { context.fn = this // this 也就是調用call的函數 var result = context.fn() delete context.fn() return result } var foo = { value: 1 } function bar() { console.log(this.value) } bar.call2(foo) // 1
可是這樣有一個小缺陷就是call()
不只能指定this到函數,還能傳入給定參數執行函數好比:prototype
var foo = { value: 1 } function bar(name, age) { console.log(name) console.log(age) console.log(this.value) } bar.call(foo, 'black', '18') // black // 18 // 1
特別要注意的一點是,傳入的參數的數量是不肯定的,因此咱們要使用arguments
對象,取出除去第一個以外的參數,放到一個數組裏:code
Function.prototype.call2 = function(context) { context.fn = this // this 也就是調用call的函數 var args = [...arguments].slice(1) var result = context.fn(...args) delete context.fn() return result } var foo = { value: 1 } function bar(name, age) { console.log(name) console.log(age) console.log(this.value); } bar.call2(foo, 'black', '18') // black 18 1
還有一點須要注意的是,若是不傳入參數,默認指向爲 window,因此最終版代碼:對象
Function.prototype.call2 = function(context) { var context = context || window context.fn = this // this 也就是調用call的函數 var args = [...arguments].slice(1) var result = context.fn(...args) delete context.fn() return result } var value = 1 function bar() { console.log(this.value) } bar.call2()
apply
的方法和 call
方法的實現相似,只不過是若是有參數,以數組形式進行傳遞,直接上代碼:ip
Function.prototype.apply2 = function(context) { var context = context || window context.fn = this // this 也就是調用apply的函數 var result // 判斷是否有第二個參數 if(arguments[1]) { result = context.fn(...arguments[1]) } else { result = context.fn() } delete context.fn() return result } var foo = { value: 1 } function bar(name, age) { console.log(name) console.log(age) console.log(this.value); } bar.apply2(foo, ['black', '18']) // black 18 1