JavaScript之call模拟实现

JavaScript之call模拟实现

call
  1. call()方法在使用指定的this值和若干个指定的参数值的前提下调用某个函数和方法。
var obj = {
    value : 1
}

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

注意:

  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函数

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)

注意: 传入的参数不确定,该怎么办!

我们可以从Arguments对象中取值,取出第二个到最后一个参数,然后放到一个数组里。
var args = []
for(let i=1; i<arguments.length; i++) {
    args.push('arguments['+i+']');
}

不定长的参数问题解决了,我们接着要把这个参数数组放到要执行的函数的参数里面去。

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

第二版代码如下:

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. 函数是可以有返回值的

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))

 

转载于:https://my.oschina.net/u/4052053/blog/3020395

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值