深入理解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 动态生成方法的例子
Jul 22 Javascript
弹出最简单的模式化遮罩层的js代码
Dec 04 Javascript
关闭页面window.location事件未执行的原因及解决方法
Sep 01 Javascript
moment.js轻松实现获取当前日期是当年的第几周
Feb 05 Javascript
js实现简单的可切换选项卡效果
Apr 10 Javascript
详解Bootstrap的aria-label和aria-labelledby应用
Jan 04 Javascript
JS正则截取两个字符串之间及字符串前后内容的方法
Jan 06 Javascript
JS对象创建的几种方式整理
Feb 28 Javascript
20行JS代码实现粘贴板复制功能
Feb 06 Javascript
微信小程序当前时间时段选择器插件使用方法详解
Dec 28 Javascript
Node.js折腾记一:读指定文件夹,输出该文件夹的文件树详解
Apr 20 Javascript
jquery树形插件zTree高级使用详解
Aug 16 jQuery
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
PHP4中实现动态代理
2006/10/09 PHP
PHP 存储文本换行实现方法
2010/01/05 PHP
php分割合并两个字符串的函数实例
2015/06/19 PHP
WordPress中用于获取文章作者与分类信息的方法整理
2015/12/17 PHP
PHP数组游标实现对数组的各种操作详解
2016/01/26 PHP
ThinkPHP框架中使用Memcached缓存数据的方法
2018/03/31 PHP
Javascript模块模式分析
2008/05/16 Javascript
jQuery获取样式中的背景颜色属性值/颜色值
2012/12/17 Javascript
juery框架写的弹窗效果适合新手
2013/11/27 Javascript
浅析Javascript匿名函数与自执行函数
2016/02/06 Javascript
JS实现输入框提示文字点击时消失效果
2016/07/19 Javascript
JavaScript对象创建模式实例汇总
2016/10/03 Javascript
jQuery插件扩展操作入门示例
2017/01/16 Javascript
详解VueJs前后端分离跨域问题
2017/05/24 Javascript
vue-router实现编程式导航的代码实例
2019/01/19 Javascript
小程序从手动埋点到自动埋点的实现方法
2019/01/24 Javascript
Vue 防止短时间内连续点击后多次触发请求的操作
2020/11/11 Javascript
Python的ORM框架SQLObject入门实例
2014/04/28 Python
python中的字典详细介绍
2014/09/18 Python
Python脚本实现集群检测和管理功能
2015/03/06 Python
Python应用03 使用PyQT制作视频播放器实例
2016/12/07 Python
Python3计算三角形的面积代码
2017/12/18 Python
Python中shapefile转换geojson的示例
2019/01/03 Python
利用pytorch实现对CIFAR-10数据集的分类
2020/01/14 Python
CSS3 Columns分列式布局方法简介
2014/05/03 HTML / CSS
英国最大的在线运动补充剂商店:Discount Supplements
2017/06/03 全球购物
日本最大美瞳直送网:Morecontact(中文)
2019/04/03 全球购物
Jar包的作用是什么
2014/03/30 面试题
期末自我鉴定
2014/02/02 职场文书
财务总监管理岗位职责
2014/03/08 职场文书
放飞理想演讲稿
2014/09/09 职场文书
党委书记个人检查对照材料思想汇报
2014/10/11 职场文书
行风评议整改报告
2014/11/06 职场文书
数据结构课程设计心得体会
2016/01/15 职场文书
2016优秀大学生个人事迹材料范文
2016/03/01 职场文书
教你怎么用PyCharm为同一服务器配置多个python解释器
2021/05/31 Python