理解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.TreeView结合ASP.Net和数据库生成菜单导航条
Aug 27 Javascript
javascript smipleChart 简单图标类
Jan 12 Javascript
基于jQuery实现的Ajax 验证用户名是否存在的实现代码
Apr 06 Javascript
js实现图片旋转的三种方法
Apr 10 Javascript
EasyUi中的Combogrid 实现分页和动态搜索远程数据
Apr 01 Javascript
Bootstrap CSS布局之按钮
Dec 17 Javascript
layui弹出层效果实现代码
May 19 Javascript
jquery+css实现侧边导航栏效果
Jun 12 jQuery
Vue from-validate 表单验证的示例代码
Sep 26 Javascript
js处理包含中文的字符串实例
Oct 11 Javascript
使用Node.js实现一个多人游戏服务器引擎
Mar 13 Javascript
解决Layui中layer报错的问题
Sep 03 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+dbfile开发小型留言本
2006/10/09 PHP
CentOS 6.3下安装PHP xcache扩展模块笔记
2014/09/10 PHP
PHP间隔一段时间执行代码的方法
2014/12/02 PHP
PHP使用JSON和将json还原成数组
2015/02/12 PHP
Yii2框架数据库简单的增删改查语法小结
2016/08/31 PHP
PHP静态延迟绑定和普通静态效率的对比
2017/10/20 PHP
Ajax中的JSON格式与php传输过程全面解析
2017/11/14 PHP
对 lightbox JS 图片控件进行了一下改造, 使其他支持复杂的图片说明
2010/03/20 Javascript
Jquery Select操作方法集合脚本之家特别版
2010/05/17 Javascript
为JavaScript提供睡眠功能(sleep) 自编译JS引擎
2010/08/16 Javascript
Pro JavaScript Techniques学习笔记
2010/12/28 Javascript
jQuery实战之品牌展示列表效果
2011/04/10 Javascript
js两行代码按指定格式输出日期时间
2011/10/21 Javascript
javascript向后台传送相同属性的参数即数组参数
2014/02/17 Javascript
web前端开发JQuery常用实例代码片段(50个)
2015/08/28 Javascript
深入浅析JavaScript字符串操作方法 slice、substr、substring及其IE兼容性
2015/12/16 Javascript
微信小程序开发之视频播放器 Video 弹幕 弹幕颜色自定义实例
2016/12/08 Javascript
JS获取填报扩展单元格控件的值的解决办法
2017/07/14 Javascript
JS高阶函数原理与用法实例分析
2019/01/15 Javascript
JS实现前端动态分页码代码实例
2020/06/02 Javascript
vue自动添加浏览器兼容前后缀操作
2020/08/13 Javascript
ant-design-vue 时间选择器赋值默认时间的操作
2020/10/27 Javascript
[03:03]DOTA2 2017国际邀请赛开幕战队入场仪式
2017/08/09 DOTA
跟老齐学Python之Python文档
2014/10/10 Python
安装python时MySQLdb报错的问题描述及解决方法
2018/03/20 Python
Python实现字符型图片验证码识别完整过程详解
2019/05/10 Python
python算法与数据结构之冒泡排序实例详解
2019/06/22 Python
利用python如何实现猫捉老鼠小游戏
2020/12/04 Python
html5教程制作简单画板代码分享
2013/12/04 HTML / CSS
护理专业毕业生推荐信
2013/10/31 职场文书
函授毕业生的自我鉴定
2013/11/26 职场文书
车间操作工岗位职责
2013/12/19 职场文书
注册资产评估专业求职信
2014/07/16 职场文书
如何制定销售人员薪酬制度?
2019/07/09 职场文书
Python面向对象之成员相关知识总结
2021/06/24 Python
php实例化对象的实例方法
2021/11/17 PHP