理解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控制的遮罩层实例介绍
May 29 Javascript
Javascript改变CSS样式(局部和全局)
Dec 18 Javascript
window.showModalDialog()返回值的学习心得总结
Jan 07 Javascript
Javascript 运动中Offset的bug解决方案
Dec 24 Javascript
jquery ui resize 中border-box的bug修正
Apr 26 Javascript
javascript函数中的3个高级技巧
Sep 22 Javascript
微信小程序 HTTPS报错整理常见问题及解决方案
Dec 14 Javascript
Angular4学习笔记之根模块与Ng模块
Sep 09 Javascript
手机注册发送验证码倒计时的简单实例
Nov 15 Javascript
js input输入百分号保存数据库失败的解决方法
May 26 Javascript
Angular如何在应用初始化时运行代码详解
Jun 11 Javascript
vue封装一个简单的div框选时间的组件的方法
Jan 06 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
ThinkPHP使用Ueditor的方法详解
2016/05/20 PHP
php 使用fopen函数创建、打开文件详解及实例代码
2016/09/24 PHP
thinkPHP模板中for循环与switch语句用法示例
2016/11/30 PHP
php 访问oracle 存储过程实例详解
2017/01/08 PHP
PHP实现登录验证码校验功能
2018/05/17 PHP
使用Node.js实现一个简单的FastCGI服务器实例
2014/06/09 Javascript
如何屏蔽防止别的网站嵌入框架代码
2015/08/24 Javascript
JS 清除字符串数组中,重复元素的实现方法
2016/05/24 Javascript
jQuery实现微信长按识别二维码功能
2016/08/26 Javascript
jQuery实现的多张图无缝滚动效果【测试可用】
2016/09/12 Javascript
如何学JavaScript?前辈的经验之谈
2016/12/28 Javascript
JavaScript实现审核流程状态的动态显示进度条
2017/03/15 Javascript
详解vue2.0 transition 多个元素嵌套使用过渡
2017/06/19 Javascript
深入浅析Nodejs的Http模块
2017/06/20 NodeJs
JS检测window.open打开的窗口是否关闭
2017/06/25 Javascript
js学习总结_基于数据类型检测的四种方式(必看)
2017/07/04 Javascript
bootstrap插件treeview实现全选父节点下所有子节点和反选功能
2017/07/21 Javascript
微信小程序中setInterval的使用方法
2017/09/29 Javascript
React.Js添加与删除onScroll事件的方法详解
2017/11/03 Javascript
微信小程序scroll-view仿拼多多横向滑动滚动条
2020/04/21 Javascript
微信小程序的部署方法步骤
2018/09/04 Javascript
JS使用队列对数组排列,基数排序算法示例
2019/03/02 Javascript
利用JS响应式修改vue实现页面的input值
2019/09/02 Javascript
解决vue动态下拉菜单 有数据未反应的问题
2020/08/06 Javascript
[49:11]完美世界DOTA2联赛PWL S3 INK ICE vs DLG 第二场 12.20
2020/12/23 DOTA
Python的Django框架中的数据库配置指南
2015/07/17 Python
python 多进程共享全局变量之Manager()详解
2019/08/15 Python
python控制台实现tab补全和清屏的例子
2019/08/20 Python
使用批处理脚本自动生成并上传NuGet包(操作方法)
2019/11/19 Python
css3实例教程 一款纯css3实现的环形导航菜单
2014/10/20 HTML / CSS
有关九一八事变的演讲稿
2014/09/14 职场文书
美容院员工规章制度
2015/08/05 职场文书
小区物业管理2015年度工作总结
2015/10/22 职场文书
python使用XPath解析数据爬取起点小说网数据
2021/04/22 Python
详解PHP Swoole与TCP三次握手
2021/05/27 PHP
nginx location 带斜杠【 / 】与不带的区别
2022/04/13 Servers