深入理解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 相关文章推荐
js程序中美元符号$是什么
Jun 05 Javascript
jQuery 遍历json数组的实现代码
Sep 22 Javascript
js hover 定时器(实例代码)
Nov 12 Javascript
JavaScript 实现鼠标拖动元素实例代码
Feb 24 Javascript
JQuery实现级联下拉框效果实例讲解
Sep 17 Javascript
基于原生js淡入淡出函数封装(兼容IE)
Oct 20 Javascript
vue中渐进过渡效果实现
Oct 27 Javascript
js 获取本地文件及目录的方法(推荐)
Nov 10 Javascript
layui框架中layer父子页面交互的方法分析
Nov 15 Javascript
Vue-cli3.x + axios 跨域方案踩坑指北
Jul 04 Javascript
vue-cli随机生成port源码的方法
Sep 02 Javascript
如何用vue实现网页截图你知道吗
Nov 17 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中Cannot send session cache limiter 的问题的方法
2007/04/27 PHP
PHP5 字符串处理函数大全
2010/03/23 PHP
基于php使用memcache存储session的详解
2013/06/25 PHP
PHP实现获取并生成数据库字典的方法
2016/05/04 PHP
浅谈php中urlencode与rawurlencode的区别
2016/09/05 PHP
Yii2中简单的场景使用介绍
2017/06/02 PHP
一个js的tab切换效果代码[代码分离]
2010/04/11 Javascript
js DOM的学习笔记
2011/12/22 Javascript
『jQuery』取指定url格式及分割函数应用
2013/04/22 Javascript
Javacript实现颜色梯度变化和渐变的效果代码
2013/05/31 Javascript
教你使用javascript简单写一个页面模板引擎
2015/05/05 Javascript
详解js中==与===的区别
2017/01/08 Javascript
jQuery中layer分页器的使用
2017/03/13 Javascript
nodejs开发——express路由与中间件
2017/03/24 NodeJs
对于input 框限定输入值为浮点型的js代码
2017/09/25 Javascript
JS插件amCharts实现绘制柱形图默认显示数值功能示例
2019/11/26 Javascript
python中去空格函数的用法
2014/08/21 Python
Python的“二维”字典 (two-dimension dictionary)定义与实现方法
2016/04/27 Python
Python加密方法小结【md5,base64,sha1】
2017/07/13 Python
python实现堆和索引堆的代码示例
2018/03/19 Python
python对离散变量的one-hot编码方法
2018/07/11 Python
Pytorch 实现冻结指定卷积层的参数
2020/01/06 Python
TensorFlow内存管理bfc算法实例
2020/02/03 Python
使用python客户端访问impala的操作方式
2020/03/28 Python
Python日志处理模块logging用法解析
2020/05/19 Python
Jupyter Notebook添加代码自动补全功能的实现
2021/01/07 Python
纯css3实现宠物小鸡实例代码
2018/10/08 HTML / CSS
基督教卡片、励志礼品、家居装饰等:DaySpring
2018/10/12 全球购物
法国一家多品牌成衣精品中/高档商店:Graduate Store
2019/08/28 全球购物
大学同学聚会邀请函
2014/01/19 职场文书
寄语十八大感言
2014/02/07 职场文书
马智宇婚礼主持词
2014/03/22 职场文书
大型公益活动策划方案
2014/08/20 职场文书
年底个人总结范文
2015/03/10 职场文书
Python中for后接else的语法使用
2021/05/18 Python
Tomcat starup.bat 脚本实现开机自启动
2022/04/20 Servers