理解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 String对象
Mar 09 Javascript
JQuery+Ajax实现数据查询、排序和分页功能
Sep 27 Javascript
基于JavaScript实现瀑布流效果(循环渐近)
Jan 27 Javascript
理解Javascript文件动态加载
Jan 29 Javascript
全面解析Javascript无限添加QQ好友原理
Jun 15 Javascript
Bootstrap基本插件学习笔记之折叠(22)
Dec 08 Javascript
教你快速搭建Node.Js服务器的方法教程
Mar 30 Javascript
浅谈JS函数节流防抖
Oct 18 Javascript
Bootbox将后台JSON数据填充Form表单的实例代码
Sep 10 Javascript
详解ES6 Promise对象then方法链式调用
Oct 20 Javascript
使用jQuery mobile NuGet让你的网站在移动设备上同样精彩
Jun 18 jQuery
angular8和ngrx8结合使用的步骤介绍
Dec 01 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 CURL模拟GET及POST函数代码
2010/04/25 PHP
yii2中使用Active Record模式的方法
2016/01/09 PHP
PHP使用curl函数发送Post请求的注意事项
2016/11/26 PHP
Yii2中添加全局函数的方法分析
2017/05/04 PHP
PHP策略模式定义与用法示例
2017/07/27 PHP
JavaScript 计算图片加载数量的代码
2011/01/01 Javascript
JavaScript/jQuery 表单美化插件小结
2012/02/14 Javascript
js中settimeout方法加参数
2014/02/28 Javascript
js登录弹出层特效
2014/03/07 Javascript
javascript获取checkbox复选框获取选中的选项
2014/08/12 Javascript
45个JavaScript编程注意事项、技巧大全
2015/02/11 Javascript
JavaScript中自带的 reduce()方法使用示例详解
2016/08/10 Javascript
基于Vuejs框架实现翻页组件
2020/06/29 Javascript
微信小程序之批量上传并压缩图片的实例代码
2018/07/05 Javascript
vue 使用自定义指令实现表单校验的方法
2018/08/28 Javascript
JavaScript惰性求值的一种实现方法示例
2019/01/11 Javascript
详解vue-cli中使用rem,vue自适应
2019/05/06 Javascript
[05:04]DOTA2上海特级锦标赛主赛事第二日TOP10
2016/03/04 DOTA
[00:12]DAC2018 天才少年转战三号位,他的SOLO是否仍如昔日般强大?
2018/04/06 DOTA
python发送邮件的实例代码(支持html、图片、附件)
2013/03/04 Python
python爬虫入门教程--优雅的HTTP库requests(二)
2017/05/25 Python
python+opencv实现动态物体识别
2018/01/09 Python
单利模式及python实现方式详解
2018/03/20 Python
python中的句柄操作的方法示例
2019/06/20 Python
对Django中内置的User模型实例详解
2019/08/16 Python
Python爬虫实现模拟点击动态页面
2020/03/05 Python
现代化办公人员工作的自我评价
2013/10/16 职场文书
模具设计与制造专业应届生求职信
2013/10/18 职场文书
视光学专业毕业生推荐信
2013/10/28 职场文书
光信息科学与技术专业职业生涯规划
2014/03/13 职场文书
四年级学生评语大全
2014/04/21 职场文书
文明礼仪演讲稿
2014/05/12 职场文书
励志演讲稿800字
2014/08/21 职场文书
镇党政领导班子民主生活会思想汇报
2014/10/11 职场文书
SpringBoot2零基础到精通之异常处理与web原生组件注入
2022/03/22 Java/Android
MySQL数据管理操作示例讲解
2022/12/24 MySQL