如何手动实现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 相关文章推荐
浅析document.ready和window.onload的区别讲解
Dec 18 Javascript
jQuery及JS实现循环中暂停的方法
Feb 02 Javascript
JS提交form表单实例分析
Dec 10 Javascript
jQuery滚动插件scrollable.js用法分析
May 25 jQuery
JS判断Android、iOS或浏览器的多种方法(四种方法)
Jun 29 Javascript
layui框架中layer父子页面交互的方法分析
Nov 15 Javascript
Thinkjs3新手入门之如何使用静态资源目录
Dec 06 Javascript
jQuery第一次运行页面默认触发点击事件的实例
Jan 10 jQuery
Angular 如何使用第三方库的方法
Apr 18 Javascript
微信小程序常见页面跳转操作简单示例
May 01 Javascript
JS内置对象和Math对象知识点详解
Apr 03 Javascript
js中Map和Set的用法及区别实例详解
Feb 15 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
Yii Framework框架获取分类下面的所有子类方法
2014/06/20 PHP
Symfony的安装和配置方法
2016/03/17 PHP
Yii统计不同类型邮箱数量的方法
2016/10/18 PHP
php微信开发之自定义菜单实现
2016/11/18 PHP
php实现的错误处理封装类实例
2017/06/20 PHP
Javascript select下拉框操作常用方法
2009/11/09 Javascript
Jquery替换已存在于element上的event的方法
2010/03/09 Javascript
基于jquery封装的一个js分页
2011/11/15 Javascript
两个数组去重的JS代码
2013/12/04 Javascript
js日期对象兼容性的处理方法
2014/01/28 Javascript
JS执行删除前的判断代码
2014/02/18 Javascript
Angularjs基础知识及示例汇总
2015/01/22 Javascript
分享jQuery插件的学习笔记
2016/01/14 Javascript
JavaScript jquery及AJAX小结
2016/01/24 Javascript
javascript实现label标签跳出循环操作
2016/03/06 Javascript
jquery实现跳到底部,回到顶部效果的简单实例(类似锚)
2016/07/10 Javascript
JQ图片文件上传之前预览功能的简单实例(分享)
2017/11/12 Javascript
vue实现城市列表选择功能
2018/07/16 Javascript
详解Axios 如何取消已发送的请求
2018/10/20 Javascript
一些你可能不熟悉的JS知识点总结
2019/03/15 Javascript
layui table 列宽百分比显示的实现方法
2019/09/28 Javascript
浅析vue中的provide / inject 有什么用处
2019/11/10 Javascript
Python编程实现删除VC临时文件及Debug目录的方法
2017/03/22 Python
详解django的serializer序列化model几种方法
2018/10/16 Python
python3使用matplotlib绘制条形图
2020/03/25 Python
tensorflow模型继续训练 fineturn实例
2020/01/21 Python
python GUI库图形界面开发之PyQt5布局控件QHBoxLayout详细使用方法与实例
2020/03/06 Python
浅谈tensorflow使用张量时的一些注意点tf.concat,tf.reshape,tf.stack
2020/06/23 Python
HTML5实现桌面通知 提示功能
2017/10/11 HTML / CSS
Internet主要有哪些网络群组成
2015/12/24 面试题
计算机大学生的自我评价
2013/10/15 职场文书
管理学专业个人求职信范文
2013/12/13 职场文书
酒店司机岗位职责
2013/12/14 职场文书
美术毕业生求职信
2014/02/25 职场文书
公务员保密承诺书
2014/03/27 职场文书
生物工程专业求职信
2014/09/03 职场文书