js的call函式”原始碼”

標子發表於2019-02-16
Function.prototype.call=function(x){
    x = x || {};
    x[`fn`] = this;
    var args = ``;//引數列表
    var type;
    for (var i = 1; i<arguments.length;i++) {        
        if (typeof arguments[i] === `string`) {//引數是字串,需要在兩邊加引號,因為在拼接引數的時候會被丟掉
            type = `"`+arguments[i] + `"`;
        }
        else if (typeof arguments[i] === `function`) {//引數是函式的話,"反編譯"出函式的程式碼
            type = arguments[i].toString();
        }
        else if (typeof arguments[i]  === `object` ) {//陣列和物件可能含有複雜的組合型別資料,可以通過遍歷變數轉成字串
            if (/function Array()/.test(arguments[i][`constructor`])) {//引數是陣列則在陣列兩邊加上[,]
                type = "[" + arguments[i] + "]";
            } else {
                type = JSON.stringify(arguments[i])//物件的話,json化,然後執行的時候反json化
            }    
        } else {
            type = arguments[i];//數字型別
        }
        args = args + type +`,`;
    }
    args = args.slice(0,args.length-1);//去掉最後的逗號
    var q = new Function(`var x = arguments[0];x.fn(`+args+`)`)//new Function的時候作用域是獨立的,無法訪問call裡面的x,所以需要傳進去
    q(x)
}

function parse_Array_Object(arg) {
    //可以npm install traverse-deep和結合js的map函式進行相應處理,主要是遍歷arg的每一個元素,進行型別判斷,然後返回相應的字串
    //to do ..
}
function a(a){
    console.log(this,arguments)
}
a.call({d:1},2,`s`,[1,2,3],{s:1},function() {})

相關文章