call方法的作用:
var obj={name:"張三"};
function fn(){
console.log(this);
}
fn.call(obj);
首先讓原型上的call方法執(zhí)行,在執(zhí)行call方法的時(shí)候,讓fn方法中的this變?yōu)榈谝粋€(gè)參數(shù)obj,然后再把fn這個(gè)函數(shù)執(zhí)行
模擬一個(gè)內(nèi)置call方法,探究原理:
Function.prototype.myCall=function(context){
//---->myCall方法中的this是當(dāng)前要操作和改變其this關(guān)鍵字的那個(gè)函數(shù)名(即fn)
//步驟1:讓this這個(gè)函數(shù)中的“this關(guān)鍵字”變?yōu)閏ontext(也就是讓fn中的this關(guān)鍵字變?yōu)閏ontext的值----->即obj)
var that=eval(this.toString().replace("this","obj"));
//先把this函數(shù)中的代碼變?yōu)樽址缓蟀裻his函數(shù)中的“this關(guān)鍵字”替換為“obj”,最后用eval()把字符串變?yōu)镴S可執(zhí)行的代碼
//步驟2:讓fn方法執(zhí)行
this();
};
fn.myCall(obj); //myCall方法中的this是fn
比較:
function fn1(){console.log(1);} function fn2(){console.log(2);}
1、fn1.call(fn2)
//首先f(wàn)n1通過(guò)原型鏈機(jī)制找到Function.prototype上的call方法,并且讓call方法執(zhí)行--->此時(shí)call方法中的this是要操作的fn1---->在call方法執(zhí)行過(guò)程中首先讓fn1中的“this關(guān)鍵字”變?yōu)閒n2,然后再讓這個(gè)fn1執(zhí)行
2、fn1.call.call(fn2); //---->2
//首先f(wàn)n1通過(guò)原型鏈找到Function.prototype上的call方法,然后再讓call方法通過(guò)原型再找到Function原型上的call(因?yàn)閏all本身的值是一個(gè)函數(shù),所以同樣可以找到Function.prototype)--->在第二次找到call的時(shí)候讓方法執(zhí)行,方法中的this是fn1.call(即變?yōu)閒n1.call();也就相當(dāng)于是call函數(shù)本身),---->讓這個(gè)方法中的this變?yōu)閒n2,然后再讓fn1.call執(zhí)行(也就相當(dāng)于把call函數(shù)中的this變?yōu)閒n2,也就是執(zhí)行fn2)---->最后結(jié)果為2
3、fn1.call.call.call.call.call(fn2);最終執(zhí)行的是fn2
——————————————————————————————————————————
fn.call(obj):讓fn方法中的this變?yōu)榈谝粋€(gè)參數(shù)obj
var obj={name:"張三“};
function fn(num1,num2){
consloe.log(num1+num2);
console.log(this);
}
fn(100,200); //this--->window;num1=100,num2=200--->300
fn.call(100,200); //this--->100,num1=200,num2=undefined---->undefined
fn.call(obj,100,200); //this-->obj,num1=100,num2=200;
fn.call(); //this--->window;在嚴(yán)格模式下(”use strict“)this--->undefined
fn.call(null); //this--->window;在嚴(yán)格模式下(”use strict“)this--->null
fn.call(undefined); //this--->window;在嚴(yán)格模式下(”use strict“)this--->undefined