理解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 ajax请求实例深入解析
Nov 26 Javascript
JavaScript词法作用域与调用对象深入理解
Nov 29 Javascript
HTML复选框和单选框 checkbox和radio事件介绍
Dec 12 Javascript
jquery实现控制表格行高亮实例
Jun 05 Javascript
jquery如何判断某元素是否具备指定的样式
Nov 05 Javascript
AngularJS入门教程之AngularJS模型
Apr 18 Javascript
jQuery移除或禁用html元素点击事件常用方法小结
Feb 10 Javascript
利用node.js实现自动生成前端项目组件的方法详解
Jul 12 Javascript
angularjs下ng-repeat点击元素改变样式的实现方法
Sep 12 Javascript
vue返回上一页面时回到原先滚动的位置的方法
Dec 20 Javascript
easyUI 实现的后台分页与前台显示功能示例
Jun 01 Javascript
详解JavaScript原型与原型链
Nov 16 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和ACCESS写聊天室(二)
2006/10/09 PHP
fleaphp常用方法分页之Pager使用方法
2011/04/23 PHP
thinkPHP框架RBAC实现原理分析
2019/02/01 PHP
firebug的一个有趣现象介绍
2011/11/30 Javascript
用客户端js实现带省略号的分页
2013/04/27 Javascript
javascript自定义右键弹出菜单实现方法
2015/05/25 Javascript
JavaScript实现节点的删除与序号重建实例
2015/08/05 Javascript
jquery实现图片水平滚动效果代码分享
2015/08/26 Javascript
js实现多张图片延迟加载效果
2017/07/17 Javascript
微信小程序解析富文本过程详解
2019/07/13 Javascript
es6中Promise 对象基本功能与用法实例分析
2020/02/23 Javascript
JavaScript数组排序的六种常见算法总结
2020/08/18 Javascript
vue实现图片裁剪后上传
2020/12/16 Vue.js
[01:02:04]EG vs Liquid 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.23
2019/09/05 DOTA
深入解析Python中的lambda表达式的用法
2015/08/28 Python
Python实现求数列和的方法示例
2018/01/12 Python
基于python 处理中文路径的终极解决方法
2018/04/12 Python
python中itertools模块zip_longest函数详解
2018/06/12 Python
python中redis查看剩余过期时间及用正则通配符批量删除key的方法
2018/07/30 Python
Selenium的使用详解
2018/10/19 Python
解决python线程卡死的问题
2019/02/18 Python
PyQt5下拉式复选框QComboCheckBox的实例
2019/06/25 Python
对Python生成器、装饰器、递归的使用详解
2019/07/19 Python
Python 转换RGB颜色值的示例代码
2019/10/13 Python
Python for循环搭配else常见问题解决
2020/02/11 Python
python实现TCP文件传输
2020/03/20 Python
python+selenium 简易地疫情信息自动打卡签到功能的实现代码
2020/08/22 Python
python多线程和多进程关系详解
2020/12/14 Python
CSS3中的@keyframes关键帧动画的选择器绑定
2016/06/13 HTML / CSS
英国儿童家具专卖店:GLTC
2016/09/24 全球购物
美国知名平价彩妆品牌:e.l.f. Cosmetics
2017/11/20 全球购物
师范应届毕业生自荐信
2013/11/18 职场文书
法人代表委托书
2014/04/04 职场文书
化工专业自荐书
2014/06/16 职场文书
购房协议书范本
2014/10/02 职场文书
Python if else条件语句形式详解
2022/03/24 Python