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

server/2024/12/22 13:53:38/

函数中的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/server/3121.html

相关文章

node項目的开发

01 创建package.json文件: npm init 创建一个package.json 项目描述的文件。package name : 包名version:版本description:项目描述entry point:入口文件 默认index.jstset command:测试命名git reposito…

【技巧】win11 删除网络中心中多余的以太网信息

因为网络环境的变化,系统在识别网络时会出现“以太网1”,“以太网2”,“以太网3”的情况。虽然不影响使用,但是对于一些强迫症来说很不友好,通过以下方式删除: 1、Win R 打开,运行,…

【Tars-go】腾讯微服务框架学习使用02-- http 服务

2 http 服务 官方文档说http这里是在net/http原生包的基础上做了修改。 官方给的案例: package mainimport ("net/http""github.com/TarsCloud/TarsGo/tars" )func main() {mux : &tars.TarsHttpMux{}mux.HandleFunc("/", fun…

如何实现文件上传到阿里云OSS!!!(结合上传pdf使用)

一、开通阿里云OSS对象存储服务 对象存储 OSS_云存储服务_企业数据管理_存储-阿里云阿里云对象存储 OSS 是一款海量、安全、低成本、高可靠的云存储服务,提供 99.995 % 的服务可用性和多种存储类型,适用于数据湖存储,数据迁移,企…

盲人盲杖:科技革新,助力视障人士独立出行

在我们的社会中,盲人朋友们以其坚韧的精神风貌,生动诠释着生活的多样与可能。然而,当我们聚焦于他们的日常出行,那些普通人视为寻常的街道、路口,却成为他们必须面对的严峻挑战。如何切实提升盲人盲杖的功能&#xff0…

一个极简鲁棒的C语言的动态数据类型扩展,取代诸如C++/Rust那些愚蠢的东西

项目地址:https://github.com/shajunxing/banana-cvar 我用过很多高级语言,喜欢简单的东西,讨厌C,一直在想C语言能不能用最简洁的手段扩充动态语言特性,并且支持垃圾回收呢?偶然迸发出灵感,网上…

数字接龙(蓝桥杯)

文章目录 数字接龙【问题描述】解题思路DFS 数字接龙 【问题描述】 小蓝最近迷上了一款名为《数字接龙》的迷宫游戏,游戏在一个大小为N N 的格子棋盘上展开,其中每一个格子处都有着一个 0 . . . K − 1 之间的整数。游戏规则如下: 从左上…

Maven实战—搭建微服务 Maven 工程架构

需求案例:搭建一个电商平台项目,该平台包括用户服务、订单服务、通用工具模块等。 项目架构: 用户服务:负责处理用户相关的逻辑,例如用户信息的管理、用户注册、登录等。订单服务:负责处理订单相关的逻辑…