理解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 相关文章推荐
基于jquery的给文章加入关键字链接
Oct 26 Javascript
jQuery设置div一直在页面顶部显示的方法
Oct 24 Javascript
JavaScript改变CSS样式的方法汇总
May 07 Javascript
JavaScript中的replace()方法使用详解
Jun 06 Javascript
JQuery日历插件My97DatePicker日期范围限制
Jan 20 Javascript
jQuery.datatables.js插件用法及api实例详解
Oct 28 Javascript
mpvue 如何使用腾讯视频插件的方法
Jul 16 Javascript
webpack 静态资源集中输出的方法示例
Nov 09 Javascript
express 项目分层实践详解
Dec 10 Javascript
vue前后分离调起微信支付
Jul 29 Javascript
基于javascript实现移动端轮播图效果
Dec 21 Javascript
vue监听键盘事件的相关总结
Jan 29 Vue.js
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设计模式之装饰器模式实例详解
2018/02/07 PHP
PHP开发实现快递查询功能详解
2019/04/08 PHP
Yii框架通过请求组件处理get,post请求的方法分析
2019/09/03 PHP
PhpStorm的使用教程(本地运行PHP+远程开发+快捷键)
2020/03/26 PHP
Firefox下提示illegal character并出现乱码的原因
2010/03/25 Javascript
JavaScript Title、alt提示(Tips)实现源码解读
2010/12/12 Javascript
JavaScript数组对象赋值用法实例
2015/08/04 Javascript
解析如何利用iframe标签以及js制作时钟
2016/12/08 Javascript
JS验证input输入框(字母,数字,符号,中文)
2017/03/23 Javascript
vue2.0获取鼠标位置的方法
2018/09/13 Javascript
微信小程序发送短信验证码完整实例
2019/01/07 Javascript
[01:39](回顾)各路豪强针锋相对,几经鏖战四强产生
2014/07/01 DOTA
[02:55]含熏伴清风,风行者至宝、屠夫身心及典藏宝瓶二展示
2020/09/08 DOTA
python解析中国天气网的天气数据
2014/03/21 Python
python shell根据ip获取主机名代码示例
2017/11/25 Python
20个常用Python运维库和模块
2018/02/12 Python
Python基于更相减损术实现求解最大公约数的方法
2018/04/04 Python
对Python中数组的几种使用方法总结
2018/06/28 Python
python中的decorator的作用详解
2018/07/26 Python
Python版名片管理系统
2018/11/30 Python
python实现动态数组的示例代码
2019/07/15 Python
通过实例解析python描述符原理作用
2020/01/22 Python
Windows 下python3.8环境安装教程图文详解
2020/03/11 Python
python Timer 类使用介绍
2020/12/28 Python
python装饰器代码深入讲解
2021/03/01 Python
css 省略号 css3让多余的字符串消失并附加省略号的实现代码
2013/02/07 HTML / CSS
用Java语言将一个键盘输入的数字转化成中文输出
2013/01/25 面试题
会计与审计毕业生自荐信范文
2013/12/30 职场文书
2014年中秋节活动总结
2014/08/29 职场文书
庆祝三八妇女节标语
2014/10/09 职场文书
安全生产先进个人总结
2015/02/15 职场文书
企业法人代表证明书
2015/06/18 职场文书
在校学生证明格式
2015/06/24 职场文书
旅游安全责任协议书
2016/03/22 职场文书
Python中的程序流程控制语句
2022/02/24 Python
MySQL约束(创建表时的各种条件说明)
2022/06/21 MySQL