深入理解JS中的Function.prototype.bind()方法


Posted in Javascript onOctober 11, 2016

前言

对于函数绑定(Function binding)很有可能是大家在使用JavaScript时最少关注的一点,但是当你意识到你需要一个解决方案来解决如何在另一个函数中保持this上下文的时候,你真正需要的其实就是 Function.prototype.bind() ,只是你有可能仍然没有意识到这点。

第一次遇到这个问题的时候,你可能倾向于将this设置到一个变量上,这样你可以在改变了上下文之后继续引用到它。

一. bind的语法

bind() 方法的主要作用就是将函数绑定至某个对象,bind() 方法会创建一个函数,函数体内this对象的值会被绑定到传入bind() 函数的值。

1.1 定义

bind()的定义如下:

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

bind() 函数会创建一个新函数(称为绑定函数),新函数与被调函数(绑定函数的目标函数)具有相同的函数体。当目标函数被调用时 this 值绑定到 bind() 的第一个参数,该参数不能被重写。

1.2 原理

可以用如下代码模拟bind()的原理:

Function.prototype.bind = function(context) {
 var self = this; // 保存原函数
 return function() { // 返回一个新函数
  return self.apply(context, arguments); // 执行新函数时,将传入的上下文context作为新函数的this
 }
}

1.3 语法

Function.prototype.bind(thisArg[, arg1[, arg2[, ...]]])

二. bind的应用场景

2.1 实现对象继承

var A = function(name) {
 this.name = name;
}

var B = function() {
 A.bind(this, arguments);
}

B.prototype.getName = function() {
 return this.name;
}

var b = new B("hello");
console.log(b.getName()); // "hello"

2.2 事件处理

var paint = {
 color: "red",
 count: 0,
 updateCount: function() {
  this.count++;
  console.log(this.count);
 }
};

// 事件处理函数绑定的错误方法:
document.querySelector('button')
 .addEventListener('click', paint.updateCount); // paint.updateCount函数的this指向变成了该DOM对象

// 事件处理函数绑定的正确方法:
document.querySelector('button')
 .addEventListener('click', paint.updateCount.bind(paint)); // paint.updateCount函数的this指向变成了paint

2.3 时间间隔函数

var notify = {
 text: "Hello World!",
 beforeRender: function() {
  alert(this.text);
 },
 render: function() {

  // 错误方法:
  setTimeout(this.beforeRender, 0); // undefined

  // 正确方法:
  setTimeout(this.beforeRender.bind(this), 0); // "Hello World!"
 }
};

notify.render();

2.4 借用Array的原生方法

var a = {};
Array.prototype.push.bind(a, "hello", "world")();

console.log(a); // "hello", "world"

三. bind()方法的浏览器兼容性

深入理解JS中的Function.prototype.bind()方法

四. bind()的兼容性写法

if (!Function.prototype.bind) {
 Function.prototype.bind = function() {
  var self = this, // 保存原函数
   context = [].shift.call(arguments), // 需要绑定的this上下文
   args = [].slice.call(arguments); // 剩余的参数转成数组
  return function() { // 返回一个新函数
   // 执行新函数时,将传入的上下文context作为新函数的this
   // 并且组合两次分别传入的参数,作为新函数的参数
   return self.apply(context, [].concat.call(args, [].slice.call(arguments))); 
  }
 };
}

五. bind与 call/apply方法的区别

共同点:

都可以改变函数执行的上下文环境;

不同点:

bind: 不立即执行函数,一般用在异步调用和事件; call/apply: 立即执行函数。

总结

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用Javascript能有一定的帮助,如果有疑问大家可以留言交流。

Javascript 相关文章推荐
JavaScript入门教程(1) 什么是JS
Jan 31 Javascript
jquery实现带复选框的表格行选中删除时高亮显示
Aug 01 Javascript
JQuery中serialize()、serializeArray()和param()方法示例介绍
Jul 31 Javascript
jQuery中ajax的get()方法用法实例
Dec 26 Javascript
浅析BootStrap Treeview的简单使用
Oct 12 Javascript
node.js实现回调的方法示例
Mar 01 Javascript
Angular2学习教程之ng中变更检测问题详解
May 28 Javascript
Vue中保存用户登录状态实例代码
Jun 07 Javascript
js canvas实现放大镜查看图片功能
Jun 08 Javascript
vue.js 嵌套循环、if判断、动态删除的实例
Mar 07 Javascript
JavaScript队列结构Queue实现过程解析
Mar 07 Javascript
uniapp实现横向滚动选择日期
Oct 21 Javascript
Bootstrap轮播插件使用代码
Oct 11 #Javascript
KnockoutJS 3.X API 第四章之表单textInput、hasFocus、checked绑定
Oct 11 #Javascript
JavaScript获取URL中参数querystring的方法详解
Oct 11 #Javascript
JS实现表单验证功能(验证手机号是否存在,验证码倒计时)
Oct 11 #Javascript
Node.js的环境安装配置(使用nvm方式)
Oct 11 #Javascript
javascript 动态样式添加的简单实现
Oct 11 #Javascript
表单input项使用label同时引用Bootstrap库导致input点击效果区增大问题
Oct 11 #Javascript
You might like
PHP与C#分别格式化文件大小的代码
2011/05/14 PHP
PHP mysqli_free_result()与mysqli_fetch_array()函数详解
2016/09/21 PHP
php高清晰度无损图片压缩功能的实现代码
2018/12/09 PHP
Ext.FormPanel 提交和 Ext.Ajax.request 异步提交函数的区别
2009/11/12 Javascript
jQuery 表格插件整理
2010/04/27 Javascript
Javascript实现单张图片浏览
2014/12/18 Javascript
简介JavaScript中Math.LOG10E属性的使用
2015/06/14 Javascript
javascript创建函数的20种方式汇总
2015/06/23 Javascript
浅谈JavaScript超时调用和间歇调用
2015/08/30 Javascript
js获取鼠标位置实例详解
2015/12/09 Javascript
利用JS判断鼠标移入元素的方向
2016/12/11 Javascript
详解JavaScript中的函数、对象
2019/04/01 Javascript
微信小程序设置全局请求URL及封装wx.request请求操作示例
2019/04/02 Javascript
vue简单练习 桌面时钟的实现代码实例
2019/09/19 Javascript
如何HttpServletRequest文件对象并储存
2020/08/14 Javascript
vue+elementUI实现简单日历功能
2020/09/24 Javascript
Python使用SocketServer模块编写基本服务器程序的教程
2016/07/12 Python
详解Python中表达式i += x与i = i + x是否等价
2017/02/08 Python
15行Python代码带你轻松理解令牌桶算法
2018/03/21 Python
python利用pandas将excel文件转换为txt文件的方法
2018/10/23 Python
用python3教你任意Html主内容提取功能
2018/11/05 Python
基于python读取.mat文件并取出信息
2019/12/16 Python
Python函数基本使用原理详解
2020/03/19 Python
Python 通过正则表达式快速获取电影的下载地址
2020/08/17 Python
详解Python中@staticmethod和@classmethod区别及使用示例代码
2020/12/14 Python
localStorage、sessionStorage使用总结
2017/11/17 HTML / CSS
HTML5 解决苹果手机不能自动播放音乐问题
2017/12/27 HTML / CSS
介绍一下Cookie和Session及他们之间的区别
2012/11/20 面试题
Python如何实现单例模式
2016/06/03 面试题
外贸英语毕业生自荐信
2013/11/14 职场文书
小学毕业感言300字
2014/02/19 职场文书
乡村卫生服务一体化管理实施方案
2014/03/30 职场文书
领导干部群众路线个人对照检查材料思想汇报
2014/09/30 职场文书
小学大队委竞选口号
2015/12/25 职场文书
创业计划书之餐饮
2019/09/02 职场文书
html5 录制mp3音频支持采样率和比特率设置
2021/07/15 Javascript