理解javascript中的Function.prototype.bind的方法

在初学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;
 };
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Javascript中的 “&” 和 “|” 详解

    一.前言: 在文章开始之前,先出几个题目给大家看看: var num1 = 1 & 0; console.log(num1); // 0 var num2 = 'string' & 1; console.log(num2); // 0 var num3 = true & 1; console.log(num3); // 1 var num4 = undefined | false; console.log(num4); // 0 var num5 = undefined | tru

  • Javascript基础回顾之(三) js面向对象

    本来是要继续由浅入深表达式系列最后一篇的,但是最近团队突然就忙起来了,从来没有过的忙!不过喜欢表达式的朋友请放心,已经在写了:) 在工作当中发现大家对Javascript的一些基本原理普遍存在这里或者那里的一知半解,所以决定先花一些时间整理一下这些基础知识和大家分享. 后面会附上培训用的PPT.刚开始是打算写一篇的,但是后来写着写着就发现越来越多,所以决定还是写一个系列吧.本系列所有内容都是涉及Javascript基础的,没有时髦的玩意儿,但是我相信这些基础的东西会有助于你理解那些有趣的东西的.

  • JavaScript数组复制详解

    前面的话   前面的博文中介绍了对象拷贝,本文将详细介绍数组复制 push function copyArray(arr){ var result = []; for(var i = 0; i < arr.length; i++){ result.push(arr[i]); } return result; } var obj1=[1,2,3]; var obj2=copyArray(obj1); console.log(obj1); //[1,2,3] console.log(obj2); /

  • JavaScript Date 知识浅析

    Date函数 new Date() Date 对象会自动把当前日期和时间保存为其初始值. date.getDate() 从 Date 对象返回一个月中的某一天 (1 ~ 31). date.getDay() 从 Date 对象返回一周中的某一天 (0 ~ 6).周日是0. date.getMonth() 从 Date 对象返回月份 (0 ~ 11). date.getFullYear() 从 Date 对象以四位数字返回年份 date.getHours() 返回 Date 对象的小时 (0 ~

  • JavaScript实现时钟滴答声效果

    下面一段代码给大家分享js实现时钟滴答声功能,具体代码如下所示: <!DOCTYPE html> <html> <head> <meta charset="utf8"> <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1"> <meta name="keywords" content=&qu

  • javascript判断回文数详解及实现代码

    javascript判断回文数 概要: 回文"是指正读反读都能读通的句子,它是古今中外都有的一种修辞方式和文字游戏,如"我为人人,人人为我"等.在数学中也有这样一类数字有这样的特征,成为回文数(palindrome number). 设n是一任意自然数.若将n的各位数字反向排列所得自然数n1与n相等,则称n为一回文数.例如,若n=1234321,则称n为一回文数:但若n=1234567,则n不是回文数. 注意: 1.偶数个的数字也有回文数124421     2.小数没有回文

  • Javascript中数组去重与拍平的方法示例

    数组的判断 在说如何进行数组的去重和拍平之前,先说一下怎么判断数组,因为要进行数组的处理当然要先判断下传过来的数据是不是数组. 首先我们都知道js的数据类型只有5种,分别是Undefined.Null.Boolean.Number和String,数组只是一个对象,用typeof([])返回的结果知识一个Object的字符串,因此我们需要通过其他手段来判断它,这里就说两种方法. 第一种用instenceof方法 instanceof是ES5提供的一个方法,它可以用来判断实例是否是某个类的实例,例如

  • Javascript中 带名 匿名 箭头函数的重要区别(推荐)

    带名函数是指函数显示地给出了一个名字的函数,function abs(x){}.匿名函数是指函数只带有function这个关键字,而没有像abs这种函数名称的函数,如function(){}.ES6标准新增了一种新的函数:Arrow Function(箭头函数)箭头函数表面上相当于匿名函数,并且简化了函数定义.它们各自的区别是什么呢? 1 带名和匿名函数的区别 区别:匿名函数需要讲地址赋值给另一个变量let a,然后再用a来调用函数:而带名函数因为显示地给出了函数名称,所以可以直接用这个函数名称

  • Javascript基础回顾之(一) 类型

    本来是要继续由浅入深表达式系列最后一篇的,但是最近团队突然就忙起来了,从来没有过的忙!不过喜欢表达式的朋友请放心,已经在写了:) 在工作当中发现大家对Javascript的一些基本原理普遍存在这里或者那里的一知半解,所以决定先花一些时间整理一下这些基础知识和大家分享. 刚开始是打算写一篇的,但是后来写着写着就发现越来越多,所以决定还是写一个系列吧.本系列所有内容都是涉及Javascript基础的,没有时髦的玩意儿,但是我相信这些基础的东西会有助于你理解那些有趣的东西的. Javascript基础

  • 浅谈javascript中的 “ && ” 和 “ || ”

    有时候,我们会在jQuery框架或者其他js插件中发现里面有很多 " && " 和 " || ",那么这两个标识到底是什么含义?怎么使用?我觉得还是有必要稍微深究一下. 一.原理: && 操作符特点:逻辑运算表达式中只要一个是false就取false的值,都是true取后面,都是false取前面. || 操作符特点:逻辑运算表达式中只要一个是true就取true的值,都是true取前面,都是false取后面. 在js逻辑运算中,我们知

  • JavaScript基础之AJAX简单的小demo

    AJAX AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX 不是新的编程语言,而是一种使用现有标准的新方法. AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下. function prepareForms() { for(var j=0 ; j<document.forms.length ; j++){ var this_forms = document.forms[j]; rese

随机推荐