深入理解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全局变量封装模块实现代码
Nov 28 Javascript
jQuery点击tr实现checkbox选中的方法
Mar 19 Javascript
CSS3实现动态背景登录框的代码
Jul 28 Javascript
jQuery实现带延时功能的水平多级菜单效果【附demo源码下载】
Sep 21 Javascript
简单理解js的冒泡排序
Dec 19 Javascript
走进javascript——不起眼的基础,值和分号
Feb 24 Javascript
EasyUI Datebox 日期验证之开始日期小于结束时间
May 19 Javascript
vue在使用ECharts时的异步更新和数据加载详解
Nov 22 Javascript
详解如何创建并发布一个 vue 组件
Nov 08 Javascript
在antd4.0中Form使用initialValue操作
Nov 02 Javascript
JS数组方法some、every和find的使用详情
Oct 05 Javascript
关于JavaScript轮播图的实现
Nov 20 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静态新闻列表自动生成代码
2007/06/14 PHP
关于Appserv无法打开localhost问题的解决方法
2009/10/16 PHP
php 中文字符入库或显示乱码问题的解决方法
2010/04/12 PHP
Centos 6.5下PHP 5.3安装ffmpeg扩展的步骤详解
2017/03/02 PHP
PHPUnit测试私有属性和方法功能示例
2018/06/12 PHP
JS对外部文件的加载及对IFRMAME的加载的实现,当加载完成后,指定指向方法(方法回调)
2011/07/04 Javascript
40款非常棒的jQuery 插件和制作教程(系列二)
2011/11/02 Javascript
js 可拖动列表实现代码
2011/12/13 Javascript
seajs1.3.0源码解析之module依赖有序加载
2012/11/07 Javascript
javascript类型转换示例
2014/04/29 Javascript
jQuery标签替换函数replaceWith()的使用例子
2014/08/28 Javascript
jquery+javascript编写国籍控件
2015/02/12 Javascript
javascript点击按钮实现隐藏显示切换效果
2016/02/03 Javascript
js添加事件的通用方法推荐
2016/05/15 Javascript
BootStrap学习系列之Bootstrap Typeahead 组件实现百度下拉效果(续)
2016/07/07 Javascript
js从外部获取图片的实现方法
2016/08/05 Javascript
JS使用cookie实现只出现一次的广告代码效果
2017/04/22 Javascript
实战node静态文件服务器的示例代码
2018/03/08 Javascript
使用node打造自己的命令行工具方法教程
2018/03/26 Javascript
小程序实现页面顶部选项卡效果
2018/11/06 Javascript
js实现类似iphone的网页滑屏解锁功能示例【附源码下载】
2019/06/10 Javascript
Vue实现日历小插件
2019/06/26 Javascript
详解js创建对象的几种方式和对象方法
2021/03/01 Javascript
[01:02:25]2014 DOTA2华西杯精英邀请赛 5 24 iG VS DK
2014/05/26 DOTA
Python使用SocketServer模块编写基本服务器程序的教程
2016/07/12 Python
Tensorflow中使用tfrecord方式读取数据的方法
2018/06/19 Python
python 不以科学计数法输出的方法
2018/07/16 Python
python selenium执行所有测试用例并生成报告的方法
2019/02/13 Python
Gauss-Seidel迭代算法的Python实现详解
2019/06/29 Python
Pycharm2020.1安装中文语言插件的详细教程(不需要汉化)
2020/08/07 Python
CSS3解决移动页面上点击链接触发色块的问题
2016/06/03 HTML / CSS
中学教师自我鉴定
2014/02/07 职场文书
2015秋季小学开学寄语
2015/05/27 职场文书
大国崛起日本观后感
2015/06/02 职场文书
SQL Server内存机制浅探
2022/04/06 SQL Server
Go调用Rust方法及外部函数接口前置
2022/06/14 Golang