Function.prototype.bind、call与apply
学习Function.prototype.bind、call与apply时,看到一篇博客,学到一些内容,但由于博客时间太久,根据官方文档对内容进行一些修正;下文为修正过内容
前言
前段时间面试遇见一题,题目内容大概是
functionParent() {this.prop = 'parent';
}
Parent.prototype.get = function() {
alert(this.prop);
};
Parent.prototype.show = function() {
setTimeout(this.get, 100);
};
var child = new Parent();
child.show(); // ?
分析
上述题目考察的是this的指向性这个经典问题。
众所周知,setTimeout是window对象的一个属性,主要起到延迟给定函数执行的作用。setTimeout(fn, delay),因此this.get的这个this指向的是window对象,但是我们并没用在window对象上定义相应的get函数,所以会报错,而不是调用构造函数Parent的原型中的get方法。
怎么改?
经过上面的分析,我们知道setTimeout(this.get, 100)会报错,但是如果我们想正常调用并且alert出正确的值,应该怎么改?
改动的原理很明确,就是将setTimeout中的this指向Parent.prototype,但是单纯的将this.get改成Parent.prototype.get仍然没有alert出真正的parent,而是undefined,原理仍然是原型中的get方法在通过实例对象child调用时内部的this仍然指向window对象。所以我们只能换种思路解决了
思路1
Parent.prototype.show = function(){var that = this;
setTimeout(this.get.call(that), 100);
}
这种方法在很多框架中经常使用,即先存储this默认指向的作用域,然后改变函数内部绑定的作用域来实现。ps: 不通过that存储,直接传递this也可
思路2
ES5中对函数方面唯一扩展是新增了一个bind函数,用于劫持函数作用域,并预先添加更多参数,然后返回绑定了新作用域的函数。而现在我们也可以使用它,其实这个思路在MDN上有相应的介绍使用,哎,只怪自己的年少无知。。。
Parent.prototype.show = function() {
setTimeout(this.get.bind(this), 100);
};
bind/call/apply
三者都是用于绑定函数作用域,区别如下:
- call 是obj.method()到method(obj)的变换,返回函数调用结果,所需参数依次用逗号分割添加至obj尾部。
- apply 功能同call,区别是传递参数的方式不是call的那种参数列表形式,而是以数组或类数组形式传递。
- bind 返回绑定作用域后的一个新函数,不会执行函数
我们可以通过apply方法实现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() {
// this instanceof fNOP === true时,说明返回的fBound被当做new的构造函数调用
return fToBind.apply(this instanceof fNOP
? this
: oThis,
// 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的
aArgs.concat(Array.prototype.slice.call(arguments)));
};
// 维护原型关系
if (this.prototype) {
// Function.prototype doesn't have a prototype property
fNOP.prototype = this.prototype;
}
// 下行的代码使fBound.prototype是fNOP的实例,因此
// 返回的fBound若作为new的构造函数,new生成的新对象作为this传入fBound,新对象的__proto__就是fNOP的实例
fBound.prototype = new fNOP();
return fBound;
};
}
另外,我们可以利用bind修复IE事件绑定attachEvent回调中的this问题,它总是指向window对象,而标准浏览器的addEventListener中的this则为其调用对象。
function(el, type, fn) {
el.attachEvent('on' + type, fn.bind(el, event));
}
Function.prototype.bind、call与apply的更多相关文章
- Function.prototype.bind、call与apply方法简介
前言 前段时间面试遇见一题,题目内容大概是 function Parent() { this.prop = 'parent'; } Parent.prototype.get = function() ...
- 一起Polyfill系列:Function.prototype.bind的四个阶段
昨天边参考es5-shim边自己实现Function.prototype.bind,发现有不少以前忽视了的地方,这里就作为一个小总结吧. 一.Function.prototype.bind的作用 其实 ...
- Function.prototype.bind接口浅析
本文大部分内容翻译自 MDN内容, 翻译内容经过自己的理解. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Glo ...
- JavaScript 函数绑定 Function.prototype.bind
ECMAScript Edition5 IE9+支持原生,作用为将一个对象的方法绑定到另一个对象上执行. Function.prototype.bind = Function.prototype.bi ...
- Function.prototype.bind
解析Function.prototype.bind 简介 对于一个给定的函数,创造一个绑定对象的新函数,这个函数和之前的函数功能一样,this值是它的第一个参数,其它参数,作为新的函数的给定参数. b ...
- 解析Function.prototype.bind
简介 对于一个给定的函数,创造一个绑定对象的新函数,这个函数和之前的函数功能一样,this值是它的第一个参数,其它参数,作为新的函数的给定参数. bind的作用 bind最直接的作用就是改变this的 ...
- javascript Function.prototype.bind
语法: fn.bind(obj,arg1,arg2,arg3...) bind是es5新增的方法,顾名思义,它的作用是将函数绑定到某个对象上,就像是某个对象调用方法一样.其本质还是改变了该函数的上下文 ...
- 理解javascript中的Function.prototype.bind
在初学Javascript时,我们也许不需要担心函数绑定的问题,但是当我们需要在另一个函数中保持上下文对象this时,就会遇到相应的问题了,我见过很多人处理这种问题都是先将this赋值给一个变量(比如 ...
- 浅析 JavaScript 中的 Function.prototype.bind() 方法
Function.prototype.bind()方法 bind() 方法的主要作用就是将函数绑定至某个对象,bind() 方法会创建一个函数,函数体内this对象的值会被绑定到传入bind() 函数 ...
随机推荐
- 使用 JavaScript 根据消费金额和消费者是否为会员确定折扣,最终核算实际应该支付的金额
查看本章节 查看作业目录 需求说明: 根据消费金额和消费者是否为会员确定折扣,最终核算实际应该支付的金额 消费金额在 200 元以上的会员折扣是 7.5 折,消费金额没有达到 200 元的会员折扣是 ...
- SpringBoot集成Actuator健康指示器health
1.说明 本文详细介绍Actuator提供的HealthIndicators, 即健康指示器的配置使用, 利用自动配置的健康指标, 检查正在运行的应用程序的状态, 以及自定义健康指标的方法. 监控软件 ...
- 我踩过的Django的坑
把自己在使用Django过程中吃过的亏 踩过的坑 记录一下 1. unique_together传的是元组 正确:unique_together = (('app_id', 'module_id', ...
- Git_同一个本地仓库上传到不同的远端仓库(github、gitee)
一.背景 github访问.推拉代码都太慢了,于是想把github上面的项目全部迁移到gitee(码云)上,但又不想放弃在github上维护项目,于是想同时维护两个远端仓库 二.准备工作 1.创建相同 ...
- reduce/reduceRight
使用 reduce 和 reduceRight 方法可以汇总数组元素的值,具体用法如下: reduce function appendCurrent (previousValue, currentVa ...
- ElasticSearch的应用
一.介绍 全文检索技术: 分布式: Restful风格: 近实时搜索 二.部署 下载:https://thans.cn/mirror/elasticsearch.html 新建用户,并登录: 解压: ...
- How to die?
下次给一个 vector 搞 unique 之前,一定要记得给它排序!!1(少点自以为是) 对一个 set "同时"删除两个数时,一定要注意特判两个数是否重复/重叠. 有两个序列, ...
- [学习分享] 在Windows操作系统下如何安装RMySQL包
最近在做股票的高频交易数据分析,需要用到数据库,而我只对MySQL比较熟悉,于是就安装了MySQL.当我安装好了MySQL后,正兴冲冲地准备安装RMySQL包时,问题来了:RMySQL包不支持wind ...
- 【数据结构与算法】蓄水池抽样算法(Reservoir Sampling)
问题描述 给定一个数据流,数据流长度 N 很大,且 N 直到处理完所有数据之前都不可知,请问如何在只遍历一遍数据(O(N))的情况下,能够随机选取出 m 个不重复的数据. 比较直接的想法是利用随机数算 ...
- 源代码管理git地址从http改为https,提交400错误
推送400错误 cmd 执行 git config --global http.sslVerify false 推送地址,修改http 为 https 就可以正常提交了