實現call函式,手寫Function.prototype.call函式

webMinStudent發表於2020-10-18

實現call函式:

使用call函式:

function fn(x,y){
	console.log(this);
	return x+ y
}
let obj = {
  name:'李雲龍'
}
//1.普通使用
fn(10,20) // this---->window,30
//2.使用call
fn.call(obj,10,20)// this--->obj , 30

思路:

  1. 為obj新增一個屬性,屬性值就是fn
  2. 執行那個新增的屬性(方法),獲取返回值,將返回值返回
  3. 刪除我們新增的屬性
Function.prototype.myCall = function(context,...params){
	//此時context---->就是obj
	//此時this----->fn
	context.xxx = this //為這個物件新增一個方法
	let result = context.xxx(...params);//執行這個方法,獲取返回值
	delete context.xxx;//刪除我們新增的那個屬性,我們不能改變原本的物件結構
	return result
}
//------------------驗證----------------------
function fn(x,y){
	console.log(this.name);
	return x+ y
}
let obj = {
  name:'李雲龍'
}
//1.普通使用
fn(10,20) // this---->window,30
//2.使用call
fn.myCall(obj,10,20)// this--->obj , 30

進一步完善

  • 我們新增的屬性,如果和原本的物件的屬性一樣,那麼就會發生改變原來的屬性,這是不允許的
  • 對context進行處理,如果是null,那麼就是window,
  • 如果context是基本型別值,那麼需要將基本型別值轉化為對應的引用型別值
  • new context.constructor(),時一般都可以,但是如果context時Symbol型別,那麼就會報錯,它不允許被new
Function.prototype.myCall = function(context,...params){
    //context ---> 一個物件,我們需要改變的this為context
    //this---->就是那個函式
    context == null ? context = window : null
    //如果傳入的是一個null或者是undefined那麼,context就是window,否則什麼都不做
    !/^(object|function)$/.test(typeof context)?context = Object(context):null
    let key = Symbol('key');
    context[key] = this;
    //這個是為context新增一個屬性,屬性值為一個函式(this就是一個函式)
    let result = context[key](...params);
    //我們執行context這個物件中的一個方法,就是執行了 this這個函式,並且獲得函式執行的返回值
    delete context[key];
    //最後刪除一個我們新增的那個屬性
    return result
    //那麼我就需要返回這個函式執行的結果
    
    
}
//-----------------驗證--------------------
function fn(x,y){
	console.log(this.name);
	return x+ y
}
let obj = {
  name:'李雲龍'
}
//1.普通使用
fn(10,20) // this---->window,30
//2.使用call
fn.myCall(20,10,20)//傳入的是一個基本型別的值 this--->20 , 30


相關文章