深入理解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 相关文章推荐
Ext面向对象开发实践(续)
Nov 18 Javascript
Jquery阻止事件冒泡 event.stopPropagation
Dec 11 Javascript
jQuery:delegate中select()不起作用的解决方法(实例讲解)
Jan 26 Javascript
iframe父页面获取子页面参数的方法
Feb 21 Javascript
js实现鼠标划过给div加透明度的方法
May 25 Javascript
javascript常用经典算法实例详解
Nov 25 Javascript
Three.js学习之Lamber材质和Phong材质
Aug 04 Javascript
js仿iphone秒表功能 计算平均数
Jan 11 Javascript
angularjs下拉框空白的解决办法
Jun 20 Javascript
详解Node中导入模块require和import的区别
Aug 11 Javascript
原生JS实现的雪花飘落动画效果
May 03 Javascript
你可能不知道的CORS跨域资源共享
Mar 13 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
Yii框架关联查询with用法分析
2014/12/02 PHP
PHP自动补全表单的两种方法
2017/03/06 PHP
PHP defined()函数的使用图文详解
2019/07/20 PHP
THINKPHP5分页数据对象处理过程解析
2020/10/28 PHP
window.name代替cookie的实现代码
2010/11/28 Javascript
Javascript延迟执行实现方法(setTimeout)
2010/12/30 Javascript
Jquery动态改变图片IMG的src地址示例
2013/06/25 Javascript
JavaScript实现维吉尼亚(Vigenere)密码算法实例
2013/11/22 Javascript
删除javascript中注释语句的正则表达式
2014/06/11 Javascript
js关于命名空间的函数实例
2015/02/05 Javascript
总结javascript中的六种迭代器
2016/08/16 Javascript
JavaScript中数组的各种操作的总结(必看篇)
2017/02/13 Javascript
vue学习笔记之vue1.0和vue2.0的区别介绍
2017/05/17 Javascript
快速搭建vue2.0+boostrap项目的方法
2018/04/09 Javascript
使用D3.js+Vue实现一个简单的柱形图
2018/08/05 Javascript
ES6使用export和import实现模块化的方法
2018/09/10 Javascript
13 个npm 快速开发技巧(推荐)
2019/07/04 Javascript
百度小程序之间的页面通信过程详解
2019/07/18 Javascript
基于javascript实现碰撞检测
2020/03/12 Javascript
[02:36]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Magma 选手采访
2021/03/11 DOTA
详解Python3操作Mongodb简明易懂教程
2017/05/25 Python
Django数据库操作的实例(增删改查)
2017/09/04 Python
Python实现的txt文件去重功能示例
2018/07/07 Python
python+pandas+时间、日期以及时间序列处理方法
2018/07/10 Python
python批量下载网站马拉松照片的完整步骤
2018/12/05 Python
Pytorch实现GoogLeNet的方法
2019/08/18 Python
pytorch模型存储的2种实现方法
2020/02/14 Python
使用python matplotlib 画图导入到word中如何保证分辨率
2020/04/16 Python
CSS3制作翻转效果_动力节点Java学院整理
2017/07/11 HTML / CSS
CSS3实现多重边框的方法总结
2016/05/31 HTML / CSS
锐步香港官方网上商店:Reebok香港
2020/11/05 全球购物
UNIX文件系统分类
2014/11/11 面试题
活动总结怎么写啊
2014/05/07 职场文书
我是一名护士演讲稿
2014/08/28 职场文书
歌颂党的演讲稿
2014/09/10 职场文书
农村老人去世追悼词
2015/06/23 职场文书