call,apply,bind均是用於改變this指向。 三者相似之處: 1:都是用於改變函數的this指向。 2:第一個參數都是this要指向的對象。 3:都可以通過後面的參數進行對方法的傳參。 在圖中可以看到只有age是有值的,直接調用fn方法,this預設指向為window。 address因 ...
call,apply,bind均是用於改變this指向。
三者相似之處:
1:都是用於改變函數的this指向。
2:第一個參數都是this要指向的對象。
3:都可以通過後面的參數進行對方法的傳參。
let obj = { address: '北京', age: 18 } let address = '上海' var age = 20 let fn = function(name,sex){ console.log('address',this.address) console.log('age',this.age) console.log('name',name) console.log('sex',sex) } fn()
在圖中可以看到只有age是有值的,直接調用fn方法,this預設指向為window。
address因為是let聲明出來的變數,會產生一個做個作用域,所以fn同樣是取不到address,只可以取到age。
使用call:
apply:
bind:
call跟apply的相同點:改變this指向後會對函數進行調用。
call跟apply的區別:後續參數call是一個一個傳入,apply是將所有參數放到一個數組中進行傳遞。
bind跟apply跟call的不同:改變this指向後,並不會主動度函數進行調用,需要再手動調用函數。
傳參方式有兩種:1、跟call相同,將後續參數依次傳入。
2、在調用時進行參數的傳遞
註意點:在嚴格模式下,即“use strict”
function fn() { console.log(this); } fn()// 普通模式下this是window,在嚴格模式下this是undefined fn.call(); // 普通模式下this是window,在嚴格模式下this是undefined fn.call(null); // 普通模式下this是window,在嚴格模式下this是null fn.call(undefined); // 普通模式下this是window,在嚴格模式下this是undefined
call的實現原理,實現一個自己的call方法。
明確call做了哪些事情。
1.改變了this指向
2.傳遞了要傳遞的參數
3.主動調用了方法
Function.prototype.myCall = function(...arg){ let obj = [...arg][0] || window//將this要指向的對象賦值給一個新對象 obj.fn = this//給新對象添加新的屬性fn為要改變this指向的方法,實現了this的改變,obj.fn的this指向的便是obj了 let result = obj.fn(...[...arg].slice(1))//實現主動調用,並將參數傳遞 delete obj.fn//刪除fn屬性,防止破壞原有對象 return result //若方法有返回值將返回值return出去 }
call的經典例子:
function fn1() { console.log(1); } function fn2() { console.log(2); } fn1.call(fn2); // 1 fn1.call.call(fn2); // 2
fn1.call(fn2); 因為並沒有涉及到this所以列印的仍然是1
fn1.call.call(fn2)
fn1.call.call(fn2)//將fn1.call看做要被該邊this指向的函數,結合自己實現的call函數 function(...arg){ let obj = [...arg][0] || window//將this要指向的對象賦值給一個新對象 obj.fn = this//給新對象添加新的屬性fn為要改變this指向的方法,實現了this的改變,obj.fn的this指向的便是obj了 let result = obj.fn(...[...arg].slice(1))//實現主動調用,並將參數傳遞 delete obj.fn//刪除fn屬性,防止破壞原有對象 return result //若方法有返回值將返回值return出去 }.call(fn2)//將裡面的this改為fn2,可以看到實際執行的就是fn2函數