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

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的concat方法实例代码(数组连接)

    JavaScript的concat方法实例代码(数组连接) JavaScript中的concat方法用于连接两个或多个数组,并返回一个新的数组。该方法不会改变原始数组,而是创建一个新的数组。 语法 array.concat(array1, array2, …, arrayX) 其中, array1, array2, …, arrayX 是要连接的数组…

    JavaScript 2023年5月27日
    00
  • websocket直接绕过JS加密示例及思路原理

    下面是对“websocket直接绕过JS加密示例及思路原理”的完整攻略。 什么是WebSocket WebSocket是一种在单个TCP连接上进行全双工通信的协议。它使得浏览器和服务器之间的数据交换变得更加实时和高效。 WebSocket旨在通过在数据传输过程中进行有效的适应和优化,使Web应用程序更加互动式和实时化。能够支持长时间开放的TCP连接,同时为W…

    JavaScript 2023年5月19日
    00
  • JavaScript高级编程之Array的用法总结

    JavaScript高级编程之Array的用法总结 1. Array是什么? 在JavaScript中,Array是一种用来存储和操作一组值的有序集合,可以容纳多种类型的数据,并且可以动态扩展大小。Array是JavaScript编程中最常用的数据类型之一,也是编写JavaScript程序时必须掌握的重要内容之一。 2. Array的常用方法 2.1 增加和…

    JavaScript 2023年5月27日
    00
  • 浅析JavaScriptSerializer类的序列化与反序列化

    浅析JavaScriptSerializer类的序列化与反序列化 什么是JavaScriptSerializer类 JavaScriptSerializer类是一个.NET框架中的类,它是用于将对象序列化和反序列化为JSON格式的工具类。在Web应用程序中,它通常用于将服务器端的数据(比如查询数据库后查询出的结果集)转换为JSON格式,然后通过HTTP响应发…

    JavaScript 2023年5月27日
    00
  • 总结javascript中的六种迭代器

    下面是对 JavaScript 中的六种迭代器的详细讲解。 什么是迭代器 在开始讲解迭代器之前,先来了解一下什么是迭代器。迭代器是一种设计模式,用于遍历任何类型的数据。简单来说,迭代器就是一个对象,该对象允许在一次运行中获取序列中的各个元素。 JavaScript 中的六种迭代器 JavaScript 提供了内置的六种迭代器,分别为: forEach() m…

    JavaScript 2023年5月27日
    00
  • JS和JQ的event对象区别分析

    JS和JQ都有一个event对象,但是它们的区别还是比较明显的。在这里我们来详细讲解一下。 1. JS的event对象 在JS中,事件触发时会自动生成一个event对象,并且通过addEventListener或者window.attachEvent绑定的函数,第一个参数都是event。event对象包含了一些事件的属性和方法,可以方便的获取事件的相关信息。…

    JavaScript 2023年6月10日
    00
  • 静态页面利用JS读取cookies记住用户信息

    静态页面读取cookie的基本原理 在使用JavaScript读取cookie之前,我们需要先了解什么是cookie。Cookie是指客户端保存在浏览器中的一小段文本数据,由Web服务器生成并存储在用户计算机上,当下次用户访问相同的站点时,服务器可读取此cookie的值,来判断用户是否合法,以及是否登录过等。 读取cookie需要使用JavaScript中的…

    JavaScript 2023年6月11日
    00
  • js以对象为索引的关联数组

    “以对象为索引的关联数组”在JavaScript中被称为“对象”,也是一种常见的数据结构。从表面上看,它与其他编程语言中的字典或散列表/哈希表类似,但实际上更加灵活和强大。 基本概念 JavaScript中的对象是一组键/值对,其中键是字符串(或符号)类型,而值可以是任何数据类型(包括另一个对象)。对象中的键是唯一的,且不允许重复,但同一个对象的多个键可以指…

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