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日

相关文章

  • JS中setTimeout和setInterval的最大延时值详解

    JS中setTimeout和setInterval的最大延时值详解 在 JavaScript 中,setTimeout 和 setInterval 都可以用来延迟执行一段代码。但是它们的使用时需要注意,因为它们都有一个最大延时值。 setTimeout 的最大延时值 在 JavaScript 中,可以使用 setTimeout 来延迟执行一段代码。setTi…

    JavaScript 2023年6月11日
    00
  • 漫谈JS引擎的运行机制 你应该知道什么

    漫谈JS引擎的运行机制 你应该知道什么 什么是JS引擎 JS引擎是指运行JavaScript程序的解释器,它可以解析、执行JavaScript代码,并将其转换成计算机能够理解的语言。目前主流的JS引擎有V8、SpiderMonkey、Chakra等。 JS引擎的运行流程 JS引擎的运行流程通常可以分为以下几个步骤: 词法分析:将JavaScript代码解析成…

    JavaScript 2023年6月10日
    00
  • JS数组push、unshift、pop、shift方法的实现与使用方法示例

    JS数组方法push、unshift、pop、shift实现及使用方法 push方法 push() 方法用于在数组末尾添加一个或多个元素,并返回数组的长度。 语法 arrayObject.push(newelement1,newelement2,….,newelementX) 示例 var fruits = ["Banana", &q…

    JavaScript 2023年5月27日
    00
  • springboot中thymeleaf模板使用详解

    这里是 SpringBoot 中 Thymeleaf 模板使用详解的完整攻略: 什么是Thymeleaf Thymeleaf 是一种现代化的服务器端 Java 模板引擎,可以与 Spring Boot 集成使用,支持 HTML、XML、JavaScript、CSS 甚至纯文本。模板文件可以使用包含表达式的标记替换,可以非常方便的将模型数据绑定到 HTML U…

    JavaScript 2023年6月10日
    00
  • React Mobx状态管理工具的使用

    React Mobx是一款流行的状态管理工具,通过简洁的语法和高效的性能,帮助开发者简化状态管理的难度。下面我将详细讲解React Mobx的使用步骤,希望对初学者和需要提高的开发者有所帮助。 一、环境准备 在学习React Mobx之前,需要在你的项目中安装和引入mobx和mobx-react两个依赖库。你可以使用npm安装依赖,命令如下: npm ins…

    JavaScript 2023年6月10日
    00
  • 深入理解javascript中的this

    深入理解JavaScript中的this的完整攻略 什么是this 所谓 this ,就是JavaScript中一个相对特殊的关键字,指向当前函数的执行环境。换句话说,this 可以看做是一个对象,这个对象指向的是函数执行时所在的环境对象,而这个环境对象是由调用方式来决定的。 this指向的典型情况 在JavaScript中,this 的指向是根据如何调用当…

    JavaScript 2023年6月10日
    00
  • JavaScript 面向对象之命名空间

    JavaScript 面向对象之命名空间 JavaScript 是一门支持面向对象编程的语言,但在实践中,我们发现 JavaScript 的命名空间机制并不完整或者说不够严谨。因此,我们可以借助 Object 对象和函数声明的方式来实现 JavaScript 的命名空间。 命名空间的概念 命名空间是一个用于“组织代码”的容器,它类似于文件系统中文件夹的概念,…

    JavaScript 2023年5月27日
    00
  • javascript三种代码注释方法

    JavaScript中有三种注释方法:单行注释、多行注释和文档注释。 1. 单行注释 单行注释用于注释一行代码,使用双斜杠(//)开头。 示例: // 这是一行单行注释 console.log("Hello World!"); 输出结果: Hello World! 2. 多行注释 多行注释用于注释多行代码,使用斜杠星号(/*)作为开始标记…

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