理解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 判断 enter 事件
Feb 12 Javascript
锋利的jQuery 要点归纳(一) jQuery选择器
Mar 21 Javascript
基于jquery的lazy loader插件实现图片的延迟加载[简单使用]
May 07 Javascript
js 浏览本地文件夹系统示例代码
Oct 24 Javascript
node.js中的path.normalize方法使用说明
Dec 08 Javascript
JavaScript中实现Map的示例代码
Sep 09 Javascript
JS实现的N多简单无缝滚动代码(包含图文效果)
Nov 06 Javascript
node.js路径处理方法以及绝对路径详解
Mar 04 Javascript
老生常谈javascript的类型转换
Oct 12 Javascript
jQuery实现在HTML文档加载完毕后自动执行某个事件的方法
May 08 jQuery
详解TypeScript+Vue 插件 vue-class-component的使用总结
Feb 18 Javascript
微信小程序实现圆形进度条动画
Nov 18 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
IP138 IP地址查询小偷实现代码
2010/02/15 PHP
PHP 伪静态隐藏传递参数名的四种方法
2010/02/22 PHP
PHP使用GIFEncoder类生成的GIF动态图片验证码
2014/07/01 PHP
PHP+MySQL实现的简单投票系统实例
2016/02/24 PHP
PHP房贷计算器实例代码,等额本息,等额本金
2017/04/01 PHP
php生成0~1随机小数的方法(必看)
2017/04/05 PHP
多种方法实现JS动态添加事件
2013/11/01 Javascript
js/jQuery简单实现选项卡功能
2014/01/02 Javascript
jQuery遍历对象、数组、集合实例
2014/11/08 Javascript
javascript处理a标签超链接默认事件的方法
2015/06/29 Javascript
jQuery Real Person验证码插件防止表单自动提交
2015/11/06 Javascript
AngularJS ng-repeat数组有重复值的解决方法
2016/10/23 Javascript
jQuery EasyUI中的日期控件DateBox修改方法
2016/11/09 Javascript
javascript基础知识之html5轮播图实例讲解(44)
2017/02/17 Javascript
实战node静态文件服务器的示例代码
2018/03/08 Javascript
解决layui数据表格table的横向滚动条显示问题
2019/09/04 Javascript
js实现坦克大战游戏
2020/02/24 Javascript
JS 设计模式之:单例模式定义与实现方法浅析
2020/05/06 Javascript
[02:10]探秘浦东源深体育馆 DOTA2 Supermajor不见不散
2018/05/17 DOTA
使用Python导出Excel图表以及导出为图片的方法
2015/11/07 Python
windows10下安装TensorFlow Object Detection API的步骤
2019/06/13 Python
Python OpenCV之图片缩放的实现(cv2.resize)
2019/06/28 Python
python实时检测键盘输入函数的示例
2019/07/17 Python
python中的测试框架
2020/11/13 Python
优衣库澳大利亚官网:UNIQLO澳大利亚
2017/01/18 全球购物
WatchShop法国:英国排名第一的独立手表零售商
2020/02/17 全球购物
实习老师个人总结的自我评价
2013/09/28 职场文书
应届生个人求职信模板
2013/11/26 职场文书
幼教个人求职信范文
2013/12/02 职场文书
安全生产投入制度
2014/01/29 职场文书
成绩单公证书
2014/04/10 职场文书
党员查摆剖析材料
2014/10/10 职场文书
史上最牛的辞职信
2015/02/28 职场文书
暑期实践个人总结
2015/03/06 职场文书
团日活动总结格式
2015/05/11 职场文书
浅谈如何保证Mysql主从一致
2022/03/13 MySQL