深入理解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 相关文章推荐
判断多个元素(RADIO,CHECKBOX等)是否被选择的原理说明
Feb 18 Javascript
extjs fckeditor集成代码
May 10 Javascript
基于jquery实现的一个选择中国大学的弹框 (数据、步骤、代码)
Jul 26 Javascript
js带按钮的提示框可供选择示例代码
Sep 17 Javascript
jQuery中ajax的post()方法用法实例
Dec 26 Javascript
详细分析JavaScript函数定义
Jul 16 Javascript
JS实现可编辑的后台管理菜单功能【附demo源码下载】
Sep 13 Javascript
详解Angular的数据显示优化处理
Dec 26 Javascript
使用jQuery监听扫码枪输入并禁止手动输入的实现方法(推荐)
Mar 21 jQuery
vue2.0的contextmenu右键弹出菜单的实例代码
Jul 24 Javascript
Vue三种常用传值示例(父传子、子传父、非父子)
Jul 24 Javascript
vue路由跳转传参数的方法
May 06 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单例模式
2014/11/25 PHP
php自动给网址加上链接的方法
2015/06/02 PHP
smarty高级特性之对象的使用方法
2015/12/25 PHP
WordPress主题制作之模板文件的引入方法
2015/12/28 PHP
PHP preg_match实现正则表达式匹配功能【输出是否匹配及匹配值】
2017/07/19 PHP
PHP实现获取ip地址的5种方法,以及插入用户登录日志操作示例
2019/02/28 PHP
javascript 获取元素位置的快速方法 getBoundingClientRect()
2009/11/26 Javascript
stream.js 一个很小、完全独立的Javascript类库
2011/10/28 Javascript
用js写了一个类似php的print_r输出换行功能
2013/02/18 Javascript
php结合imgareaselect实现图片裁剪
2015/07/05 Javascript
js点击按钮实现带遮罩层的弹出视频效果
2015/12/19 Javascript
GitHub上一些实用的JavaScript的文件压缩解压缩库推荐
2016/03/13 Javascript
JS实现弹出居中的模式窗口示例
2016/06/20 Javascript
Vue项目中设置背景图片方法
2018/02/21 Javascript
React如何解决fetch跨域请求时session失效问题
2018/11/02 Javascript
video.js 一个页面同时播放多个视频的实例代码
2018/11/27 Javascript
微信小程序如何实现五星评价功能
2019/10/15 Javascript
手把手教你实现 Promise的使用方法
2020/09/02 Javascript
wxPython框架类和面板类的使用实例
2014/09/28 Python
Python Sleep休眠函数使用简单实例
2015/02/02 Python
Python的Bottle框架中获取制定cookie的教程
2015/04/24 Python
python实现发送邮件功能
2017/07/22 Python
python pandas库的安装和创建
2019/01/10 Python
Python-ElasticSearch搜索查询的讲解
2019/02/25 Python
11个Python Pandas小技巧让你的工作更高效(附代码实例)
2019/04/30 Python
pycharm new project变成灰色的解决方法
2019/06/27 Python
如何获取Python简单for循环索引
2019/11/21 Python
Python爬虫实战案例之爬取喜马拉雅音频数据详解
2020/12/07 Python
小橄榄树:Le Petit Olivier
2018/04/23 全球购物
广告学专业应届生求职信
2013/10/01 职场文书
农村党支部先进事迹
2014/01/14 职场文书
高二英语教学反思
2014/01/19 职场文书
行政司机岗位职责
2015/04/10 职场文书
2015年小学总务工作总结
2015/07/21 职场文书
导游词之山东八大关
2019/12/18 职场文书
详解PHP用mb_string处理windows中文字符
2021/05/26 PHP