为什么需要bind

var name = "The Window";
var object = {name: "My Object",getNameFunc: function () {return function () {return this.name;}}
};alert(object.getNameFunc()()); //"The Window"

object.getNameFunc()返回一个匿名函数,在全局环境调用该函数,this指向的全局对象

解决这一问题,可以像下面这样,将匿名函数外部作用域中this对象保存在闭包能够访问到的变量中

var name = "The Window";
var object = {name: "My Object",getNameFunc: function () {var that = this;return function () {return that.name;}}
};alert(object.getNameFunc()()); //"My Object"

上述解决方法需要修改对象的方法,如果不能修改原对象的方法,该如何做呢?

这时,我们可以像下面这样,使用apply或call方法指定函数的作用域

var name = "The Window";
var object = {name: "My Object",getNameFunc: function () {return function () {return this.name;}}
};
var func=object.getNameFunc();
alert(func.apply(object)); //"My Object"

通过apply、call,已经可以输出预期的My Object

但是,每次调用时都需要以func.apply(object)的形式调用,这不是很怪么

理想的调用方式,当然是在通过某种处理后,之后可以以func()形式调用,像下面这样

var name = "The Window";
var object = {name: "My Object",getNameFunc: function () {return function () {return this.name;}}
};
var func=object.getNameFunc();
func=func.bind(object);
alert(func()); //"My Object"

ECMAScript 5中的bind

ECMAScript 5定了了bind方法,这个方法会创建一个函数实例,其this值会被绑定到传给bind函数的值,上面代码给出了bind函数的使用方式,再给一个简单示例。

window.color="red";
var o={color:"blue"};
function sayColor(){alert(this.color);
}var func=sayColor.bind(o);
func();//"blue"

虽然大部分浏览器中已经可以使用ECMAScript 5定义的这个方法,但在少数不支持的浏览器中你还是会遇到兼容性问题,这是如何处理呢?

通过上面apply、call方法使用示例 ,可以像下面这样提供一个解决方案

Function.prototype.bind=Function.prototype.bind||function(context){var self=this;return function(){return self.apply(context,arguments);}}

Prototype.js中的bind

// The .bind method from Prototype.js
Function.prototype.bind = function(){ var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); return function(){ return fn.apply(object, args.concat(Array.prototype.slice.call(arguments))); };
};

上述代码中,

args=Array.prototype.slice.call(arguments)将调用bind函数时参数集合arguments转换为数组array

object=args.shift()将args数组第一个元素取出作为当前对象

匿名函数中,调用args.concat(Array.prototype.slice.call(arguments))是为了将调用匿名函数时传入的参数与调用bind时参数合并成一个参数数组

以一个调用示例来看上述过程

var obj = { x: 'prop x' };
//args = Array.prototype.slice.call(arguments)后args = [obj, 12, 23 ]//object=args.shift()后,args =[12, 23] ,object =obj

var boundExample = example.bind(obj, 12, 23); 
boundExample(36, 49); // arguments => 36, 49 ,调用args.concat(Array.prototype.slice.call(arguments))后,arguments that our example() function receives => [12, 23, 36, 49]

Firefox中的bind

if (!Function.prototype.bind) {Function.prototype.bind = function (oThis) {if (typeof this !== "function") {// closest thing possible to the ECMAScript 5 internal IsCallable functionthrow 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 || window,aArgs.concat(Array.prototype.slice.call(arguments)));};fNOP.prototype = this.prototype;fBound.prototype = new fNOP();return fBound;};
}

Firefox为bind提供了一个兼容实现,主要代码与prototype.js中实现类似,不再逐句解释了

转载于:https://www.cnblogs.com/GongQi/p/4041460.html

《Javascript高级程序设计》读书笔记之bind函数详解相关推荐

  1. javascript高级程序设计读书笔记----引用类型

    Array类型. ECMAScript数组的每一项可以保存任何类型的数据. 数组大小是可以动态调整的. 创建数组第一种基本方式方式: 使用Array构造函数 var colors = new Arra ...

  2. javascript高级程序设计读书笔记2

    <!DOCTYPE HTML>//这个网页的文档类型,这个是html5的写法 Bootstrap使用的某些HTML元素和CSS属性需要文档类型为HTML5 doctype.因此这一文档类型 ...

  3. JavaScript高级程序设计-读书笔记(6)

    第20章 JSON JSON是一个轻量级的数据格式,可以简化表示复杂数据结构的工作量 JSON的语法可以表示一下三种类型的值 l        简单值:使用与JavaScript相同的语法,可以在JS ...

  4. JavaScript高级程序设计读书笔记(一)

    第一章 总结: JavaScript是一种专为与网页交互设计的脚本语言. 由三个不同的部分组成: ECMAScript, 由ECMA-262定义,提供核心语言功能: DOM(文件对象模型),提供访问和 ...

  5. Javascript高级程序设计--读书笔记--第八章BOM

    BOM(browser object model 浏览器对象模型) BOM的核心对象是window,它表示浏览器的一个实例.在浏览器钟,window对象有双重角色,它既是通过javascript 访问 ...

  6. JavaScript高级程序设计读书笔记(第8章BOM之location对象查询字符串参数)

    为什么80%的码农都做不了架构师?>>> location对象查询字符串参数 //location.search返回从问号到URL末尾的所有内容function getQuerySt ...

  7. JavaScript高级程序设计读书笔记(第6章面向对象的程序设计之创建对象)

    2019独角兽企业重金招聘Python工程师标准>>> 面向对象语言都有"类"的概念,而通过类可以创建任意多个具有相同属性和方法的对象. JS中没有"类 ...

  8. javascript高级程序设计读书笔记1

    浮点数虽然精度很高,但在实际计算中的精度可能不如整数.比如0.1+0.2并不等于0.3,而是0.3000000000000004,所以把浮点数的计算结果当做判断条件会产生失误,这是基于IEEE754数 ...

  9. JavaScript高级程序设计读书笔记(第5章引用类型之Array类型)

    为什么80%的码农都做不了架构师?>>> 1.数组长度 //lenth会自动更新 var arr=["black","red","g ...

最新文章

  1. pt-tools系统:pt-kill 实战
  2. GPT-2大战GPT-3:OpenAI内部的一场终极对决
  3. js中获取事件对象的方法小结
  4. 快速安装本地yum源
  5. NOIP2007 树网的核 [BZOJ2282][Sdoi2011]消防
  6. Ubuntu 默认输入法切换(更改)--- 解决中文输入问题
  7. boost::fusion::as_deque用法的测试程序
  8. 面试官:为什么 wait() 方法需要写在循环里?
  9. vue 项目中当访问路由不存在的时候默认访问404页面
  10. python-study-09
  11. 三网融合:不给安全营造“盗梦空间”
  12. varbinary mysql_MySQL中的数据类型binary和varbinary详解
  13. JS项目(制作随机选号页面)
  14. Go语言 windows环境安装
  15. 计算机网络应用答题卡,计算机软考中高级答题卡填涂注意事项
  16. 解方程(equation)
  17. t450加固态硬盘教程_T450能加固态硬盘么 是什么接口
  18. python微信api_用Python实现微信公众号API素材库图文消息抓取
  19. php mkdir 失败原因,php mkdir 失败怎么办
  20. BIM模型轻量化的方法总结

热门文章

  1. python2执行程序内存溢出导致被killed的问题因果分析
  2. linux知识点记录二
  3. 要管理组策略 您必须以域用户账户登录此计算机,组策略设置:使普通用户登陆域控制器的电脑...
  4. linux中没有semanagea安装包,如何使用semanage管理SELinux安全策略
  5. 正则表达式中的字符类
  6. php 7.2 兼容5.5吗,PHP5.5至PHP7.2 新特性整理
  7. Angular介绍、安装Angular Cli、创建Angular项目入门教程
  8. 几百个Android开源个性化控件、工具库、项目、开发工具快快收藏
  9. Dubbo环境搭建-管理控制台dubbo-admin实现服务监控
  10. Java未将对象引用设置到对象的实例