深入理解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通用函数
May 09 Javascript
jQuery AnythingSlider滑动效果插件
Feb 07 Javascript
用javascript添加控件自定义属性解析
Nov 25 Javascript
jQuery实现单击按钮遮罩弹出对话框(仿天猫的删除对话框)
Apr 10 Javascript
node.js中的fs.renameSync方法使用说明
Dec 16 Javascript
jQuery带进度条全屏图片轮播特效代码分享
Jun 28 Javascript
jQuery简单注册和禁用全局事件的方法
Jul 25 Javascript
Jquery Easyui菜单组件Menu使用详解(15)
Dec 18 Javascript
详解利用 Vue.js 实现前后端分离的RBAC角色权限管理
Sep 15 Javascript
jquery获取file表单选择文件的路径、名字、大小、类型
Jan 18 jQuery
JS实现继承的几种常用方式示例
Jun 22 Javascript
详解Vue中CSS样式穿透问题
Sep 12 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
php5中类的学习
2008/03/28 PHP
PHP 配置open_basedir 让各虚拟站点独立运行
2009/11/12 PHP
Codeigniter的一些优秀特性总结
2015/01/21 PHP
Yii使用技巧大汇总
2015/12/29 PHP
Twig模板引擎用法入门教程
2016/01/20 PHP
表单的一些基本用法与技巧
2006/07/15 Javascript
js控制的回到页面顶端goTop的代码实现
2013/03/20 Javascript
基于javascipt-dom编程 table对象的使用
2013/04/22 Javascript
复制js对象方法(详解)
2013/07/08 Javascript
JS代码同步文本框内容的实例方法
2013/07/12 Javascript
jquery用get实现ajax在ie里面刷新不进入后台解决方法
2013/08/12 Javascript
JavaScript的MVVM库Vue.js入门学习笔记
2016/05/03 Javascript
基于jQuery的ajax方法封装
2016/07/14 Javascript
纯js三维数组实现三级联动效果
2017/02/07 Javascript
利用PM2部署node.js项目的方法教程
2017/05/10 Javascript
小程序跳转H5页面的方法步骤
2020/03/06 Javascript
vue结合el-upload实现腾讯云视频上传功能
2020/07/01 Javascript
JavaScript中arguments的使用方法详解
2020/12/20 Javascript
python3.4.3下逐行读入txt文本并去重的方法
2018/04/29 Python
python实现贪吃蛇小游戏
2020/03/21 Python
python利用wx实现界面按钮和按钮监听和字体改变的方法
2019/07/17 Python
windows10 pycharm下安装pyltp库和加载模型实现语义角色标注的示例代码
2020/05/07 Python
django ObjectDoesNotExist 和 DoesNotExist的用法
2020/07/09 Python
Python 创建TCP服务器的方法
2020/07/28 Python
工程师必须了解的LRU缓存淘汰算法以及python实现过程
2020/10/15 Python
UI自动化定位常用实现方法代码示例
2020/10/27 Python
canvas实现圆绘制的示例代码
2019/09/11 HTML / CSS
浅谈html5之sse服务器发送事件EventSource介绍
2017/08/28 HTML / CSS
中国跨境电商:Tomtop
2017/03/16 全球购物
公司端午节活动方案
2014/02/04 职场文书
大型演出策划方案
2014/05/28 职场文书
美容院合作经营协议书
2014/10/10 职场文书
2014年前台文员工作总结
2014/12/08 职场文书
圆明园观后感
2015/06/03 职场文书
go mod 安装依赖 unkown revision问题的解决方案
2021/05/06 Golang
什么是Python装饰器?如何定义和使用?
2022/04/11 Python