如何手动实现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 相关文章推荐
javascript multibox 全选
Mar 22 Javascript
基于jQuery的ajax功能实现web service的json转化
Aug 29 Javascript
循环 vs 递归浅谈
Feb 28 Javascript
JS中的==运算: [''] == false —>true
Jul 24 Javascript
浅谈在koa2中实现页面渲染的全局数据
Oct 09 Javascript
JavaScript实现精美个性导航栏筋斗云效果
Oct 29 Javascript
Vue 动态设置路由参数的案例分析
Apr 24 Javascript
在vue-cli搭建的项目中增加后台mock接口的方法
Apr 26 Javascript
JS中实现隐藏部分姓名或者电话号码的代码
Jul 17 Javascript
Vue cli构建及项目打包以及出现的问题解决
Aug 27 Javascript
vue组件(全局,局部,动态加载组件)
Sep 02 Javascript
Postman参数化实现过程及原理解析
Aug 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
php模板之Phpbean的目录结构
2008/01/10 PHP
php的sso单点登录实现方法
2015/01/08 PHP
php限制ip地址范围的方法
2015/03/31 PHP
PHP基于单例模式实现的mysql类
2016/01/09 PHP
利用switch语句进行多选一判断的实例代码
2016/11/14 PHP
php实现的顺序线性表示例
2019/05/04 PHP
通过身份证号得到出生日期和性别的js代码
2009/11/23 Javascript
js constructor的实际作用分析
2011/11/15 Javascript
使用Javascript简单实现图片无缝滚动
2014/12/05 Javascript
jquery.uploadify插件在chrome浏览器频繁崩溃解决方法
2015/03/01 Javascript
jQuery Ajax 上传文件处理方式介绍(推荐)
2016/06/30 Javascript
详解Angular4中路由Router类的跳转navigate
2017/06/09 Javascript
5 种JavaScript编码规范
2018/01/30 Javascript
js神秘的电报密码 哈弗曼编码实现
2019/09/10 Javascript
JS相册图片抖动放大展示效果的示例代码
2021/01/29 Javascript
Python语言实现获取主机名根据端口杀死进程
2016/03/31 Python
python基于pyDes库实现des加密的方法
2017/04/29 Python
Python3.5迭代器与生成器用法实例分析
2019/04/30 Python
python 使用多线程创建一个Buffer缓存器的实现思路
2020/07/02 Python
python如何删除列为空的行
2020/07/17 Python
html5组织文档结构_动力节点Java学院整理
2017/07/11 HTML / CSS
html5+css3进度条倒计时动画特效代码【推荐】
2016/03/08 HTML / CSS
HTML5 source标签:媒介元素定义媒介资源
2018/01/29 HTML / CSS
canvas进阶之如何画出平滑的曲线
2018/10/15 HTML / CSS
DJI大疆德国官方商城:大疆无人机
2018/09/01 全球购物
公司员工检讨书
2014/02/08 职场文书
家长对学生的评语
2014/04/18 职场文书
学校运动会霸气口号
2014/06/07 职场文书
禁止高声喧哗的标语
2014/06/11 职场文书
大学新生军训自我鉴定
2014/09/18 职场文书
考试作弊检讨书
2015/01/27 职场文书
离婚起诉书怎么写
2015/05/19 职场文书
新学期开学寄语2016
2015/12/04 职场文书
六年级上册《闻官军收河南河北》的教学设计
2019/11/15 职场文书
基于Go Int转string几种方式性能测试
2021/04/28 Golang
Java无向树分析 实现最小高度树
2022/04/09 Javascript