博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Javascript高级程序设计》读书笔记之bind函数详解
阅读量:6596 次
发布时间:2019-06-24

本文共 3527 字,大约阅读时间需要 11 分钟。

为什么需要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 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 || 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

你可能感兴趣的文章
IBM预通过R语言扩展 简化Watson系统的应用
查看>>
施耐德电气推出EcoStruxure架构与平台,开启转型之路
查看>>
NVIDIA与阿里云达成战略合作 共同拓展深度学习市场
查看>>
数据中心机房对环境的新要求
查看>>
一个页面标题和过滤输出的解决方案(下)
查看>>
JSP连接access数据库
查看>>
Loadrunner监控服务器资源
查看>>
Pandas:按条件进行行选择
查看>>
spring boot 自定义规则访问获取内部或者外部静态资源图片
查看>>
Object类
查看>>
【云计算的1024种玩法】使用 NAS 文件储存低价获得好磁盘性能
查看>>
Coding打坐
查看>>
springmvc + mybatis + ehcache + redis架构
查看>>
使用rollup打包库的一种基本配置
查看>>
Spring Boot 学习笔记(4):配置properties(2)
查看>>
VUE的生命周期
查看>>
ES 学习笔记-安装
查看>>
微信支付-H5支付绕过ip地址
查看>>
SpringCloud微服务实战
查看>>
Vue、Typescript 的项目实践
查看>>