理解并手写 call() 函数
手写自己的call,我们要先通过call的使用,了解都需要完成些什么功能?
call()进行了调用,是个方法,已知是建立在原型上的,使用了多个参数(绑定的对象+传递的参数)。
我们把手写的函数起名为myCall,obj作为形参承载传过来的第一个参数(即绑定的对象)。
Function.prototype.myCall = function(obj){}
call的调用对this的指向进行了改变,而this是函数,这是前提(对this进行判断)。
Funtion.prototype.myCall = function(obj){
// 判断调用对象是否为函数
if(typeof this !== 'function'){
console.error('type error')
}
}
同理应当判断是否传入了参数,如果没有传入参数,则绑定的对象设置为window。
Funtion.prototype.myCall = function(obj){
if(typeof this !== 'function'){
console.error('type error')
}
// 判断绑定的对象
obj = obj || window;
}
要调用这个this方法,我们可以先将其作为对象的属性方法,然后调用。
Function.prototype.myCall = function(obj){
if(typeof this !== 'function'){
console.error('type error!');
}
obj = obj || window;
// 添加属性方法,并调用
obj.fn = this;
obj.fn();
}
call调用完后,拥有使用完方法后的返回值,所以肯定要将方法的执行结果保存并返回。
Function.prototype.mycall = function(obj){
if(typeof this !== 'function'){
console.error('type error!')
}
obj = obj || window;
obj.fn = this;
// 将执行结果保存,并返回
let result = obj.fn();
return result;
}
在原对象中,并没有obj.fn属性,所以我们要将其进行删除。
Function.prototype.mycall = function(obj){
if(typeof this !== 'function'){
console.error('type error!')
}
obj = obj || window;
obj.fn = this;
let result = obj.fn();
// 删除context.fn属性
delete obj.fn;
return result;
}
最后考虑下方法中使用的参数(从传递过来的第二个参数开始),通过slice()进行切割,并拼凑为数组。
Function.prototype.mycall = function(obj){
if(typeof this !== 'function'){
console.error('type error!')
}
// 获取正确参数
let args = [...arguments].slice(1)
obj = obj || window;
obj.fn = this;
let result = obj.fn(...args);
delete obj.fn;
return result;
}
最后通过一个例子,来验证是否达到call()的功能要求。
Function.prototype.myCall = function(obj) {
if (typeof this !== 'function') {
console.error('type error!');
}
obj = obj || window;
let args = [...arguments].slice(1);
obj.fn = this;
let result = obj.fn(...args)
delete obj.fn;
return result;
}
let dog = {
name: '狗',
eat(food1, food2) {
console.log(this.name + '爱吃' + food1 + food2);
}
}
let cat = {
name: '猫',
}
dog.eat.call(cat, '鱼', '肉'); // 猫爱吃鱼肉
dog.eat.myCall(cat, '鱼', '肉'); // 猫爱吃鱼肉
另外两篇:'对apply()函数的分析' 和 '对bind()函数的分析' 。
理解并手写 call() 函数的更多相关文章
- 理解并手写 bind() 函数
有了对call().apply()的前提分析,相信bind()我们也可以手到擒来. 参考前两篇:'对call()函数的分析' 和 '对apply()函数的分析',我们可以先得到以下代码: Functi ...
- 理解并手写 apply() 函数
apply()函数,在功能上类似于call(),只是传递参数的格式有所不同. dog.eat.call(cat, '鱼', '肉'); dog.eat.apply(cat, ['鱼', '肉']); ...
- WPF启动流程-自己手写Main函数
WPF一般默认提供一个MainWindow窗体,并在App.Xaml中使用StartupUri标记启动该窗体.以下通过手写实现WPF的启动. 首先先介绍一下VS默认提供的App.Xaml的结构,如下图 ...
- python 精华梳理(已理解并手写)--全是干货--已结
基础部分 map,reduce,filter,sort,推导式,匿名函数lambda , 协程,异步io,上下文管理 自定义字符串转数字方法一不使用reduce import re def str2i ...
- 前端面试题整理——手写bind函数
var arr = [1,2,3,4,5] console.log(arr.slice(1,4)) console.log(arr) Function.prototype.bind1 = functi ...
- 手写bind函数
实现bind函数 参考MDN提供的Polyfill方案 Function.prototype.myBind = function(context){ //这里对调用者做一个判断,如果不是函数类型,直接 ...
- C++之手写strlen函数
代码: int strlen(const char *str){ assert(str!=NULL); intlen=; while((*str++)!='\0') len++; return len ...
- js面试题之手写节流函数和防抖函数
函数节流:不断触发一个函数后,执行第一次,只有大于设定的执行周期后才会执行第二次 /* 节流函数:fn:要被节流的函数,delay:规定的时间 */ function throttle(fn,dela ...
- 【OpenCV学习笔记】之六 手写图像旋转函数---万丈高楼平地起
话说,平凡之处显真格,这一点也没错! 比如,对旋转图像进行双线性插值,很简单吧? 可,对我,折腾了大半天,也没有达到预期效果! 尤其是三个误区让我抓瞎好久: 1,坐标旋转公式. 这东西,要用 ...
随机推荐
- JSP response.setCharacterEncoding与response.setContentType的区别
问题描述 昨天在参考别人的项目时,发现页面引用js,css等文件总是乱码,后来才发现是MIME类型统一设置为text/html,并且仅仅编码设置了浏览器端的解析编码.另外,可以先通过文本编辑器(如no ...
- Git refusing to merge unrelated histories (拒绝合并不相关仓库)
感谢原文作者:lindexi_gd 原文链接:https://blog.csdn.net/lindexi_gd/article/details/52554159 本文讲的是把git在最新2.9.2,合 ...
- 让HTML和JSP页面不缓存从Web服务器上重新获取页面
感谢原文作者:佚名 原文链接:https://www.jb51.net/web/100639.html 问题描述 用户退出后,如果点击浏览器上的后退按钮,Web应用将不能正确保护受保护的页面--在Se ...
- JVM学习一:常用JVM配置参数
原文链接:https://www.cnblogs.com/pony1223/p/8661219.html 在IDE的后台打印GC日志: 既然学习JVM,阅读GC日志是处理Java虚拟机内存问题的基础技 ...
- 抽象修饰符abstract
描述一类事物的时候发现该类存在一种行为,但不知道行为具体怎么实现,我们将这种行为称之为抽象行为,这时候我们就需要抽象类 抽象类的好处:抽象类中的抽象方法一定要备子类重写 抽象类注意点: 1.在类中,一 ...
- MHA高可用配置及故障切换
MHA高可用配置及故障切换 目录 MHA高可用配置及故障切换 一.案例概述 二.案例前置知识点 1. MHA概述 2. MHA的组成 (1)MHA Manager(管理节点) (2)MHA Node( ...
- MySQL保留2位小数
1.round(x,d),四舍五入.round(x) ,其实就是round(x,0),也就是默认d为0 select round(110.35,1); # 110.4 2.TRUNCATE(x,d), ...
- Solution -「牛客 NOIP 模拟赛」打拳
\(\mathcal{Description}\) 现 \(2^n\) 个人进行淘汰赛,他们的战力为 \(1\sim 2^n\),战力强者能战胜战力弱者,但是战力在集合 \(\{a_m\}\) 里 ...
- Solution -「HNOI 2019」「洛谷 P5293」白兔之舞
\(\mathcal{Description}\) Link. 不想概括题意.jpg \(\mathcal{Solution}\) 定义点集 \(S_c=\{(u,v)|v=c\}\):第 ...
- python-xlutils模块-修改excel
前言 xlrd库用于读取excel文件中的数据,xlwt库用于将数据写入excel文件,修改用xlutils模块: xlutils库也仅仅是通过复制一个副本进行操作后保存一个新文件,像是xlrd库和x ...