理解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 相关文章推荐
JavaScript 滚轮事件使用说明
Mar 07 Javascript
jQuery中extend函数详解
Jul 13 Javascript
HTML5 Shiv完美解决IE(IE6/IE7/IE8)不兼容HTML5标签的方法
Nov 25 Javascript
详解javascript中原始数据类型Null和Undefined
Dec 17 Javascript
JavaScript+html5 canvas绘制的圆弧荡秋千效果完整实例
Jan 26 Javascript
通过正则表达式获取url中参数的简单实现
Jun 07 Javascript
js微信分享API
Oct 11 Javascript
js仿新浪微博消息发布功能
Feb 17 Javascript
分享Bootstrap简单表格、表单、登录页面
Aug 04 Javascript
two.js之实现动画效果示例
Nov 06 Javascript
Vue父子组建的简单通信之控制开关Switch的实现
Jun 04 Javascript
vue路由导航守卫和请求拦截以及基于node的token认证的方法
Apr 07 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基于str_pad实现卡号不足位数自动补0的方法
2014/11/12 PHP
Zend Framework实现多文件上传功能实例
2016/03/21 PHP
Laravel5中防止XSS跨站攻击的方法
2016/10/10 PHP
js版本A*寻路算法
2006/12/22 Javascript
Javascript 学习书 推荐
2009/06/13 Javascript
jQuery 创建Dom元素
2010/05/07 Javascript
JQuery从头学起第三讲
2010/07/06 Javascript
JavaScript自定义事件介绍
2013/08/29 Javascript
HTML页面弹出居中可拖拽的自定义窗口层
2014/05/07 Javascript
原生js实现复制对象、扩展对象 类似jquery中的extend()方法
2014/08/30 Javascript
js实现鼠标悬停图片上时滚动文字说明的方法
2015/02/17 Javascript
javascript实现控制的多级下拉菜单
2015/07/05 Javascript
confirm确认对话框的实现方法总结
2016/06/17 Javascript
Vue2.0实现组件数据的双向绑定问题
2018/03/06 Javascript
jQuery实现动态加载(按需加载)javascript文件的方法分析
2019/05/31 jQuery
JavaScript实现五子棋游戏的方法详解
2019/07/08 Javascript
js 判断当前时间是否处于某个一个时间段内
2019/09/19 Javascript
微信小程序实现电子签名功能
2020/07/29 Javascript
微信小程序实现点击生成随机验证码
2020/09/09 Javascript
Python创建xml的方法
2015/03/10 Python
Python用户推荐系统曼哈顿算法实现完整代码
2017/12/01 Python
微信跳一跳小游戏python脚本
2018/01/05 Python
Python subprocess模块功能与常见用法实例详解
2018/06/28 Python
对python条件表达式的四种实现方法小结
2019/01/30 Python
Python读写文件基础知识点
2019/06/10 Python
详解CSS3 用border写 空心三角箭头 (两种写法)
2017/09/29 HTML / CSS
STUBHUB日本:购买和出售全球活动门票
2018/07/01 全球购物
Ibatis中如何提高SQL Map的性能
2013/05/11 面试题
实习单位推荐信范文
2013/11/27 职场文书
副处级干部考察材料
2014/05/17 职场文书
专题组织生活会方案
2014/06/15 职场文书
新农村建设汇报材料
2014/08/15 职场文书
大学生预备党员自我评价
2015/03/04 职场文书
单位更名证明
2015/06/18 职场文书
Python中rapidjson参数校验实现
2021/07/25 Python
SQL Server表分区降低运维和维护成本
2022/04/08 SQL Server