如何手动实现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 相关文章推荐
jQuery Ajax 仿AjaxPro.Utility.RegisterTypeForAjax辅助方法
Sep 27 Javascript
JAVASCRIPT模式窗口中下载文件无法接收iframe的流
Oct 11 Javascript
jquery实现效果比较好的table选中行颜色
Mar 25 Javascript
实例讲解JS中数组Array的操作方法
May 09 Javascript
JS定义网页表单提交(submit)的方法
Mar 20 Javascript
JavaScript中的anchor()方法使用详解
Jun 08 Javascript
CSS3 media queries结合jQuery实现响应式导航
Sep 30 Javascript
详解vue2.0 transition 多个元素嵌套使用过渡
Jun 19 Javascript
原生JS实现的自动轮播图功能详解
Dec 28 Javascript
解决在layer.open中使用时间控件laydate失败的问题
Sep 11 Javascript
Vue发布订阅模式实现过程图解
Apr 30 Javascript
如何通过Proxy实现JSBridge模块化封装
Oct 22 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几个数学计算的内部函数学习整理
2011/08/06 PHP
PHP上传文件时自动分配路径的方法
2015/01/09 PHP
Thinkphp5框架实现图片、音频和视频文件的上传功能详解
2019/08/27 PHP
基于jquery的兼容各种浏览器的iframe自适应高度的脚本
2010/08/13 Javascript
读jQuery之五(取DOM元素)
2011/06/20 Javascript
jQuery 获取和设置select下拉框的值实现代码
2013/11/08 Javascript
jquery操作下拉列表、文本框、复选框、单选框集合(收藏)
2014/01/08 Javascript
JS获取各种浏览器窗口大小的方法
2014/01/14 Javascript
js对象内部访问this修饰的成员函数示例
2014/04/27 Javascript
全面解析Bootstrap表单样式的使用
2016/09/09 Javascript
通过BootStrap实现轮播图的实际应用
2016/09/26 Javascript
JS实现闭包中的沙箱模式示例
2017/09/07 Javascript
JavaScript中错误正确处理方式小结你用对了吗
2017/10/10 Javascript
jQuery实现的监听导航滚动置顶状态功能示例
2018/07/23 jQuery
axios向后台传递数组作为参数的方法
2018/08/11 Javascript
基于Vue 服务端Cookies删除的问题
2018/09/21 Javascript
python cookielib 登录人人网的实现代码
2012/12/19 Python
Python的Flask框架中实现登录用户的个人资料和头像的教程
2015/04/20 Python
python3实现163邮箱SMTP发送邮件
2018/05/22 Python
Python全局变量与局部变量区别及用法分析
2018/09/03 Python
Python控制键盘鼠标pynput的详细用法
2019/01/28 Python
Python使用urllib模块对URL网址中的中文编码与解码实例详解
2020/02/18 Python
如何基于Python pygame实现动画跑马灯
2020/11/18 Python
Python实现Word文档转换Markdown的示例
2020/12/22 Python
英国内衣连锁店:Boux Avenue
2018/01/24 全球购物
美国最大的无人机经销商:DroneNerds
2018/03/20 全球购物
公司合作协议书范本
2014/04/18 职场文书
2014党员自我评议表范文
2014/09/20 职场文书
党员教师四风自我剖析材料
2014/09/30 职场文书
遗嘱继承权公证书
2015/01/26 职场文书
交流会主持词
2015/07/02 职场文书
感恩信:写给爸爸妈妈的一封感谢信
2019/09/12 职场文书
写作之关于描写老人的好段摘抄
2019/11/14 职场文书
SQL语句中JOIN的用法场景分析
2021/07/25 SQL Server
利用JuiceFS使MySQL 备份验证性能提升 10 倍
2022/03/17 MySQL
Java多线程并发FutureTask使用详解
2022/06/28 Java/Android