如何手动实现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 相关文章推荐
不错的一个日期输入 动态
Nov 06 Javascript
按下Enter焦点移至下一个控件的实现js代码
Dec 11 Javascript
jquery Ajax 实现加载数据前动画效果的示例代码
Feb 07 Javascript
bootstrap data与jquery .data
Jul 07 Javascript
JS自定义对象实现Java中Map对象功能的方法
Jan 20 Javascript
jquery实现键盘左右翻页特效
Apr 30 Javascript
原生js实现的贪吃蛇网页版游戏完整实例
May 18 Javascript
jQuery实现限制文本框的输入长度
Jan 11 Javascript
微信小程序-滚动消息通知的实例代码
Aug 03 Javascript
jquery ajax异步提交表单数据的方法
Oct 27 jQuery
使用imba.io框架得到比 vue 快50倍的性能基准
Jun 17 Javascript
微信小程序学习之自定义滚动弹窗
Dec 20 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
删除无限分类并同时删除它下面的所有子分类的方法
2010/08/08 PHP
php中get_cfg_var()和ini_get()的用法及区别
2015/03/04 PHP
PHPExcel简单读取excel文件示例
2016/05/26 PHP
js 获取class的元素的方法 以及创建方法getElementsByClassName
2013/03/11 Javascript
JS中setTimeout()的用法详解
2013/04/14 Javascript
jQuery $命名冲突解决方案汇总
2014/11/13 Javascript
angularJS提交表单(form)
2015/02/09 Javascript
JS原型、原型链深入理解
2016/02/27 Javascript
jQuery使用模式窗口实现在主页面和子页面中互相传值的方法
2016/03/01 Javascript
新手学习前端之js模仿淘宝主页网站
2016/10/31 Javascript
vue-自定义组件传值的实例讲解
2018/09/18 Javascript
node.js实现上传文件功能
2019/07/15 Javascript
js 根据对象数组中的属性进行排序实现代码
2019/09/12 Javascript
Javascript中的this,bind和that使用实例
2019/12/05 Javascript
JS自定义对象创建与简单使用方法示例
2020/01/15 Javascript
node.js通过Sequelize 连接MySQL的方法
2020/12/28 Javascript
Python中实现常量(Const)功能
2015/01/28 Python
Python3实现将文件树中所有文件和子目录归档到tar压缩文件的方法
2015/05/22 Python
Python使用turtule画五角星的方法
2015/07/09 Python
Python通过matplotlib画双层饼图及环形图简单示例
2017/12/15 Python
python读取Excel实例详解
2018/08/17 Python
python实现图片筛选程序
2018/10/24 Python
通过pykafka接收Kafka消息队列的方法
2018/12/27 Python
pandas factorize实现将字符串特征转化为数字特征
2019/12/19 Python
Python和Sublime整合过程图示
2019/12/25 Python
python实现简单学生信息管理系统
2020/04/09 Python
python分布式爬虫中消息队列知识点详解
2020/11/26 Python
input元素的url类型和email类型简介
2012/07/11 HTML / CSS
类的返射机制中的包及核心类
2016/09/12 面试题
2013年学期结束动员演讲稿
2014/01/07 职场文书
幼儿园教师奖惩制度
2014/02/01 职场文书
公益广告标语
2014/06/19 职场文书
工厂仓管员岗位职责
2015/04/01 职场文书
管理者日常工作必备:22条企业管理流程模板!
2019/07/12 职场文书
关于mysql中string和number的转换问题
2022/06/14 MySQL
Spring Boot实现文件上传下载
2022/08/14 Java/Android