首先看數(shù)組中的一個(gè)方法:
Array.prototype.slice = function() {}
var ary = [12, 23, 34];
// ary.slice -> ary這個(gè)實(shí)例,通過原型鏈的查找機(jī)制,找到Array.prototype上的slice方法,此時(shí)是該函數(shù)的地址
// ary.slice(); -> 讓找到的slice方法執(zhí)行,在執(zhí)行slice方法的過程中,才把a(bǔ)ry數(shù)組進(jìn)行截取
call方法的作用:
-> 首先讓原型上的call方法執(zhí)行,在執(zhí)行call方法的時(shí)候,讓fn方法中的this變?yōu)榈谝粋€(gè)參數(shù)值obj;然后再把fn這個(gè)函數(shù)執(zhí)行。
var obj = {
name: 'derrick'
}
function fn() {
console.log(this);
}
fn(); // this -> window
fn.call(obj); // this -> obj
自己模擬內(nèi)置的call方法,寫一個(gè)myCall方法,深入探討call方法執(zhí)行的原理。
Function.prototype.myCall = function (context) {
// -> myCall方法中的this就是當(dāng)前要操作和改變其this關(guān)鍵字的那個(gè)函數(shù)
// -> 1. 讓fn中的this關(guān)鍵字變?yōu)閏ontext的值 -> obj
// -> 讓this這個(gè)函數(shù)中的"this關(guān)鍵字"變?yōu)閏ontext
// var that = eval(this.toString().replace('this', context));
// -> 2. 讓fn方法在執(zhí)行
this();
}
fn.myCall(obj); // -> myCall方法中的this是fn
function sum() {
}
sum.myCall(obj); // -> myCall方法中this是sum
下面看一道面試題:
function fn1() {
console.log(1);
}
function fn2() {
console.log(2);
}
fn1.call(fn2); // -> 首先fn1通過原型鏈機(jī)制找到Function.prototype上的call方法,并且讓call方法執(zhí)行,
// -> 此時(shí)call這個(gè)方法中的this就是要操作fn1 -> 在call方法代碼的執(zhí)行過程中,首先fn1中的"this關(guān)鍵字"變?yōu)閒n2,
// 再讓fn1這個(gè)方法執(zhí)行 -> 最終執(zhí)行結(jié)果為 1
fn1.call.call(fn2); // -> fn1.call 首先fn1通過原型鏈機(jī)制找到Function.prototype上的call方法,
// 然后再讓call方法通過原型再找到Function原型上的call(因?yàn)閏all本身的值也是一個(gè)函數(shù),所以同樣可以找到Function.prototype),在
// 第二次再找到call的時(shí)候,讓方法執(zhí)行,方法中的this是fn1.call, 首先讓這個(gè)方法中的this變?yōu)閒n2,然后再讓fn1.call執(zhí)行
// -> 輸出結(jié)果為 2
再次分析:
function xxx(context) {
// 1. 讓this這個(gè)函數(shù)中的"this關(guān)鍵字"變?yōu)閏ontext
// 2. 讓this方法執(zhí)行
this();
}
Function.prototype.myCall = xxx;
fn1.call.call(fn2);
// -> fn1.call -> xxx;
// -> xxx.call(fn2) -> 先讓call方法執(zhí)行,call中this是xxx,讓xxx中的this變?yōu)閒n2,
// 再讓xxx執(zhí)行 -> 2
fn1.call.call.call.call.call(fn2); // 2
Function.prototype.call(fn1); // Funciton.prototype是空函數(shù),將其執(zhí)行就是空函數(shù)執(zhí)行,直接銷毀
Function.prototype.call.call.call.call(fn1); // fn1() -> 1