JavaScript之call模擬實現

JavaScript之call模擬實現javascript

call
  1. call()方法在使用指定的this值和若干個指定的參數值的前提下調用某個函數和方法。
var obj = {
    value : 1
}

function foo(){
    console.log(this.value)
}
foo.call(obj)

注意:java

  1. call改變了this的指向,指向到obj
  2. foo函數執行了

模擬實現第一步
試想當調用 call 的時候,把obj對象改形成以下
var obj = {
    value :1,
    foo : function(){
        console.log(this.value)
    }
}
obj.foo()

這個時候this就指向了obj數組

可是這樣卻給obj對象上添加了一個屬性。
這樣可不行,咱們用 delete 刪除掉就行了。
因此咱們模擬步驟能夠分爲:
  1. 將函數設置爲對象的屬性
  2. 執行該函數
  3. 刪除該函數

以上個例子爲例,就是:函數

// 第一步
obj.fn=foo
// 第二步
obj.fn()
// 第三步
deleteobj.fn
 

按照這個思路,嘗試寫初版call2函數this

Function.prototype.call2 = function(context){
    context.fn=this
    context.fn()
    delete context.fn
}

var obj = {
    value : 2
}
function foo(){
    console.log(this.value)
}

foo.call2(obj)
 
模擬實現第二步
一開始也有提到,call 函數還能指定參數執行函數
var obj = {
    value : 1
}

function foo(name,age){
    console.log(name)// hy
    console.log(age)// 18
    console.log(this.value)// 1
}

foo.call(obj,'hy',18)

注意: 傳入的參數不肯定,該怎麼辦!spa

咱們能夠從Arguments對象中取值,取出第二個到最後一個參數,而後放到一個數組裏。
var args = []
for(let i=1; i<arguments.length; i++) {
    args.push('arguments['+i+']');
}

不定長的參數問題解決了,咱們接着要把這個參數數組放到要執行的函數的參數裏面去。prototype

eval('context.fn('+ args +')')

第二版代碼以下:code

Function.prototype.call2 = function(context){
    context.fn=this
    var args = []
    for(let i=1; i<arguments.length; i++) {
        args.push('arguments['+i+']');
    }
    eval('context.fn('+args+')');
    delete context.fn
}


var obj = {
    value :2
}
function foo(name,age){
    console.log(name)
    console.log(age)
    console.log(this.value)
}

foo.call2(obj,'hy',18)

模擬實現第三步對象

還有兩個地方須要注意:
  1. this參數能夠傳null,當爲null的時候this指向window
var value = 1
function foo(){
    console.log(this.value)
}
foo.call(null)// 1

  2. 函數是能夠有返回值的ip

var obj = {
    value :1
}
function foo(name,age){
    return{
        value : this.value,
        name : name,
        age : age
    }
}
console.log(foo.call(obj,'hy',18))// { value: 1, name: 'hy', age: 18 }

到目前爲止已經完成了 call 的模擬

Function.prototype.call2 = function(context){
    context.fn=this
    var args = []
    for(leti=1;i<arguments.length;i++) {
        args.push('arguments['+i+']');
    }
    var result = eval('context.fn('+args+')');
    delete context.fn
    return result
}


var obj = {
    value : 2
}
function foo(name,age){
    return{
        value : this.value,
        name : name,
        age : age
    }
}
console.log(foo.call2(obj,'hy',18))
相關文章
相關標籤/搜索