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))
相关文章
相关标签/搜索