標籤:type 對象 foo script div 定義 應用 第一個 function
一、探索call方法原理
Function.prototype.call = function(obj) {// 1、讓fn中的this指向obj// eval(this.toString().replace("this","obj"));// 2、讓fn方法再執行// this();}
function fn1() { console.log(1); console.log(this);}function fn2() { console.log(2); console.log(this);}fn1.call(); //1,this指向windowfn1.call(fn2); //1,原來的this指向fn1,fn1.call(fn2)把this指向fn2,再讓fn1方法執行。fn1.call.call(); //報錯了,fn1.call.call is not a function。fn1.call.call(fn2); //2/*設fn1.call = test;test.call(fn2)原來的this指向test,test.call(fn2)把this指向fn2,再讓test方法執行,即fn1.call的內部this()執行,即fn2()執行。*/
二、call,apply,bind的調用文法
function fn(num1, num2) { console.log(num1 + num2); console.log(this);}//call方法fn.call(obj , 100 , 200);//apply方法fn.apply(obj , [100, 200]);//bind方法var tempFn = fn.bind(obj, 1, 2);tempFn();//或者fn.bind(obj, 1, 2)();
1、相同點
- apply、call、bind三者都是用來改變函數的this對象的指向的;
- apply、call、bind三者第一個參數都是this要指向的對象,也就是想指定的上下文;
- apply、call、bind三者都可以利用後續參數傳參。
2、不同點
- call在給fn傳遞參數的時候,是一個個的傳遞值的;而apply不是一個個傳的,而是把值放在數組中,傳過去的。
- 明確知道參數數量時用call;不確定參數數量時用apply,然後把參數push進數組並傳遞進去,函數內部也可以通過arguments這個數組來遍曆所有的參數。
- bind是返回對應函數,便於稍後調用;apply、call則是立即調用。
- bind這個方法在IE6~8下不相容。在Javascript中,多次bind()是無效的,因為bind的實現,相當於使用函數在內部包了一個call/apply,第二次bind()相當於再包住第一次bind(),故第二次以後的bind是無法生效的。
四、應用情境
1、驗證是否是數組
function isArray(obj){ return Object.prototype.toString.call(obj) === ‘[object Array]‘;}
2、擷取數組最大最小值
var numbers = [5, 458 , 120 , -215];var maxInNumbers = Math.max.apply(Math, numbers), //458maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458
3、數組追加
var arr1 = [12 , "foo" , {name "Camille"} , -2458];var arr2 = ["HouYi" , 555 , 100];Array.prototype.push.apply(arr1, arr2);
4、偽數組使用數組方法
//定義一個log方法,讓它可以代理console.log方法,常見的解決方案是:function log(msg) { console.log(msg);}log(‘msg1‘); //msg1log(‘msg1‘,‘msg2‘); //msg1
//當不確定傳入參數的個數時,上面的方法就失效了,於是想到了apply.function log(){ console.log.apply(console, arguments);};log(‘msg1‘); //msg1log(‘msg1‘,‘msg2‘); //msg1 msg2
//如果給log訊息添加一個"app_"前輟,這時可以想到Array.prototype.slice.call可以把arguments偽數組轉化為標準數組,再使用數組方法unshift即可。function log(){ var args = Array.prototype.slice.call(arguments); args.unshift(‘app_‘); console.log.apply(console, args);};log(‘msg1‘); //app_ msg1
區別call,apply,bind