JS基础面试题之手写bind

JS基础面试题之手写bind

  • 手写bind
    • 返回函数的模拟实现
    • 传参的模拟实现
    • 构造函数效果的模拟实现
    • 构造函数效果的优化实现
    • 最终版

手写bind

bind()方法会创建一个新的函数。当这个函数被调用时,bind()的第一个参数将作为它的运行时的this,之后的一序列参数将会在传递的实参前传入作为它的参数。

由此,我们可以首先得出bind函数的两个特点:

  • 返回一个函数。
  • 可以传入参数。

返回函数的模拟实现

var foo = {
	value:1
};
function bar(){
	console.log(this.value);
}
//返回一个函数
var bindFoo = bar.bind(foo);

bindFoo();//1

关于指定this的指向,我们可以使用call或者apply实现。

//第一版
Function.prototype.bind2 = function (context){
	var self = this;
	//考虑到绑定函数可能是有返回值的,加上return
	return function(){
		return self.apply(context);
	}
}

传参的模拟实现

接下来,关于参数的传递:

var foo = {
	value:1
};
function bar(name,age){
	console.log(this.value);
	console.log(name);
	console.log(age);
}
var bindFoo = bar.bind(foo,'kin');
bindFoo('18');
//1
//kin
//18

当需要传name和age两个参数时,可以在bind的时候,只传一个name,在执行返回的函数的时候,再传另一个参数age。
这里如果不适用rest,使用arguments进行处理:

//第二版
Function.prototype.bind2 = function(context){
	var self = this;
	//获取bind2函数从第二个参数到最后一个参数
	var args = Array.prototype.slice.call(arguments,1);
	return function(){
		//这个时候的arguments是指bind返回的函数传入的参数
		var bindArgs = Array.prototype.slice.call(arguments);
		return self.apply(context,args.concat(bindArgs));
	}
}

构造函数效果的模拟实现

bind还有一个特点,就是

一个绑定函数也能使用new操作符创建对象:这种行为就像把原函数当成构造器。提供的this值被忽略,同时调用时的参数被提供给模拟函数。

也就是说当bind返回的函数作为构造函数的时候,bind指定的this值会失效,但传入的参数依然生效。举个例子:

var value = 2;
var foo = {
	value:1
};
function bar(name,age){
	this.habit = 'shopping';
	console.log(this.value,name,age);
}
bar.prototype.friend = 'ming';
var bindFoo = bar.bind(foo,'hong');
var obj = new bindFoo('18');
//undefined
//hong
//18
console.log(obj.habit);
console.log(obj.friend);
//shopping
//ming

尽管在全局和foo中都声明了value值,最后依然反悔了undefined,说明绑定的this失效了。

后文中new的模拟实现,就会知道这个时候的this已经指向了obj。

构造函数效果的优化实现

但是在这个写法中,我们直接将fBound.prototype = this.prototype,我们直接修改fBound.prototype的时候,也会直接修改绑定函数的prototype。这个时候,我们可以通过一个空函数来进行中转:

//第四版
Function.prototype.bind2 = function(context){
	var self = this;
	var args = Array.prototype.slice.call(arguments,1);
	var fNOP = function(){};
	var fBound = function(){
		var bindArgs = Array.prototype.slice.call(arguments);
		return self.apply(this instanceof fNOP ? this : context,args.concat(bindArgs));
	}
	fNOP.prototype = this.prototype;
	fBound.prototype = new fNOP();
	return fBound;
}

最终版

调用bind的不是函数时,提示错误:

if(typeof this !== "function"){
	throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}

最终代码为:

Function.prototype.bind2 = function (context){
	if(typeof this !== "function"){
		throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
	}
	var self = this;
	var args = Array.prototype.slice.call(arguments,1);
	var fNOP = function(){};
	var fBound = function(){
		var bindArgs = Array.prototype.slice.call(arguments);
		return self.apply(this instanceof fNOP?this : context,args.concat(bindArgs));
	}
	fNOP.prototype = this.prototype;
	fBound.prototype = new fNOP();
	return fBound;
}

最简化版:

Function.prototype.myBind = function(context){
//判断是否是undefined和null
	if(typeof context === 'undefined' || context === null){
		context = window;
	}
	self = this;
	return function(...args){
		return self.apply(context,args);
	}
}

好啦!说实话,写到这里我也还有点蒙,我先消化一下~
欢迎大家留言讨论!一起消化!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/227904.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VSCode SSH登录服务器 提示XHR failed

设置->搜索“代理” 把图中的√去掉 重启 即可

【Linux】diff命令使用

diff命令 是一个用于比较两个文件或目录之间差异的命令。它可以显示两个文件之间的行级别差异,并以易于阅读的格式输出结果。 著者 由保罗艾格特、迈克海特尔、大卫海耶斯、理查德史泰尔曼和Len Tower撰写。 diff命令 -Linux手册页 语法 diff [选项] [文件1]…

Python-滑雪大冒险【附源码】

滑雪大冒险 《滑雪大冒险》是一款充满趣味性和挑战性的休闲竞技游戏,在游戏中,玩家将扮演一位勇敢的滑雪者,在雪山上展示他们的滑雪技巧,游戏采用2D图形界面,以第三人称视角呈现 运行效果:用方向键及方向键…

高端的露营装备网站搭建的作用是什么

近些年发展促进了露营热潮,周边游也多了起来,城市中高频工作带来的烦恼使得很多人想要放松,露营无疑是接触大自然很好的方式,而选择好的露营装备同样重要,还包括门店经营者,选择好的品牌合作也能带来很多生…

解决谷粒学苑新建父工程,pom 依赖大量飘红

解决谷粒学苑新建父工程&#xff0c;pom 依赖大量飘红 找到dependencyManagement标签&#xff0c;注释掉该标签&#xff08;同时注释掉对应的</dependencyManagement>标签&#xff09;。 重新加载 maven 项目 经过上面两个步骤&#xff0c;应该大部分依赖都已经引入。&a…

第21章总结 网络通信

21.1 网络程序设计基础 网络程序设计编写的是与其他计算机进行通信的程序。Java已经将网络程序所需要的元素封装成不同的类&#xff0c;用户只要创建这些类的对象&#xff0c;使用相应的方法&#xff0c;即使不具备有关的网络知识&#xff0c;也可以编写出高质量的网络通信程序…

二氧化碳注气开采石油中的无线传输解决方案

一、应用背景 在传统的石油开采过程中&#xff0c;只能采收到地下原油储层中约30%至40%的石油。二氧化碳强化石油开采技术是一种利用二氧化碳来提高石油采收率的技术。将工业尾气中的二氧化碳被捕集起来&#xff0c;注入油田地下油层&#xff0c;把原油"驱赶”出来&#…

经验分享|MySQL分区实战(RANGE)

概述 分区概述 在 MySQL 中&#xff0c; InnoDB存储引擎长期以来一直支持表空间的概念。在 MySQL 8.0 中&#xff0c;同一个分区表的所有分区必须使用相同的存储引擎。但是&#xff0c;也可以为同一 MySQL 服务器甚至同一数据库中的不同分区表使用不同的存储引擎。 通俗地讲…

洞察 丨 中国智能电动车发展趋势分析

中国弯道超车的愿景&#xff1a;多年的用市场换技术的方针&#xff0c;并没有在传统汽油车里完美实现&#xff0c;然而电动车的三电技术&#xff08;电池&#xff0c;电控&#xff0c;电驱&#xff09;完美避开了传统汽车有的发动机&#xff0c;变速箱&#xff0c;发动机控制器…

java集合之HashMap详解

HashMap详解 介绍 HashMap是在项目中使用的最多的Map&#xff0c;实现了Map接口&#xff0c;继承AbstractMap。基于哈希表的Map接口实现&#xff0c;不包含重复的键&#xff0c;一个键对应一个值&#xff0c;在HashMap存储的时候会将key、value作为一个整体Entry进行存储。 Has…

Codeforces Round 911 (Div. 2)补题

Cover in Water 题目大意&#xff1a;我们有一排房间&#xff0c;一些房间是空的&#xff0c;一些房间是阻塞的&#xff0c;现在需要将所有的空房间都填满水&#xff0c;我们能做的只有两个操作&#xff1a;1.往一个空房间内放入水&#xff1b;2.将一个房间中的水取出放入另一…

UEM 在企业 IT 管理数字化转型有什么帮助

近年大多数公司都在努力实现数字化转型&#xff0c;业务应用程序正在迁移到云端&#xff0c;日常 IT 运营正变得更加面向移动化&#xff0c;高管们使用各种设备。员工不仅使用公司提供的台式机&#xff0c;还经常使用公司拥有的、个人启用的&#xff08;COPE&#xff09;笔记本…

基于springboot实现的宠物医院管理系统

一、系统架构 前端&#xff1a;html | jquery | echarts | css 后端&#xff1a;springboot | thymeleaf | mybatis 环境&#xff1a;jdk1.8 | mysql | maven 二、代码及数据库 三、功能介绍 01. 登录页 02. 系统设置-用户管理 03. 系统设置-页面管理 04. 系统设置-角…

接口测试方向

一、Http接口测试 前面我们已经有了接口文档&#xff0c;那么我们就要根据接口文档来拼接参数调用接口&#xff0c;那么怎么调用呢&#xff1f; 1、接口请求报文拼接---传参方式 1&#xff09;key-value形式 这种是最简单的一种&#xff0c;问号前面是请求url&#xff0c;后…

Liunx系统使用超详细(四)~文件/文本相关命令2

承接文章Liunx系统使用超详细(四)~文件/文本相关命令1http://t.csdnimg.cn/f7G6S 目录 一、awk命令(三剑客之一) 1.1工作原理 1.2工作流程 1.3语法格式 1.3.1格式注释&#xff1a; 1.3.2模式&#xff08;pattern&#xff09;的类型&#xff1a; 1.3.3动作&#xff08;ac…

【动态规划系列】环形子数组的和-918

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Java面试题(每天10题)-------连载(45)

Dubbo篇 1、Dubbo的服务调用流程 2、Dubbo支持那种协议&#xff0c;每种协议的应用场景&#xff0c;优缺点&#xff1f; dubbo&#xff1a; 单一长连接和 NIO 异步通讯&#xff0c;适合大并发小数据量的服务调用&#xff0c;以及消费者远大于提供者。传输协议 TCP&#xff0c;…

题目:纪念品分组(蓝桥OJ 532)

题目描述&#xff1a; 解题思路&#xff1a; 本题使用贪心思想&#xff0c;先排序&#xff0c;则最大和最小就分别位于头部和尾部。如果最大和最小之和不超过容量&#xff0c;就取两个放到一个&#xff08;ans&#xff09;并去除&#xff1b;如果最大和最小之和超过容量&#x…

域名与SSL证书

域名是互联网上的地址标识符&#xff0c;它通过DNS&#xff08;Domain Name System&#xff09;将易于记忆的人类可读的网址转换为计算机可以理解的IP地址。当用户在浏览器中输入一个网址时&#xff0c;实际上是通过DNS解析到对应的服务器IP地址&#xff0c;从而访问到相应的网…

C //例10.5 有一个磁盘文件,内有一些信息。要求第1次将它的内容显示在屏幕上,第2次把它复制到另一文件上。

C程序设计 &#xff08;第四版&#xff09; 谭浩强 例10.5 例10.5 有一个磁盘文件&#xff0c;内有一些信息。要求第1次将它的内容显示在屏幕上&#xff0c;第2次把它复制到另一文件上。 IDE工具&#xff1a;VS2010 Note: 使用不同的IDE工具可能有部分差异。 代码块 方法&a…