如何手动实现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向flash swf文件传递参数值注意细节
Dec 11 Javascript
js中typeof的用法汇总
Dec 12 Javascript
js中的如何定位固定层的位置
Jun 15 Javascript
解析JavaScript的ES6版本中的解构赋值
Jul 28 Javascript
window.onload使用指南
Sep 13 Javascript
30分钟快速掌握Bootstrap框架
May 24 Javascript
jQuery实现对无序列表的排序功能(附demo源码下载)
Jun 25 Javascript
Javascript中常见的逻辑题和解决方法
Sep 17 Javascript
微信小程序 绘图之饼图实现
Oct 24 Javascript
bootstrap weebox 支持ajax的模态弹出框
Feb 23 Javascript
React路由管理之React Router总结
May 10 Javascript
javascript设计模式 ? 适配器模式原理与应用实例分析
Apr 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
德生PL330的评价与改造
2021/03/02 无线电
php防注
2007/01/15 PHP
php 解决旧系统 查出所有数据分页的类
2012/08/27 PHP
php使用GD2绘制几何图形示例
2017/02/15 PHP
动态加载图片路径 保持JavaScript控件的相对独立性
2010/09/03 Javascript
JQuery+JS实现仿百度搜索结果中关键字变色效果
2011/08/02 Javascript
打豆豆小游戏 用javascript编写的[打豆豆]小游戏
2013/01/08 Javascript
Jquery对数组的操作技巧整理
2014/03/25 Javascript
JavaScript实现穷举排列(permutation)算法谜题解答
2014/12/29 Javascript
jQuery简单操作cookie的插件实例
2016/01/13 Javascript
AngularJS使用ngOption实现下拉列表的实例代码
2016/01/23 Javascript
AngularJS中的表单简单入门
2016/07/28 Javascript
JavaScript实现输入框与清空按钮联动效果
2016/09/09 Javascript
jQuery实现下拉菜单动态添加数据点击滑出收起其他功能
2018/06/14 jQuery
JavaScript 复制对象与Object.assign方法无法实现深复制
2018/11/02 Javascript
vscode 开发Vue项目的方法步骤
2018/11/25 Javascript
JavaScript实现邮箱后缀提示功能的示例代码
2018/12/13 Javascript
微信公众号平台接口开发 获取access_token过程解析
2019/08/14 Javascript
详解Python连接MySQL数据库的多种方式
2019/04/16 Python
Python基础学习之时间转换函数用法详解
2019/06/18 Python
python实现udp聊天窗口
2020/03/31 Python
Python3爬虫发送请求的知识点实例
2020/07/30 Python
CSS3提交意见输入框样式代码
2014/10/30 HTML / CSS
HTML5实现预览本地图片
2016/02/17 HTML / CSS
英国航空官网:British Airways
2016/09/11 全球购物
物业管理应届生求职信
2013/10/28 职场文书
退伍老兵事迹材料
2014/01/31 职场文书
市场拓展计划书
2014/05/03 职场文书
公司优秀员工获奖感言
2014/08/14 职场文书
民事二审代理词
2015/05/25 职场文书
班级班风口号大全
2015/12/25 职场文书
幼师自荐信范文(2016推荐篇)
2016/01/28 职场文书
再读《皇帝的新衣》的读后感悟!
2019/08/07 职场文书
解决golang结构体tag编译错误的问题
2021/05/02 Golang
mysql 索引合并的使用
2021/08/30 MySQL
二维码条形码生成的JavaScript脚本库
2022/07/07 Javascript