如何手动实现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 相关文章推荐
在网站上应该用的30个jQuery插件整理
Nov 03 Javascript
根据当前时间在jsp页面上显示上午或下午
Aug 18 Javascript
BootStrap与validator 使用笔记(JAVA SpringMVC实现)
Sep 21 Javascript
聊一聊JS中的prototype
Sep 29 Javascript
详解PHP中pathinfo()函数导致的安全问题
Jan 05 Javascript
Node.js编写CLI的实例详解
May 17 Javascript
详解Vue微信公众号开发踩坑全记录
Aug 21 Javascript
CKEditor4配置与开发详细中文说明文档
Oct 08 Javascript
vue项目前端埋点的实现
Mar 06 Javascript
详解vue微信网页授权最终解决方案
Jun 16 Javascript
微信小程序实现日期格式化和倒计时
Nov 01 Javascript
js对象简介与基本用法示例
Mar 13 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
ASP知识讲座四
2006/10/09 PHP
linux使用crontab实现PHP执行计划定时任务
2014/05/10 PHP
Yii结合CKEditor实现图片上传功能
2014/06/13 PHP
php删除文本文件中重复行的方法
2015/04/28 PHP
thinkPHP连接sqlite3数据库的实现方法(附Thinkphp代码生成器下载)
2016/05/27 PHP
laravel 使用事件系统统计浏览量的实现
2019/10/16 PHP
json属性名为什么要双引号(个人猜测)
2014/07/31 Javascript
JS日期格式化之javascript Date format
2015/10/01 Javascript
自定义Angular指令与jQuery实现的Bootstrap风格数据双向绑定的单选与多选下拉框
2015/12/12 Javascript
jquery实用技巧之输入框提示语句
2016/07/28 Javascript
vue.js入门教程之计算属性
2016/09/01 Javascript
使用BootStrap实现表格隔行变色及hover变色并在需要时出现滚动条
2017/01/04 Javascript
原生js实现无缝轮播图效果
2017/01/11 Javascript
JS实现前端缓存的方法
2017/09/21 Javascript
在Vue-cli里应用Vuex的state和mutations方法
2018/09/16 Javascript
python文件读写操作与linux shell变量命令交互执行的方法
2015/01/14 Python
Python单例模式实例分析
2015/01/14 Python
Python判断Abundant Number的方法
2015/06/15 Python
使用Python3+PyQT5+Pyserial 实现简单的串口工具方法
2019/02/13 Python
基于Python生成个性二维码过程详解
2020/03/05 Python
Python figure参数及subplot子图绘制代码
2020/04/18 Python
经验丰富程序员才知道的8种高级Python技巧
2020/07/27 Python
Pycharm无法打开双击没反应的问题及解决方案
2020/08/17 Python
CSS3模块的目前的状况分析
2010/02/24 HTML / CSS
HTML5 canvas实现雪花飘落特效
2016/03/08 HTML / CSS
Under Armour澳大利亚官网:美国知名的高端功能性运动品牌
2018/02/22 全球购物
员工自我鉴定
2013/10/09 职场文书
高中校园广播稿
2014/01/11 职场文书
税务职业生涯规划书范文
2014/09/16 职场文书
2014年向国旗敬礼活动方案
2014/09/27 职场文书
见习报告格式范文
2014/11/08 职场文书
社区文明创建工作总结2015
2015/04/21 职场文书
幼儿园开学家长寄语(2016秋季)
2015/12/03 职场文书
市场营销计划书
2019/04/24 职场文书
CSS 还能这样玩?奇思妙想渐变的艺术
2021/04/27 HTML / CSS
Android中的Launch Mode详情
2022/06/05 Java/Android