(十六)call、apply、bind介绍、区别和实现

news/2025/3/12 12:24:08/

函数中的this指向:

函数中的this指向是在函数被调用的时候确定的,也就是执行上下文被创建时确定的。在一个执行上下文中,this由调用者提供,由调用函数的方式来决定。

类数组对象arguments:

arguments只在函数(除了箭头函数)中存在的类数组参数对象,储存了我们传入的所有参数。

一、call

  • call(this, 参1, 参2, ...),第一个参数为this,后面是函数的一系列参数
  • 当第一个this参数为null、undefind时,默认this指向window
  • 函数立即调用
  • 原理:实际就是把函数放到call传入的第一个参数上,然后再调用该函数。
  • 实现:
javascript">/*** 手写call* @param {*} context* @param  {...any} args* @returns*/
Function.prototype.mycall = function (context, ...args) {if (typeof this !== "function") {throw new TypeError("Error");}//context不传,默认windowlet _this = context || window;//假如原来的context上存在fn属性会产生冲突,暂存一下。let temp = null;if (_this.fn) {temp = _this.fn;}_this.fn = this;// 调用函数let res = _this.fn(...args);if (temp) {//恢复_this对象上的原来的fn属性_this.fn = temp;} else {//删除_this对象上的fn属性delete _this.fn;}return res;// 测试
let num = 1;
let obj = {num: 2,fn: "this is obj.fn",
};
function test(a, b, c, d) {let num = 1;console.log(this.num, "test参数", a, b, c, d);
}
test(4, 3, 2, 1);
// 调用myCall函数
test.mycall(obj, 4, 3, 2, 1);// 检查obj本身的fn是否被修改
console.log(obj.fn);
};

在这里插入图片描述

二、apply

  • applyl(this, arr),第一个参数为this,第二个参数是一个参数数组
  • 当第一个this参数为null、undefind时,默认this指向window
  • 函数立即调用
  • 原理:和call类似,区别就是参数不同,call方法接受的参数是一个参数列表,而apply接受的是一个包含多个参数的数组。
  • 实现:
javascript">// 和myCall的不同之处1:参数
Function.prototype.myApply=function(context){if(typeof this!== 'function'){throw new TypeError('type error')}console.log("myApply", arguments, context, this);let _this = context || window;let temp = null;if (_this.fn) {temp = _this.fn;}_this.fn = this;let res;//   判断是否存在第二个参数if (arguments[1]) {res = _this.fn(...arguments[1]);} else {res = _this.fn();}// 删除context对象上的fn属性if (temp) {_this.fn = temp;} else {delete _this.fn;}return res;
}// 测试
let num = 1;
let obj = {num: 2,fn: "this is obj.fn",
};
function test(a, b, c, d) {let num = 1;console.log(this.num, "test参数", a, b, c, d);
}
test(4, 3, 2, 1);
// 调用myCall函数
test.myApply(obj, [4, 3, 2, 1]);// 检查obj本身的fn是否被修改
console.log(obj.fn);

结果:
在这里插入图片描述

三、bind

  • bind(this, 参1, 参2, ...),第一个参数为this,后面是函数的一系列参数
  • 当第一个this参数为null、undefind时,默认this指向window
  • bind方法的返回值是函数,不会立即调用
  • 原理:(1)bind返回的函数作为构造函数使用的时候,bind绑定的this会失效,到那时参数有效。(2)如何判断bind 是正常使用还是当构造函数,根据this。当为构造函数时,this指向实例对象(this的prototype在该构造函数上)
  • 实现:
javascript">Function.prototype.myBind = function (_this) {if (typeof this !== "function") {throw new TypeError("_this must be a function");}//获取参数let args0 = [...arguments].slice(1);//保存this,如果作为构造函数使用,此时this会指向实例let that = this;let context = _this||window;return function Fn(...args) {// 如果是new的形式来使用绑定函数的if (this instanceof Fn) {return new that(...args0, ...args);} else {return that.call(context , ...args0, ...args);}};
};//测试:
function Point(x, y) {this.x = x;this.y = y;
}// 情况1:正常调用bind函数
let testObj = {};
let MyPoint = Point.myBind(testObj, 0);
MyPoint(1);
console.log(testObj);
//情况2:bind返回的函数作为构造函数
let newObj = new MyPoint(2);
console.log(newObj);

结果:
在这里插入图片描述

四、区别:

1、相同点:
(1) call、apply、bind 都有改变this指向的作用。
(2)都可以给参数传参
2、不同点:
(1)call、bind 的第二个、后续参数是多个;而apply接收的第二参数是数组。
(2)call、apply会立即执行参数;而bind不会立即执行,得再调用才能执行。

参考:
1、https://blog.csdn.net/weixin_51472145/article/details/132566180
2、https://blog.csdn.net/weixin_40856652/article/details/124293144?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171348813116800178533534%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=171348813116800178533534&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-124293144-null-null.142v100pc_search_result_base1&utm_term=call%E3%80%81apply%E5%92%8Cbind%E7%9A%84%E5%8C%BA%E5%88%AB&spm=1018.2226.3001.4187
3、https://blog.csdn.net/sinat_41904410/article/details/104396112


http://www.ppmy.cn/news/1424610.html

相关文章

Adobe Premiere Pro将加入AI生成式功能,以提高视频编辑的效率;OpenAI宣布在东京设立亚洲首个办事处

🦉 AI新闻 🚀 Adobe Premiere Pro将加入AI生成式功能,以提高视频编辑的效率 摘要:Adobe宣布,将为Premiere Pro引入由生成式AI驱动的新功能,以提高视频编辑的效率。这些功能包括“生成扩展”,能…

ArrayList,Vector,LinkedList内存解析

1.ArrayList (1). 特点 : 实现了List接口&#xff0c;存储有序的&#xff0c;可重复的数据.底层使用Object[]数组存储.线程不安全.(底层方法未用synchronized修饰.) (2). 版本解析 : <i> : JDK7版本 ArrayList<String> list &#xff1d;new ArrayList<&…

OV通配符证书:安全、便捷的网络认证新选择

OV通配符证书&#xff0c;即组织验证型通配符证书&#xff0c;其最大特点在于其通配符功能。这意味着&#xff0c;一个OV通配符证书可以覆盖同一主域名下的多个子域名&#xff0c;大大简化了证书管理和维护的复杂性。无论是大型企业还是个人网站&#xff0c;都可以通过OV通配符…

服务器上部署GPU版的milvus向量数据库

1、安装docker compose 我们可以从 Github 上下载它的二进制包来使用&#xff0c;最新发行的版本地址&#xff1a; https://github.com/docker/compose/releases sudo curl -L "https://github.com/docker/compose/releases/download/v2.6.0/docker-compose-$(uname -s)…

「GO基础」在Windows上安装Go编译器并配置Golang开发环境

文章目录 1、安装Go语言编译程序1.1、下载GoLang编译器1.2、安装GoLang编译器 2、配置Golang IDE运行环境2.1、配置GO编译器2.1.1、GOROOT 概述2.1.2、GOROOT 作用2.1.2、配置 GOROOT 2.2、配置GO依赖管理2.2.1、Module管理依赖2.2.2、GOPATH 管理依赖 2.3、运行GO程序2.3.1、创…

什么是PE 格式

2024年4月19日&#xff0c;周五下午 PE&#xff08;Portable Executable&#xff09;格式是一种 Windows 操作系统中常见的可执行文件和对象文件格式。它是微软公司为 Windows NT 操作系统引入的一种文件格式&#xff0c;用于存储可执行程序、动态链接库&#xff08;DLL&#x…

全栈外包接单/远程工作(TS, React, Vue, Java, 移动端)

个人介绍 我毕业于中国某一本院校计算机专业&#xff0c;曾在北京大型软件公司从事Java开发多年&#xff0c;主要服务于全国各大头部985/211院校。后来为扩宽职业路径&#xff0c;转向了Ts全栈&#xff0c;现专注于远程外包接单工作&#xff0c;致力于打造一个能为客户带来优质…

binary tree Leetcode 二叉树算法题

144.二叉树的前序遍历 前序遍历是&#xff1a;根-左-右 所以记录序列的的时候放在最前面 递归 class Solution {List<Integer> ans new ArrayList<>();public List<Integer> preorderTraversal(TreeNode root) {if(root null) return ans;ans.add(root…