理解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 相关文章推荐
离开当前页面前使用js判断条件提示是否要离开页面
May 02 Javascript
JavaScript实现在数组中查找不同顺序排列的字符串
Sep 26 Javascript
Javascript中的apply()方法浅析
Mar 15 Javascript
JavaScript学习笔记之数组随机排序
Mar 23 Javascript
JavaScript头像上传插件源码分享
Mar 29 Javascript
JS中使用FormData上传文件、图片的方法
Aug 07 Javascript
AngularJs Dependency Injection(DI,依赖注入)
Sep 02 Javascript
jQuery实现页面下拉100像素出现悬浮窗口的方法
Sep 05 Javascript
微信小程序  生命周期详解
Oct 27 Javascript
JS实现字符串中去除指定子字符串方法分析
May 17 Javascript
Vue搭建后台系统需要注意的问题
Nov 08 Javascript
JS实现盒子拖拽效果
Feb 06 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和Java的des加密解密代码分享
2014/06/26 PHP
Yii框架调试心得--在页面输出执行sql语句
2014/12/25 PHP
js 静态动态成员 and 信息的封装和隐藏
2011/05/29 Javascript
仿百度的关键词匹配搜索示例
2013/09/25 Javascript
将中国标准时间转换成标准格式的代码
2014/03/20 Javascript
JavaScript实现列出数组中最长的连续数
2014/12/29 Javascript
JavaScript SHA512&SHA256加密算法详解
2015/08/11 Javascript
简单纯js实现点击切换TAB标签实例
2015/08/23 Javascript
JS+CSS实现滑动切换tab菜单效果
2015/08/25 Javascript
javascirpt实现2个iframe之间传值的方法
2016/06/30 Javascript
Node.js测试中的Mock文件系统详解
2016/11/21 Javascript
jQuery密码强度验证控件使用详解
2017/01/05 Javascript
荐书|您有一份JavaScript书单待签收
2017/07/21 Javascript
微信小程序之前台循环数据绑定
2017/08/18 Javascript
利用Vue2.x开发实现JSON树的方法
2018/01/04 Javascript
layui 实现table翻页滚动条位置保持不变的例子
2019/09/05 Javascript
vue ssr+koa2构建服务端渲染的示例代码
2020/03/23 Javascript
Python3.x版本中新的字符串格式化方法
2015/04/24 Python
Python执行时间的计算方法小结
2017/03/17 Python
Python递归实现汉诺塔算法示例
2018/03/19 Python
pycharm双击无响应(打不开问题解决办法)
2020/01/10 Python
pytorch forward两个参数实例
2020/01/17 Python
如何通过python实现人脸识别验证
2020/01/17 Python
PyQT5速成教程之Qt Designer介绍与入门
2020/11/02 Python
Python远程linux执行命令实现
2020/11/11 Python
澳大利亚网上书店:QBD
2021/01/09 全球购物
小学教师岗位职责
2013/11/25 职场文书
竞选文艺委员演讲稿
2014/04/28 职场文书
创业培训计划书
2014/05/03 职场文书
建筑结构施工求职信
2014/07/11 职场文书
幼师中班个人总结
2015/02/12 职场文书
情侣之间的道歉短信
2015/05/12 职场文书
2015年会计工作总结范文
2015/05/26 职场文书
选对餐饮营销策略,营业额才会上涨
2019/08/27 职场文书
CocosCreator ScrollView优化系列之分帧加载
2021/04/14 Python
Valheim服务器 Mod修改安装教程 【ValheimPlus】
2022/12/24 Servers