深入理解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 相关文章推荐
客户端静态页面玩分页
Jun 26 Javascript
比较详细的关于javascript中void(0)的具体含义解释
Aug 02 Javascript
jquery提升性能最佳实践小结
Dec 06 Javascript
js每隔5分钟执行一次ajax请求的实现方法
Nov 27 Javascript
angularjs客户端实现压缩图片文件并上传实例
Jul 06 Javascript
Kindeditor在线文本编辑器如何过滤HTML
Apr 14 Javascript
深入理解requestAnimationFrame的动画循环
Sep 20 Javascript
JS前端加密算法示例
Dec 22 Javascript
Express系列之multer上传的使用
Oct 27 Javascript
Bootstrap treeview实现动态加载数据并添加快捷搜索功能
Jan 07 Javascript
webpack 样式加载的实现原理
Jun 12 Javascript
Vue与React的区别和优势对比
Dec 18 Vue.js
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/10/20 PHP
php取出数组单个值的方法
2018/03/12 PHP
laravel 解决paginate查询多个字段报错的问题
2019/10/22 PHP
PHP dirname简单使用代码实例
2020/11/13 PHP
Firefox outerHTML实现代码
2009/06/04 Javascript
jQuery学习2 选择器的使用说明
2010/02/07 Javascript
jQuery解决input超多的表单提交
2015/08/10 Javascript
JS模拟Dialog弹出浮动框效果代码
2015/10/16 Javascript
基于jQuery和CSS3制作数字时钟附源码下载(jquery篇)
2015/11/24 Javascript
jQuery UI插件实现百度提词器效果
2016/11/21 Javascript
js实现右键菜单功能
2016/11/28 Javascript
解决Jstree 选中父节点时被禁用的子节点也会选中的问题
2017/12/27 Javascript
Vue2.0 给Tab标签页和页面切换过渡添加样式的方法
2018/03/13 Javascript
js传递数组参数到后台controller的方法
2018/03/29 Javascript
Angular-UI Bootstrap组件实现警报功能
2018/07/16 Javascript
VUE2.0 ElementUI2.0表格el-table自适应高度的实现方法
2018/11/28 Javascript
简单了解vue.js数组的常用操作
2019/06/17 Javascript
vue中使用v-for时为什么不能用index作为key
2020/04/04 Javascript
JavaScript经典案例之简易计算器
2020/08/24 Javascript
浅谈vue websocket nodeJS 进行实时通信踩到的坑
2020/09/22 NodeJs
jQuery实现二级导航菜单的示例
2020/09/30 jQuery
python简单程序读取串口信息的方法
2015/03/13 Python
用Python3创建httpServer的简单方法
2018/06/04 Python
Python 3.x基于Xml数据的Http请求方法
2018/12/28 Python
python实现对输入的密文加密
2019/03/20 Python
pytorch ImageFolder的覆写实例
2020/02/20 Python
Python小白学习爬虫常用请求报头
2020/06/03 Python
解决python和pycharm安装gmpy2 出现ERROR的问题
2020/08/28 Python
美国诺德斯特龙百货官网:Nordstrom
2016/08/23 全球购物
美国独家设计师眼镜在线光学商店:Glasses Gallery
2017/12/28 全球购物
JSP和EJB可以共享HttpSession么?EJB里面可以改变session里面的内容
2013/06/05 面试题
《匆匆》教学反思
2014/02/22 职场文书
创建省级文明单位实施方案
2014/02/27 职场文书
高中生职业规划范文
2014/03/09 职场文书
颁奖典礼主持词
2014/03/25 职场文书
维稳承诺书
2015/01/20 职场文书