理解并手写 bind() 函数
有了对call()、apply()的前提分析,相信bind()我们也可以手到擒来。
参考前两篇:'对call()函数的分析' 和 '对apply()函数的分析',我们可以先得到以下代码:
Function.prototype.myBind = function(obj){
// 判断调用对象是否为函数
if(typeof this !== 'function'){
console.error('type error!')
}
// 判断绑定的对象
obj = obj || window;
}
bind()函数与call()函数参数的格式相同,不同的是bind()返回的是一个函数。
Function.prototype.myBind = function(obj){
if(typeof this !== 'function'){
console.error('type error!')
}
obj = obj || window;
// 获取正确参数
let args = [...arguments].slice(1);
// 返回函数
return function Fn(){};
}
使用bind()函数来对this进行绑定,可以之间在内部使用 apply() 。
Function.prototype.myBind = function(obj){
if(typeof this !== 'function'){
console.error('type error!')
}
obj = obj || window;
let args = [...arguments].slice(1);
return function Fn(){
// 直接使用apply()
return this.apply();
};
}
这个时候会发现,我们绑定的this是window,而不是我们想要的’this‘环境,可以使用that作为中间量。
Function.prototype.myBind = function(obj){
if(typeof this !== 'function'){
console.error('type error!')
}
obj = obj || window;
// 在这里借助that
that = this;
let args = [...arguments].slice(1);
return function Fn(){
return that.apply();
};
}
然后我们需要考虑apply()中传递的参数,这里我们使用数组的concat()方法,得到apply中传递的数组。
Function.prototype.myBind = function(obj){
if(typeof this !== 'function'){
console.error('type error!')
}
obj = obj || window;
that = this;
let args = [...arguments].slice(1);
return function Fn(){
// 传递两个参数(绑定对象,数组)
return that.apply(obj,args.concat(...arguments));
};
}
最后需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this 给 apply 调用,其余情况都传入指定的上下文对象。
Function.prototype.myBind = function(obj){
if(typeof this !== 'function'){
console.error('type error!')
}
obj = obj || window;
that = this;
let args = [...arguments].slice(1);
return function Fn(){
// 根据调用方式,传入不同绑定值
return that.apply(
this instanceof Fn ? this : obj,
args.concat(...arguments));
};
}
最后通过一个例子,来验证是否达到bind()的功能要求。
Function.prototype.myBind = function(obj){
if(typeof this !== 'function'){
console.error('type error!')
}
obj = obj || window;
that = this;
let args = [...arguments].slice(1);
return function Fn(){
return that.apply(
this instanceof Fn ? this : obj,
args.concat(...arguments)
);
}
}
let dog = {
name: '狗',
eat(food1, food2) {
console.log(this.name + '爱吃' + food1 + food2);
}
}
let cat = {
name: '猫',
}
dog.eat.bind(cat, '鱼', '肉')(); // 猫爱吃鱼肉
dog.eat.mybind(cat, '鱼', '肉')(); // 猫爱吃鱼肉
理解并手写 bind() 函数的更多相关文章
- 理解并手写 call() 函数
手写自己的call,我们要先通过call的使用,了解都需要完成些什么功能? call()进行了调用,是个方法,已知是建立在原型上的,使用了多个参数(绑定的对象+传递的参数). 我们把手写的函数起名为m ...
- 手写bind函数
实现bind函数 参考MDN提供的Polyfill方案 Function.prototype.myBind = function(context){ //这里对调用者做一个判断,如果不是函数类型,直接 ...
- 理解并手写 apply() 函数
apply()函数,在功能上类似于call(),只是传递参数的格式有所不同. dog.eat.call(cat, '鱼', '肉'); dog.eat.apply(cat, ['鱼', '肉']); ...
- 前端面试题整理——手写bind函数
var arr = [1,2,3,4,5] console.log(arr.slice(1,4)) console.log(arr) Function.prototype.bind1 = functi ...
- WPF启动流程-自己手写Main函数
WPF一般默认提供一个MainWindow窗体,并在App.Xaml中使用StartupUri标记启动该窗体.以下通过手写实现WPF的启动. 首先先介绍一下VS默认提供的App.Xaml的结构,如下图 ...
- 优雅手撕bind函数(面试官常问)
优雅手撕bind函数 前言: 为什么面试官总爱让实现一个bind函数? 他想从bind中知道些什么? 一个小小的bind里面内有玄机? 今天来刨析一下实现一个bind要懂多少相关知识点,也方便我们将零 ...
- python 精华梳理(已理解并手写)--全是干货--已结
基础部分 map,reduce,filter,sort,推导式,匿名函数lambda , 协程,异步io,上下文管理 自定义字符串转数字方法一不使用reduce import re def str2i ...
- C++之手写strlen函数
代码: int strlen(const char *str){ assert(str!=NULL); intlen=; while((*str++)!='\0') len++; return len ...
- js面试题之手写节流函数和防抖函数
函数节流:不断触发一个函数后,执行第一次,只有大于设定的执行周期后才会执行第二次 /* 节流函数:fn:要被节流的函数,delay:规定的时间 */ function throttle(fn,dela ...
随机推荐
- RPC原理及RPC实例分析(转)
出处:https://my.oschina.net/hosee/blog/711632 在学校期间大家都写过不少程序,比如写个hello world服务类,然后本地调用下,如下所示.这些程序的特点是服 ...
- Emoji与unicode特殊字符的处理
遇到了一个很让人纠结的问题:emoji表情在使用的过程中,会莫名其妙的消失,或者变成乱码,同时数据库用utf8mb4来存储,但是也出现了问题,冷备过后,导入进库的时候,变成了不可见字符,神奇的消失了! ...
- HTML-iframe标签
碎碎:这两天在实践中,用到了 iframe,之前对其不甚了解,了解之中遇到好多奇葩问题,今天记录下这两天遇到的相关的内容. 嵌入的 iframe 页面的边框 嵌入的 iframe 页面的背景 嵌入的 ...
- js 对象的深克隆
前端笔试或者面试的时候,很喜欢问的一个问题就是对象的深度克隆,或者说是对象的深度复制.其实这个问题说容易很容易,但是要说全面也挺不易. 要弄明白对象的克隆,首先要明白js中对象的组成.在js中一切实例 ...
- 在zabbix中实现发送带有图片的邮件和微信告警
1 python实现在4.2版本zabbix发送带有图片的报警邮件 我们通常收到的报警,都是文字,是把动作中的消息内容当成了正文参数传给脚本,然后邮件或者微信进行接收,往往只能看到当前值,无法直观的获 ...
- nodejs串行无关联
var async = require('async'); //串行无关联async.series({ one:function(cb) { setTimeout(function(){ consol ...
- springboot自动扫描添加的BeanDefinition源码解析
1. springboot启动过程中,首先会收集需要加载的bean的定义,作为BeanDefinition对象,添加到BeanFactory中去. 由于BeanFactory中只有getBean之类获 ...
- Solution -「洛谷 P4320」道路相遇
\(\mathcal{Description}\) Link. 给定一个 \(n\) 个点 \(m\) 条边的连通无向图,并给出 \(q\) 个点对 \((u,v)\),询问 \(u\) 到 ...
- MySQL架构原理之运行机制
所谓运行机制即MySQL内部就如生产车间如何进行生产的.如下图: 1.建立连接,通过客户端/服务器通信协议与MySQL建立连接.MySQL客户端与服务端的通信方式是"半双工".对于 ...
- 超简单集成华为 HMS MLKit 机器学习服务:银行卡识别 SDK,一键实现银行卡绑定
前言 小编前面几期文章分别给大家介绍了使用 HMS ML Kit SDK 实现微笑抓拍.证件照 DIY.拍照翻译的功能开发(链接见文章末尾),本次小编给大家带来的是使用 HMS 机器学习服务(ML K ...