理解并手写 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 ...
随机推荐
- asp.net core 中的各种路径
1.获取完整网址URL 方法一:先引用"using Microsoft.AspNetCore.Http.Extensions;",然后直接用"Request.GetDis ...
- Android 存储到SD卡,获取SD的大小及可用空间
使用Sdcard注意事项: 1.权限问题: <uses-permission android:name="android.permission.WRIT ...
- Java 内置注解简单理解
感谢原文作者:yejg1212 原文链接 https://www.cnblogs.com/yejg1212/p/3187362.html https://www.cnblogs.com/yejg121 ...
- Git Push 免输 用户名和密码
前言 在大家使用github的过程中,一定会碰到这样一种情况,就是每次要push 和pull时总是要输入github的账号和密码,这样不仅浪费了大量的时间且降低了工作效率.在此背景下,本文在网上找了两 ...
- K8s多节点部署+负载均衡+keepalived ——囊萤映雪
K8s多节点部署+负载均衡+keepalived --囊萤映雪 1.多节点master2 部署 2.负载均衡部署+keepalived 1.多节点master2部署: #从master01节点上拷贝证 ...
- 还在做廉价的劳动力?部署PXE实现Kickstart无人值守安装
搭建PXE实现Kickstart无人值守安装 1.搭建PXE远程安装服务器 2.实现kicstart无人值守安装 1.PXE介绍及搭载: PXE是有Intel公司开发的网络引导技术,工作在Client ...
- 枚举和注解@override、@Deprecated、@SuppressWarnings
一.枚举 简介: 1)枚举对应英文(enumeration,简写 enum) 2)枚举是一组常量的集合. 3)可以这里理解:枚举属于一种特殊的类,里面只包含一组有限的特定的对象. 实现方式: 1.自定 ...
- Solution -「CF 793G」Oleg and Chess
\(\mathcal{Description}\) Link. 给一个 \(n\times n\) 的棋盘,其中 \(q\) 个互不重叠的子矩阵被禁止放棋.问最多能放多少个互不能攻击的车. ...
- linux大工程 - 我要一个属于自己的回收站
我要开始装13了 'rm -rf 是一个很"粗鲁"的命令,就像windows的shift+delete,删除的文件是无法找回的(当然,除了数据恢复软件,但是很麻烦,很费时)' '为 ...
- EasyX库简单中文手册
EasyX库简单中文手册 作者: 时间: 2021/2/2 第一个例程 #include <graphics.h> // 图像相关库 #include <conio.h> // ...