如何手动实现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 相关文章推荐
Locate a File Using a File Open Dialog Box
Jun 18 Javascript
关于jquery append() html时的小问题的解决方法
Dec 16 Javascript
Javascript 加载和执行-性能提高篇
Dec 28 Javascript
js左侧三级菜单导航实例代码
Sep 13 Javascript
javascript 判断整数方法分享
Dec 16 Javascript
原生javascript获取元素样式
Dec 31 Javascript
javascript实现可全选、反选及删除表格的方法
May 15 Javascript
JS中常用的输出方式(五种)
Jun 12 Javascript
jQuery模仿单选按钮选中效果
Jun 24 Javascript
js学习总结_选项卡封装(实例讲解)
Jul 13 Javascript
JavaScript实现开关等效果
Sep 08 Javascript
ES6如何用一句代码实现函数的柯里化
Jan 18 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获取当前网址url并替换参数或网址的方法
2010/06/06 PHP
Zend Framework教程之Autoloading用法详解
2016/03/08 PHP
php使用filter_var函数判断邮箱,url,ip格式示例
2019/07/06 PHP
制作特殊字的脚本
2006/06/26 Javascript
如何实现动态删除javascript函数
2007/05/27 Javascript
用js实现的页面关键字密度查询代码
2007/12/27 Javascript
关于B/S判断浏览器断开的问题讨论
2008/10/29 Javascript
javascript处理表单示例(javascript提交表单)
2014/04/28 Javascript
使用jquery菜单插件HoverTree仿京东无限级菜单
2014/12/18 Javascript
js完美实现@提到好友特效(兼容各大浏览器)
2015/03/16 Javascript
详解js图片轮播效果实现原理
2015/12/17 Javascript
总结Javascript中的隐式类型转换
2016/08/24 Javascript
VUE2.0+ElementUI2.0表格el-table实现表头扩展el-tooltip
2018/11/30 Javascript
如何手写简易的 Vue Router
2020/10/10 Javascript
[14:51]DOTA2 HEROS教学视频教你分分钟做大人-卓尔游侠
2014/06/13 DOTA
[45:16]完美世界DOTA2联赛PWL S3 Magma vs Phoenix 第一场 12.12
2020/12/16 DOTA
多版本Python共存的配置方法
2017/05/22 Python
python numpy元素的区间查找方法
2018/11/14 Python
python实现人工蜂群算法
2020/09/18 Python
Willer台湾:日本高速巴士/夜行巴士预约
2017/07/09 全球购物
荷兰街头时尚之家:Funkie House
2019/03/18 全球购物
欧姆龙医疗保健与医疗产品:Omron Healthcare
2020/02/10 全球购物
Expedia瑞典官网:预订度假屋、酒店、汽车租赁、机票等
2021/01/23 全球购物
.NET概念性的面试题
2012/02/29 面试题
市场营销毕业生自荐信
2013/11/23 职场文书
中学门卫岗位职责
2013/12/26 职场文书
元旦晚会感言
2014/03/12 职场文书
竞选体育委员演讲稿
2014/04/26 职场文书
关爱留守儿童标语
2014/06/18 职场文书
人口与计划生育目标管理责任书
2014/07/29 职场文书
客户经理岗位职责
2015/01/31 职场文书
业务员管理制度范本
2015/08/06 职场文书
干部考核工作总结
2015/08/12 职场文书
《天净沙·秋思》教学反思三篇
2019/11/02 职场文书
2020年元旦晚会策划书模板
2019/12/30 职场文书
详细聊一聊mysql的树形结构存储以及查询
2022/04/05 MySQL