如何手动实现es5中的bind方法详解


Posted in Javascript onDecember 07, 2018

前言

this的指向在javascript中一直是个谜一样的存在,但是很多地方又会用到this,所以理解和使用this非常重要,关于this的理解这篇文章不做介绍,因为这篇的目的是改变this的指向。

改变this的指向有三种方法,call,apply,bind。下面先介绍下这三种方法,话不多说了,来一起看看详细的介绍吧

改变this指向

call

var a = {
 name:"aaa",
 say(type){
  console.log(type,this.name);
 }
}
a.say("at");//at aaa
var tn = {name:"ttt"};
a.say.call(tn,"tt")//tt ttt

可以看到通过call,say方法中的this指向了tn,传参的方式的列举

apply

var a = {
 name:"aaa",
 say(type){
  console.log(type,this.name);
 }
}
a.say("at");
var tn = {name:"ttt"};
a.say.apply(tn,["tt"])

可以看到通过apply,say方法中的this指向了tn,传参的方式是数组

bind

bind也能改变this的指向,不过和call,apply不同的地方在于,bind只改变this,不会指向函数

var a = {
 name:"aaa",
 say(type){
  console.log(type,this.name);
 }
}
var tn = {name:"ttt"};
var b = a.say.bind(tn);
b();//ttt

bind 改变this,也是能够继承原型链的,看下下面的代码

var to = {name:"to",color:"red"};
function Animal(){
 console.log(`name:${this.name}...color:${this.color}`);
}
Animal.prototype.say = function(){
 console.log(`say..name:${this.name}...color:${this.color}`);
}
var Cat = Animal.bind(to);
Cat();//name:to...color:red
var cat = new Cat();// name:undefined...color:undefined
cat.say();//say..name:undefined...color:undefined

因为cat是Cat的实例,Cat是改变了this的Animal,所以cat也是Animal的实例,但是this是指向cat的,所以this.name是undefined

实现bind

Function.prototype.bind = function(obj){
 const args = Array.prototype.slice.call(arguments,1);//保留bind时的参数
 const that = this;
 const bound = function(){
  const inArgs = Array.prototype.slice.call(arguments);//执行bind的函数时的参数
  const newArgs = args.concat(inArgs);//组装参数
  that.apply(obj,newArgs);//执行bind的函数
 }
 //继承prototype--寄生组合式继承
 function F(){};
 F.prototype = that.prototype;
 bound.prototype = new F();
 return bound;
}

然后执行上面的代码

Cat();//name:to...color:red
var cat = new Cat();//name:to...color:red
cat.say();//say..name:undefined...color:undefined

不过第二行和原生的bind还是有点区别的,这里还是记住了之前的bind的对象,原生的不知道为啥是undefined

面试题

实现es5中的bind方法,使得下面的代码输出success

function Animal(name,color){
 this.name = name;
 this.color = color;
}
Animal.prototype.say = function(){
 return `i am a ${this.color} ${this.name}`
}
const Cat = Animal.bind(null,"cat");
const cat = new Cat("white");
if(cat.say() === 'i am a white cat' && cat instanceof Cat && cat instanceof Animal){
 console.log("success")
}

加上上面的bind实现,咦??没有出现success??为什么?

分析一下代码,bind的第一个参数是null??null的时候应该默认为this,修改代码如下

Function.prototype.bind = function(obj){
 const args = Array.prototype.slice.call(arguments,1);//保留bind时的参数
 const that = this;
 const bound = function(){
  const inArgs = Array.prototype.slice.call(arguments);//执行bind的函数时的参数
  const newArgs = args.concat(inArgs);//组装参数
  const bo = obj || this;
  that.apply(bo,newArgs);//执行bind的函数
 }
 //继承prototype--寄生组合式继承
 function F(){};
 F.prototype = that.prototype;
 bound.prototype = new F();
 return bound;
}

输出success

完美~~~

撒花~~~

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
JavaScript开发时的五个注意事项
Dec 08 Javascript
JS获取父节点方法
Aug 20 Javascript
jquery下异步提交表单 异步跨域提交表单
Nov 17 Javascript
javascript匿名函数实例分析
Nov 18 Javascript
node.js中的events.emitter.removeListener方法使用说明
Dec 10 Javascript
JavaScript模块规范之AMD规范和CMD规范
Oct 27 Javascript
javascript创建对象、对象继承的实用方式详解
Mar 08 Javascript
15个值得开发人员关注的jQuery开发技巧和心得总结【经典收藏】
May 25 Javascript
vue构建单页面应用实战
Apr 10 Javascript
Vue 进入/离开动画效果
Dec 26 Javascript
vue 录制视频并压缩视频文件的方法
Jul 27 Javascript
JS数组方法some、every和find的使用详情
Oct 05 Javascript
JavaScript时间与时间戳的转换操作实例分析
Dec 07 #Javascript
vue+SSM实现验证码功能
Dec 07 #Javascript
详解如何为你的angular app构建一个第三方库
Dec 07 #Javascript
JS实现随机生成10个手机号的方法示例
Dec 07 #Javascript
angular学习之动态创建表单的方法
Dec 07 #Javascript
JavaScript栈和队列相关操作与实现方法详解
Dec 07 #Javascript
微信小程序实现两边小中间大的轮播效果的示例代码
Dec 07 #Javascript
You might like
使用PHP数组实现无限分类,不使用数据库,不使用递归.
2006/12/09 PHP
解析在PHP中使用全局变量的几种方法
2013/06/24 PHP
thinkPHP5.0框架模块设计详解
2017/03/18 PHP
PHP的PDO错误与错误处理
2019/01/27 PHP
javascript如何创建表格(javascript绘制表格的二种方法)
2013/12/10 Javascript
document.write的几点使用心得
2014/05/14 Javascript
在Node.js中实现文件复制的方法和实例
2014/06/05 Javascript
百度判断手机终端并自动跳转js代码及使用实例
2014/06/11 Javascript
HTML+CSS+JS实现完美兼容各大浏览器的TABLE固定列
2015/04/26 Javascript
jQuery实现自动调整字体大小的方法
2015/06/15 Javascript
浅谈vue方法内的方法使用this的问题
2018/09/15 Javascript
在layui中select更改后生效的方法
2019/09/05 Javascript
JS面向对象编程基础篇(一) 对象和构造函数实例详解
2020/03/03 Javascript
JS数组及对象遍历方法代码汇总
2020/06/16 Javascript
vant中的toast层级改变操作
2020/11/04 Javascript
[07:52]2014DOTA2 TI逗比武士游V社解说背后的故事
2014/07/10 DOTA
[01:20]DOTA2更新全新英雄 天涯墨客现已加入游戏
2018/08/25 DOTA
[52:06]完美世界DOTA2联赛决赛日 Inki vs LBZS 第一场 11.08
2020/11/10 DOTA
Python安装使用命令行交互模块pexpect的基础教程
2016/05/12 Python
基于Python实现的ID3决策树功能示例
2018/01/02 Python
Python中摘要算法MD5,SHA1简介及应用实例代码
2018/01/09 Python
高效使用Python字典的清单
2018/04/04 Python
Python查找文件中包含中文的行方法
2018/12/19 Python
完美解决Python matplotlib绘图时汉字显示不正常的问题
2019/01/29 Python
python实现动态创建类的方法分析
2019/06/25 Python
Python列表的切片实例讲解
2019/08/20 Python
Python填充任意颜色,不同算法时间差异分析说明
2020/05/16 Python
python numpy库np.percentile用法说明
2020/06/08 Python
浅析Python中字符串的intern机制
2020/10/03 Python
Python通过getattr函数获取对象的属性值
2020/10/16 Python
python 实现逻辑回归
2020/12/30 Python
CSS3新属性transition-property transform box-shadow实例学习
2013/06/06 HTML / CSS
模特职业生涯规划范文
2014/02/26 职场文书
感恩老师主题班会
2015/08/12 职场文书
CentOS7安装MySQL8的超级详细教程(无坑!)
2022/06/10 Servers
win10截图快捷键win+shift+s没有反应无法截图怎么解决?
2022/08/14 数码科技