理解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 相关文章推荐
IE图片缓存document.execCommand("BackgroundImageCache",false,true)
Mar 01 Javascript
JavaScript异步编程:异步数据收集的具体方法
Aug 19 Javascript
扩展IE中一些不兼容的方法如contains、startWith等等
Jan 09 Javascript
Bootstrap每天必学之媒体对象
Nov 30 Javascript
JQuery中Ajax()的data参数类型实例分析
Dec 15 Javascript
JavaScript面向对象编写购物车功能
Aug 19 Javascript
JS实现类似51job上的地区选择效果示例
Nov 17 Javascript
深入理解vue Render函数
Jul 19 Javascript
使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件(推荐)
May 01 Javascript
vue-cli项目无法用本机IP访问的解决方法
Sep 20 Javascript
Vue安装浏览器开发工具的步骤详解
May 12 Javascript
vue 解决provide和inject响应的问题
Nov 12 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 信息采集程序代码
2009/03/17 PHP
用PHP的ob_start() 控制您的浏览器cache
2009/08/03 PHP
PHP开发框架kohana3 自定义路由设置示例
2014/07/14 PHP
dvwa+xampp搭建显示乱码的问题及解决方案
2015/08/23 PHP
php正则匹配文章中的远程图片地址并下载图片至本地
2015/09/29 PHP
理解php依赖注入和控制反转
2016/05/11 PHP
如何重写Laravel异常处理类详解
2020/12/20 PHP
CheckBox 如何实现全选?
2006/06/23 Javascript
JQUERY THICKBOX弹出层插件
2008/08/30 Javascript
js 父窗口控制子窗口的行为-打开,关闭,重定位,回复
2010/04/20 Javascript
javascript获得服务器端控件的ID的实现代码
2011/12/28 Javascript
Ext JS添加子组件的误区探讨
2013/06/28 Javascript
jQuery中prepend()方法用法实例
2014/12/25 Javascript
jQuery实现单击弹出Div层窗口效果(可关闭可拖动)
2015/09/19 Javascript
JavaScript动态设置div的样式的方法
2015/12/26 Javascript
JavaScript基础知识及常用方法总结
2016/01/10 Javascript
基于Bootstrap实现Material Design风格表单插件 附源码下载
2016/04/18 Javascript
AngularJS中的缓存使用
2017/01/11 Javascript
JavaScript限制在客户区可见范围的拖拽(解决scrollLeft和scrollTop的问题)(2)
2017/05/17 Javascript
详解webpack分包及异步加载套路
2017/06/29 Javascript
对vue中v-if的常见使用方法详解
2018/09/28 Javascript
vue-cli3 DllPlugin 提取公用库的方法
2019/04/24 Javascript
JS学习笔记之原型链和利用原型实现继承详解
2019/05/29 Javascript
Vue中函数防抖节流的理解及应用实现
2020/04/24 Javascript
Python操作MongoDB详解及实例
2017/05/18 Python
Diango + uwsgi + nginx项目部署的全过程(可外网访问)
2018/04/22 Python
基于Django框架的权限组件rbac实例讲解
2019/08/31 Python
Python钉钉报警及Zabbix集成钉钉报警的示例代码
2020/08/17 Python
Django配置Bootstrap, js实现过程详解
2020/10/13 Python
专业毕业生个性的自我评价
2013/10/03 职场文书
生产厂厂长岗位职责
2013/12/25 职场文书
安全资金保障制度
2014/01/23 职场文书
中国好声音华少广告词
2014/03/17 职场文书
2014年城管工作总结
2014/11/20 职场文书
工程服务质量承诺书
2015/04/29 职场文书
重阳节简报
2015/07/20 职场文书