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() 函数 ...
随机推荐
- MySQL百分比显示和显示前百分之几的方法
前几天一个朋友让我帮忙写的,随手记录一下,感觉难度也不大,就是写的时候遇到一些问题.优化方便做得不太好.有好的优化方法欢迎分享!(数据库在文章结尾) 要求 1)查询所有时间内,所有产品销售金额占比,按 ...
- 使用 JavaScript 的 HTML 页面混合、JavaScript 文件引用和 HTML 代码嵌入 3 种方式在 HTML 页面上打印出“点击我进入到百度首页”的超链接
查看本章节 查看作业目录 需求说明: 使用 JavaScript 的 HTML 页面混合.JavaScript 文件引用和 HTML 代码嵌入 3 种方式在 HTML 页面上打印出"点击我进 ...
- 执行jar包指定main
java包中多个main,需要指定执行java -cp iot-device-sdk-java-0.0.5-SNAPSHOT.jar com.inspur.iot.client.sample.paho ...
- Linux-saltstack-3 saltstack的grains和pillar的基本使用
@ 目录 一.简介 二.grains 1.查看客户端所有的grains项 2.查看grains的所有的项和值 3.查看某个项和值 (1)语法1: (2)语法2: 4.根据grains来匹配目标主机 例 ...
- 木棒poj1011
题目描述 乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位. 然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度. 请你设计一个程 ...
- Go语言实战爬虫项目
Go语言爬虫框架之Colly和Goquery Python爬虫框架比较多有requests.urllib, pyquery,scrapy等,解析库有BeautifulSoup.pyquery.Scra ...
- Elasticsearch安装与配置
一.下载(华为云) https://mirrors.huaweicloud.com/elasticsearch/https://mirrors.huaweicloud.com/kibana/7.6.2 ...
- dart系列之:手写Library,Library编写最佳实践
目录 简介 使用part和part of src中的文件 package中的lib文件 总结 简介 Library是dart用来组织代码的一种非常有用的方式,通过定义不同的Library,可以将非常有 ...
- BitMap算法知识笔记以及在大数据方向的使用
概述 所谓的BitMap算法就是位图算法,简单说就是用一个bit位来标记某个元素所对应的value,而key即是该元素,由于BitMap使用了bit位来存储数据,因此可以大大节省存储空间,这是很常用的 ...
- RHCSA 第一天
1.修改主机名: 查看主机名 2.查看日期 使用指定格式输出日期 YY-mm-DD HH:MM:SS 3.将"We are learning RHCSA"输出在屏幕上 4.使用ti ...