理解并手写 apply() 函数
apply()函数,在功能上类似于call(),只是传递参数的格式有所不同。
dog.eat.call(cat, '鱼', '肉');
dog.eat.apply(cat, ['鱼', '肉']);
因此我们完全可以套用 '上一篇对call()的分析‘,得到下列代码。
Function.prototype.myApply = 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;
}
最后考虑下方法中使用的参数(是传递过来的第二个参数),并且格式就是数组,可以之间使用。
Function.prototype.myApply = function(obj){
if(typeof this !== 'function'){
console.error('type error!')
}
obj = obj || window;
obj.fn = this;
// 之间使用传递过来的数组
let result = obj.fn(...arguments[1]);
delete obj.fn;
return result;
}
当没有数组传递过来的时候,arguments[1]获取不到,会报错,因此要再加一层判断。
Function.prototype.myApply = function(obj){
if(typeof this !== 'function'){
console.error('type error!')
}
obj = obj || window;
obj.fn = this;
// 判断arguments[1]是否存在
if(arguments[1]){
result = obj.fn(...arguments[1]);
}else{
result = obj.fn();
}
delete obj.fn;
return result;
}
最后通过一个例子,来验证是否达到apply()的功能要求。
Function.prototype.myApply = function(obj){
if(typeof this !== 'function'){
console.error('type error!')
}
obj = obj || window;
obj.fn = this;
// 判断arguments[1]是否存在
if(arguments[1]){
result = obj.fn(...arguments[1]);
}else{
result = obj.fn();
}
delete obj.fn;
return result;
}
let dog = {
name: '狗',
eat(food1, food2) {
console.log(this.name + '爱吃' + food1 + food2);
}
}
let cat = {
name: '猫',
}
dog.eat.apply(cat, ['鱼', '肉']); // 猫爱吃鱼肉
dog.eat.myApply(cat, ['鱼', '肉']); // 猫爱吃鱼肉
另外两篇:'对apply()函数的分析' 和 '对bind()函数的分析' 。
理解并手写 apply() 函数的更多相关文章
- 理解并手写 call() 函数
手写自己的call,我们要先通过call的使用,了解都需要完成些什么功能? call()进行了调用,是个方法,已知是建立在原型上的,使用了多个参数(绑定的对象+传递的参数). 我们把手写的函数起名为m ...
- 理解并手写 bind() 函数
有了对call().apply()的前提分析,相信bind()我们也可以手到擒来. 参考前两篇:'对call()函数的分析' 和 '对apply()函数的分析',我们可以先得到以下代码: Functi ...
- WPF启动流程-自己手写Main函数
WPF一般默认提供一个MainWindow窗体,并在App.Xaml中使用StartupUri标记启动该窗体.以下通过手写实现WPF的启动. 首先先介绍一下VS默认提供的App.Xaml的结构,如下图 ...
- 前端面试题整理——手写bind函数
var arr = [1,2,3,4,5] console.log(arr.slice(1,4)) console.log(arr) Function.prototype.bind1 = functi ...
- python 精华梳理(已理解并手写)--全是干货--已结
基础部分 map,reduce,filter,sort,推导式,匿名函数lambda , 协程,异步io,上下文管理 自定义字符串转数字方法一不使用reduce import re def str2i ...
- 手写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 ...
- 常见的JS手写函数汇总(代码注释、持续更新)
最近在复习面试中常见的JS手写函数,顺便进行代码注释和总结,方便自己回顾也加深记,内容也会陆陆续续进行补充和改善. 一.手写深拷贝 <script> const obj1 = { name ...
随机推荐
- Ajax向服务器发起请求
Ajax向服务器发起请求的三个步骤: 1:创建Ajax 2:打开Ajax,打开Ajax请求 3:向服务器发起请求:需要知道地址和是get请求还是post方法 向服务器发起请求的两个方法:open 和 ...
- 【转】Nginx location写法
转自:https://www.cnblogs.com/IPYQ/p/7889399.html nginx location正则写法 location = / { # 精确匹配 / ,主机名后面不能带任 ...
- 深入Java微服务之网关系列1:什么是网关
前言 近来,在想着重构一个新的产品.准备采用微服务的技术解决方案,来搭建基础设施框架.网关,是一个必不可少的组件.那么,网关到底是什么? 其又有什么特点或者特性,成为微服务必不可少的组件呢?今天, ...
- JS快速入门(二)
目录 JS快速入门(二) 结构图 BOM window对象 open() window子对象 location对象 history对象(了解) navigator 对象 screen对象 BOM 定时 ...
- Kubernets-初见
只是入门文档. 使用 linux 通过 java -jar 方式部署单体架构,war 包丢tomcat. 使用 Docker部署微服务架构. 使用 K8s Pod 进行部署 一个一个 服务 命令 je ...
- linux 定时删除图以及crontab介绍
执行 sudo crontab -e 0 3 1 * * /etc/letsencrypt/certbot-auto renew --renew-hook "sudo nginx -s re ...
- Solution -「ZJOI 2013」「洛谷 P3337」防守战线
\(\mathcal{Description}\) Link. 有 \(n\) 个位置,从左至右编号 \(1\sim n\).在第 \(i\) 个位置放一座塔的代价为 \(c_i\),一个位置 ...
- Solution -「CF 1119F」Niyaz and Small Degrees
\(\mathcal{Description}\) Link. 给定一棵 \(n\) 个结点的树,边有边权,对于每个整数 \(x\in[0,n)\),求出最少的删边代价使得任意结点度数不超过 ...
- Solution -「CF 1391E」Pairs of Pairs
\(\mathcal{Description}\) Link. 给定一个 \(n\) 个点 \(m\) 条边的无向图,在其上找到一条包括不少于 \(\lceil\frac{n}2\rceil\ ...
- .NET 云原生架构师训练营(权限系统 代码实现 Store.EntityFramework)--学习笔记
目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.Secu ...