资讯专栏INFORMATION COLUMN

使用模拟实现的方式探究call 和 apply 的原理

whlong / 1363人阅读

摘要:使用模拟实现的方式探究和的原理作用方法就是在使用一个指定值和若干个指定的参数值的前提下调用某个函数或者方法。如果不对进行绑定执行会返回也就是说改变了的指向到了。

使用模拟实现的方式探究call 和 apply 的原理 call

作用:

call() 方法就是在使用一个指定 this 值和若干个指定的参数值的前提下调用某个函数或者方法。
var foo = {
    value : 1
}
function bar() {
    console.log(this.value)
}
// 如果不对this进行绑定执行bar() 会返回undefined
bar.call(foo) // 1

也就是说call()改变了 this 的指向到了 foo

下面进行一下模拟实现

试想当调用 call 的时候,也就是类似于

var foo = {
    value: 1,
    bar: function() {
        console.log(this.value)
    }
}
foo.bar() // 1

这样就把 this 指向到了 foo 上,但是这样给 foo 对象加了一个属性,有些瑕疵,不过不要紧,执行完删除这个属性就可以完美实现了。

也就是说步骤可以是这样:

将函数设为对象的属性

执行这个函数

删除这个函数

下面就试着去实现一下:

Function.prototype.call2 = function(context) {
    context.fn = this // this 也就是调用call的函数
    var result = context.fn()
    delete context.fn()
    return result
}

var foo = {
    value: 1
}
function bar() {
    console.log(this.value)
}
bar.call2(foo) // 1

但是这样有一个小缺陷就是call() 不仅能指定this到函数,还能传入给定参数执行函数比如:

var foo = {
    value: 1
}
function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value)
}
bar.call(foo, "black", "18")
// black
// 18
// 1

特别要注意的一点是,传入的参数的数量是不确定的,所以我们要使用arguments 对象,取出除去第一个之外的参数,放到一个数组里:

Function.prototype.call2 = function(context) {
    context.fn = this // this 也就是调用call的函数
    var args = [...arguments].slice(1)
    var result = context.fn(...args)
    delete context.fn()
    return result
}

var foo = {
    value: 1
}
function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}
bar.call2(foo, "black", "18") // black 18 1

还有一点需要注意的是,如果不传入参数,默认指向为 window,所以最终版代码:

Function.prototype.call2 = function(context) {
    var context = context || window
    context.fn = this // this 也就是调用call的函数
    var args = [...arguments].slice(1)
    var result = context.fn(...args)
    delete context.fn()
    return result
}
var value = 1
function bar() {
    console.log(this.value)
}
bar.call2()
apply

apply的方法和 call 方法的实现类似,只不过是如果有参数,以数组形式进行传递,直接上代码:

Function.prototype.apply2 = function(context) {
    var context = context || window
    context.fn = this // this 也就是调用apply的函数
    var result
    // 判断是否有第二个参数
    if(arguments[1]) {
        result = context.fn(...arguments[1])
    } else {
        result = context.fn()
    }
    delete context.fn()
    return result
}

var foo = {
    value: 1
}
function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}
bar.apply2(foo, ["black", "18"]) // black 18 1

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97094.html

相关文章

  • 我们不背诵 API,只实现 API

    摘要:接下来,我们换一种思路,用一个相对较新的来实现方法。从这道题目看出,相比考察死记硬背,这样的实现更有意义。对数组的操作我们不能陌生,其中方法更要做到驾轻就熟。最后,我们再看下社区上著名的和的实现。 有不少刚入行的同学跟我说:JavaScript 很多 API 记不清楚怎么办?数组的这方法、那方法总是傻傻分不清楚,该如何是好?操作 DOM 的方式今天记,明天忘,真让人奔溃! 甚至有的开发...

    wudengzan 评论0 收藏0
  • 我们不背诵 API,只实现 API

    摘要:接下来,我们换一种思路,用一个相对较新的来实现方法。从这道题目看出,相比考察死记硬背,这样的实现更有意义。对数组的操作我们不能陌生,其中方法更要做到驾轻就熟。最后,我们再看下社区上著名的和的实现。 有不少刚入行的同学跟我说:JavaScript 很多 API 记不清楚怎么办?数组的这方法、那方法总是傻傻分不清楚,该如何是好?操作 DOM 的方式今天记,明天忘,真让人奔溃! 甚至有的开发...

    wayneli 评论0 收藏0
  • 探究call apply 原理

    建议看这片文章时可以点击音乐

    qqlcbb 评论0 收藏0
  • javasscript - 收藏集 - 掘金

    摘要:跨域请求详解从繁至简前端掘金什么是为什么要用是的一种使用模式,可用于解决主流浏览器的跨域数据访问的问题。异步编程入门道典型的面试题前端掘金在界中,开发人员的需求量一直居高不下。 jsonp 跨域请求详解——从繁至简 - 前端 - 掘金什么是jsonp?为什么要用jsonp?JSONP(JSON with Padding)是JSON的一种使用模式,可用于解决主流浏览器的跨域数据访问的问题...

    Rango 评论0 收藏0

发表评论

0条评论

whlong

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<