理解javascript中的Function.prototype.bind的方法


Posted in Javascript onFebruary 03, 2017

在初学Javascript时,我们也许不需要担心函数绑定的问题,但是当我们需要在另一个函数中保持上下文对象this时,就会遇到相应的问题了,我见过很多人处理这种问题都是先将this赋值给一个变量(比如self、_this、that等),尤其是var that = this是我见的最多的,这样当你改变环境之后就可以使用它。这些都是可以的,但是还有一种更好的、更专有的方法,那就是使用Function.prototype.bind,下面进行详尽的讲解。

第一部分:需要解决的问题

首先看下面的代码

var myObj = {

  specialFunction: function () {

  },

  anotherSpecialFunction: function () {

  },

  getAsyncData: function (cb) {
    cb();
  },

  render: function () {
this.getAsyncData(function () {
      this.specialFunction();
      this.anotherSpecialFunction();
    });
  }
};

myObj.render();

这里我希望创建一个对象,包含了前面两个普通的方法;第三个方法可以传递一个函数,传入的这个函数立即执行;最后一个方法会调用myObj对象的getAsyncData方法,这里使用了this,然后在getAsyncData方法中传入了一个函数,这个函数继续调用这个对象的前两个方法,仍使用了this,这时很多人实际上就可以看出问题所在了,将上述代码输入控制台,得到下面的结果:

TypeError: this.specialFunction is not a function

第二部分:问题剖析

在对象中render方法中的this的确是指向myObj对象的,所以我们可以通过this.getAsyncData来调用这个对象中的函数,但是当我们给其传递函数作为参数时,这里的this就指向了全局环境window了,因为全局环境中没有对象中的前两个方法,所以才会报错。

第三部分:解决问题的几种方式

所以我们需要做的就是正确调用对象中的前两个方法 ,很多人使用的方法便是首先在对象的环境中获取this赋值给另一个变量,这时就可以在后面的环境中调用了,如下所示:

render: function () {
    var that = this;
    this.getAsyncData(function () {
      that.specialFunction();
      that.anotherSpecialFunction();
    });
  }

虽然这种方法是可行的,但是使用Function.prototype.bind()会使代码更清晰、易懂,如下所示:

render: function () {

  this.getAsyncData(function () {

    this.specialFunction();

    this.anotherSpecialFunction();

  }.bind(this));

}

这里我们就成功地把this绑定到了环境中。

下面是另外一个简单的例子:

var foo = {
  x: 3
}

var bar = function(){
  console.log(this.x);
}

bar(); // undefined

var boundFunc = bar.bind(foo);

boundFunc(); // 3

下面的例子也是常见的:

this.x = 9;  // this refers to global "window" object here in the browser
var module = {
 x: 81,
 getX: function() { return this.x; }
};

module.getX(); // 81

var retrieveX = module.getX;
retrieveX();  
// returns 9 - The function gets invoked at the global scope

// Create a new function with 'this' bound to module
// New programmers might confuse the
// global var x with module's property x
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81

第四部分:浏览器支持

但是这个方法在IE8及以下是不被支持的,所以我们可以使用MDN提供的方法来使得IE低版本支持.bind()方法:

if (!Function.prototype.bind) {
 Function.prototype.bind = function (oThis) {
  if (typeof this !== "function") {
   // closest thing possible to the ECMAScript 5 internal IsCallable function
   throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
  }

  var aArgs = Array.prototype.slice.call(arguments, 1),
    fToBind = this,
    fNOP = function () {},
    fBound = function () {
     return fToBind.apply(this instanceof fNOP && oThis
                 ? this
                 : oThis,
                aArgs.concat(Array.prototype.slice.call(arguments)));
    };

  fNOP.prototype = this.prototype;
  fBound.prototype = new fNOP();

  return fBound;
 };
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery实现多级下拉菜单的实例代码
Oct 02 Javascript
关于两个jQuery(js)特效冲突的bug的解决办法
Sep 04 Javascript
jquery动态创建div与input的实例代码
Oct 12 Javascript
HTML Table 空白单元格补全的简单实现
Oct 13 Javascript
cocos creator Touch事件应用(触控选择多个子节点的实例)
Sep 10 Javascript
从零开始最小实现react服务器渲染详解
Jan 26 Javascript
mpvue小程序仿qq左滑置顶删除组件
Aug 03 Javascript
微信小程序用户信息encryptedData详解
Aug 24 Javascript
浅谈Angular单元测试总结
Mar 22 Javascript
小程序异步问题之多个网络请求依次执行并依次收集请求结果
May 05 Javascript
简述pm2常用命令集合及配置文件说明
May 30 Javascript
微信浏览器左上角返回按钮监听的实现
Mar 04 Javascript
JavaScript数组复制详解
Feb 02 #Javascript
常用jQuery选择器汇总
Feb 02 #Javascript
JavaScript优化以及前段开发小技巧
Feb 02 #Javascript
JavaScript字符集编码与解码详谈
Feb 02 #Javascript
JS实现购物车特效
Feb 02 #Javascript
jQuery实现复选框的全选和反选
Feb 02 #Javascript
jQuery制作图片旋转效果
Feb 02 #Javascript
You might like
用php+mysql一个名片库程序
2006/10/09 PHP
php获取mysql版本的几种方法小结
2008/03/25 PHP
jQuery+php实现ajax文件即时上传的详解
2013/06/17 PHP
JS中彻底删除JSON对象组成的数组中的元素
2020/09/22 PHP
Javascript中Array用法实例分析
2015/06/13 Javascript
基于javascript实现九宫格大转盘效果
2020/05/28 Javascript
jquery html5 视频播放控制代码
2016/11/06 Javascript
JS正则匹配中文的方法示例
2017/01/06 Javascript
Angular2开发——组件规划篇
2017/03/28 Javascript
微信小程序利用co处理异步流程的方法教程
2017/05/20 Javascript
自定义vue全局组件use使用、vuex的使用详解
2017/06/14 Javascript
谈谈对vue响应式数据更新的误解
2017/08/01 Javascript
bootstrap Table的一些小操作
2017/11/01 Javascript
jQuery实现炫丽的3d旋转星空效果
2018/07/04 jQuery
JavaScript学习笔记之数组基本操作示例
2019/01/09 Javascript
Vue退出登录时清空缓存的实现
2019/11/12 Javascript
js判断非127开头的IP地址的实例代码
2020/01/05 Javascript
[01:11:21]DOTA2-DPC中国联赛 正赛 Phoenix vs CDEC BO3 第三场 3月7日
2021/03/11 DOTA
python3批量删除豆瓣分组下的好友的实现代码
2016/06/07 Python
Python在for循环中更改list值的方法【推荐】
2018/08/17 Python
python树莓派红外反射传感器
2019/01/21 Python
Python提取特定时间段内数据的方法实例
2019/04/01 Python
解决Django一个表单对应多个按钮的问题
2019/07/18 Python
Python队列RabbitMQ 使用方法实例记录
2019/08/05 Python
python多项式拟合之np.polyfit 和 np.polyld详解
2020/02/18 Python
Python基于class()实现面向对象原理详解
2020/03/26 Python
赫里福德的一家乡村零售商店:Philip Morris & Son
2017/06/25 全球购物
do you have any Best Practice for testing
2016/06/04 面试题
毕业生的自我评价分享
2013/12/18 职场文书
法律进企业活动方案
2014/03/04 职场文书
勤奋学习演讲稿
2014/05/10 职场文书
关于公司年会的开幕词
2016/03/04 职场文书
Python基于Opencv识别两张相似图片
2021/04/25 Python
只用40行Python代码就能写出pdf转word小工具
2021/05/31 Python
Docker官方工具docker-registry案例演示
2022/04/13 Servers
python实现双链表
2022/05/25 Python