理解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 弹出框口并返回值的两种常用方法
Dec 30 Javascript
Javascript的常规数组和关联数组对比小结
May 24 Javascript
图片延迟加载的实现代码(模仿懒惰)
Mar 29 Javascript
jquery使用append(content)方法注意事项分享
Jan 06 Javascript
js操作cookie保存浏览记录的方法
Dec 25 Javascript
JavaScript制作简单分页插件
Sep 11 Javascript
Angular排序实例详解
Jun 28 Javascript
Angularjs 手写日历的实现代码(不用插件)
Oct 18 Javascript
使用vue 国际化i18n 实现多实现语言切换功能
Oct 11 Javascript
Vue监听页面刷新和关闭功能
Jun 20 Javascript
通过实例了解Render Props回调地狱解决方案
Nov 04 Javascript
vue ant design 封装弹窗表单的使用
Jun 01 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 number_format() 函数通过千位分组来格式化数字的实现代码
2013/08/06 PHP
PHP取整函数:ceil,floor,round,intval的区别详细解析
2013/08/31 PHP
如何让CI框架支持service层
2014/10/29 PHP
php输入数据统一类实例
2015/02/23 PHP
php使用curl打开https网站的方法
2015/06/17 PHP
详解PHP对象的串行化与反串行化
2016/01/24 PHP
ThinkPHP简单使用memcache缓存的方法
2016/11/15 PHP
JS字符串累加Array不一定比字符串累加快(根据电脑配置)
2012/05/14 Javascript
SOSO地图API使用(一)在地图上画圆实现思路与代码
2013/01/15 Javascript
jQuery+CSS 半开折叠效果原理及代码(自写)
2013/03/04 Javascript
js获取URL的参数的方法(getQueryString)示例
2013/09/29 Javascript
vue.js实现用户评论、登录、注册、及修改信息功能
2020/05/30 Javascript
node.js用fs.rename强制重命名或移动文件夹的方法
2017/12/27 Javascript
Vue中qs插件的使用详解
2020/02/07 Javascript
在react-antd中弹出层form内容传递给父组件的操作
2020/10/24 Javascript
详解Python中的相对导入和绝对导入
2017/01/06 Python
python实现QQ邮箱/163邮箱的邮件发送
2019/01/22 Python
深入浅析Python 中 is 语法带来的误解
2019/05/07 Python
详解Python 中sys.stdin.readline()的用法
2019/09/12 Python
Python实现把类当做字典来访问
2019/12/16 Python
python要安装在哪个盘
2020/06/15 Python
纯HTML+CSS3制作导航菜单(附源码)
2013/04/24 HTML / CSS
Turnbull & Asser官网:英国皇室御用的顶级定制衬衫
2019/01/31 全球购物
美国排名第一的泳池用品直接来源:In The Swim
2019/09/23 全球购物
大学生职业生涯规划范文——找准自我,定位人生
2014/01/23 职场文书
城市精细化管理实施方案
2014/03/04 职场文书
党风廉政承诺书
2014/03/27 职场文书
房屋出售协议书
2014/04/10 职场文书
店铺转让协议书(2014版)
2014/09/23 职场文书
五年级学生期末评语
2014/12/26 职场文书
2015年毕业生个人自荐书
2015/03/24 职场文书
企业百日安全活动总结
2015/05/07 职场文书
2015年污水处理厂工作总结
2015/05/26 职场文书
60句有关成长的名言
2019/09/04 职场文书
Python基础详解之邮件处理
2021/04/28 Python
javascript遍历对象的五种方式实例代码
2021/10/24 Javascript