JavaScript函数Call、Apply原理实例解析

yizhihongxing

JavaScript函数Call、Apply原理实例解析

什么是Call、Apply

在JavaScript中,每个函数都是一个对象,函数对象可以有方法,比如call和apply方法。这两个方法都是用来改变函数内部this的指向的。

call方法的语法如下:

function.call(thisArg, arg1, arg2, ...)
  • thisArg:在调用函数时,将其绑定到函数的this上。
  • arg1,arg2,...:传递给函数的参数列表。

apply方法的语法如下:

function.apply(thisArg, [argsArray])
  • thisArg:在调用函数时,将其绑定到函数的this上。
  • argsArray:传递给函数的参数列表,必须是数组或类数组对象。

Call、Apply的作用

改变this指向

通过call和apply方法,可以改变函数内部this的指向,让其指向指定的对象。下面给出一个简单的例子:

var obj = {
    name: 'Tom'
};

function sayName() {
    console.log(this.name);
}

sayName(); // undefined
sayName.call(obj); // Tom

在上面的例子中,sayName函数本身并没有任何问题,但是在全局上下文,this指向的是全局对象,因此打印出undefined。在使用call方法时,指定this为obj,因此打印出了obj的name属性。

借用函数对象

通过call和apply方法,可以实现函数对象的借用。下面给出一个示例:

function sum() {
    var result = 0;
    for(var i = 0; i < arguments.length; i++) {
        result += arguments[i];
    }
    return result;
}

var arr = [1, 2, 3];

console.log(sum.apply(null, arr)); // 6

在上面的例子中,sum函数实现了一个可以接收任意数量参数的求和函数。在调用时,我们将数组arr作为apply方法的第二个参数传入,因此实现了对数组的求和。

Call、Apply的实现原理

在JavaScript中,每个函数都是Function类型,因此每个函数对象都具有call和apply方法。可以通过以下方式来自己实现一个call方法:

Function.prototype.myCall = function(thisArg, ...args) {
    // 1. 判断this的类型,必须为函数类型
    if(typeof this !== 'function') {
        throw new TypeError('myCall should be call on a function!');
    }

    // 2. 将this关键字绑定到thisArg上
    thisArg = thisArg || window;
    thisArg.fn = this;

    // 3. 执行函数
    var result = thisArg.fn(...args);

    // 4. 删除函数属性
    delete thisArg.fn;

    // 5. 返回函数执行结果
    return result;
}

实现apply方法的原理与call方法类似,只是参数列表不同。

Function.prototype.myApply = function(thisArg, args) {
    // 1. 判断this的类型,必须为函数类型
    if(typeof this !== 'function') {
        throw new TypeError('myApply should be apply on a function!');
    }

    // 2. 将this关键字绑定到thisArg上
    thisArg = thisArg || window;
    thisArg.fn = this;

    // 3. 执行函数
    var result = thisArg.fn(...args);

    // 4. 删除函数属性
    delete thisArg.fn;

    // 5. 返回函数执行结果
    return result;
}

示例

示例一

var obj1 = {
    name: 'Tom',
    age: 18,
    sayNameAge: function() {
        console.log(this.name + ' is ' + this.age + ' years old.');
    }
};

var obj2 = {
    name: 'Jerry',
    age: 20
};

obj1.sayNameAge(); // Tom is 18 years old.
obj1.sayNameAge.call(obj2); // Jerry is 20 years old.

在上面的例子中,obj1和obj2都有name和age属性,但是obj1有一个sayNameAge方法,该方法打印出名字和年龄。在调用sayNameAge方法时,this指向的是obj1,因此第一次调用打印出了Tom的信息。在使用call方法调用sayNameAge方法时,this指向的是obj2,因此第二次调用打印出了Jerry的信息。

示例二

function max() {
    var result = -Infinity;
    for(var i = 0; i < arguments.length; i++) {
        if(arguments[i] > result) {
            result = arguments[i];
        }
    }
    return result;
}

var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];

console.log(max.apply(null, arr1)); // 3
console.log(max.call(null, ...arr2)); // 6

在上面的例子中,max函数是一个求最大值的函数。在第一个例子中,我们使用apply方法将数组arr1作为参数列表传入函数,从而实现了对数组的求最大值。在第二个例子中,我们使用call方法时,使用spread操作符将数组arr2展开成参数列表,并按原样调用函数,也实现了对数组的求最大值。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript函数Call、Apply原理实例解析 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • JavaScript 正则应用详解【模式、欲查、反向引用等】

    JavaScript 正则应用详解【模式、欲查、反向引用等】攻略 正则表达式是用来描述或者匹配一些字符串模式的工具。JavaScript 支持正则表达式,可以使用正则表达式进行字符串的匹配、查找、替换、拆分等操作。本文将详细介绍 JavaScript 正则表达式的常用应用。 一、正则表达式概述 正则表达式是一种字符模式,用于匹配或识别一些特定的字符串模式。正…

    JavaScript 2023年5月27日
    00
  • 详解Javascript事件驱动编程

    详解Javascript事件驱动编程攻略 Javascript事件驱动编程是Javascript开发中一个重要的概念,它可以让编写的网页更有交互性。本攻略将详细地介绍Javascript事件驱动编程的概念、方法和注意事项。 概念 Javascript事件驱动编程是一种编程范式,它的核心思想是通过触发事件来执行代码。在Web开发中,当用户与网页发生交互时(比如…

    JavaScript 2023年5月27日
    00
  • 解决js中的setInterval清空定时器不管用问题

    当我们使用 JavaScript 中的 setInterval 函数来实现定时器时,需要注意清空定时器的问题。如果不正确地清空定时器,会导致在后续代码执行中仍然存在遗留的定时器,从而出现各种各样的问题,例如内存泄漏或者无法及时响应后续清空操作等。 为了避免这个问题,我们可以使用以下两种方法来清空定时器。 方法一:使用 clearInterval 函数清空定时…

    JavaScript 2023年6月11日
    00
  • Javascript this指针

    Javascript中的this指针用于指示当前执行的代码所属的对象。在不同的情况下,this指向的对象是不同的,因此在使用this时需要谨慎处理。下面将详细介绍Javascript this指针的相关知识和使用技巧。 什么是this指针? 在Javascript中,this指针是一个关键字,用于指示当前执行的代码所属的对象。this关键字可以在任何函数中使…

    JavaScript 2023年6月11日
    00
  • JS 文件传参及处理技巧分析

    JS文件传参及处理技巧分析 在JavaScript中,文件传参是一个非常常见的操作,尤其是在web开发中。在本文中,我们将介绍文件传参的一些技巧和处理方法。 传统方式:URL参数传递 在web开发中,最常见的文件传参方式是通过URL参数传递。这种方式将参数作为URL的一部分,通常被称为GET方式。以下是一个典型的URL参数的例子: http://exampl…

    JavaScript 2023年5月27日
    00
  • win2003下杀任何进程的命令(taskkill,ntsd)

    在Win2003系统下,有两个命令能够杀死进程,分别是taskkill和ntsd。 使用taskkill命令 命令格式 taskkill [/S system [/U username [/P [password]]]] {[/FI filter] [/PID processid | /IM imagename]} [/T] [/F] 参数说明 /S sys…

    JavaScript 2023年5月28日
    00
  • HTML中不支持静态Expando的元素的问题

    “HTML中不支持静态Expando的元素的问题”指的是在某些HTML元素上添加特定属性或JS对象时,如果该元素不支持静态Expando,则可能会导致问题。通常,此类问题表现为少量JS工作正常,大量JS工作不正常。 以下是解决“HTML中不支持静态Expando的元素的问题”的攻略: 1.了解什么是静态Expando Expando是为DOM元素添加的自定义…

    JavaScript 2023年6月10日
    00
  • js读取csv文件并使用json显示出来

    下面是 JS 读取 CSV 文件并使用 JSON 显示的攻略: 1. CSV 文件格式 CSV(Comma Separated Values,逗号分隔值)格式是一种通用的电子表格格式,也是在 Web 开发中常用的数据格式之一。CSV 文件以纯文本方式存储,文件由一行行数据组成,每行数据由多个字段组合而成,字段之间使用逗号(,)分隔。 一个简单的 CSV 文件…

    JavaScript 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部