当前位置: 首页 > 编程日记 > 正文

apply call bind 简介

Function.prototype.call(thisArg [, arg1, arg2, ...])

call() 简述

  • call() 方法 调用一个函数, 其具有一个指定的 this 值和分别地提供的参数(参数的列表)。
  • 当第一个参数为 null、undefined 的时候, 默认 this 上下文指向window。

call() 简单实例

const name = 'qianyin';
const product = {name: 'linheng',
};function log(...args){console.log(this.name, ...args);
}log(1, 2, 3);               // qianyin 1 2 3
log.call(null, 1, 2, 3);    // qianyin 1 2 3
log.call(product, 1, 2, 3); // linheng 1 2 3
复制代码

call() 对箭头函数无效

const name = 'qianyin';
const product = {name: 'linheng',
};const log = (...args) => {console.log(this.name, ...args);
}log(1, 2, 3);               // qianyin 1 2 3
log.call(null, 1, 2, 3);    // qianyin 1 2 3
log.call(product, 1, 2, 3); // qianyin 1 2 3复制代码

补充:

  • 箭头函数作为函数的一种形式, 对于this的处理和普通函数有所区别, 其没有自己的 this 上下文,也就是说通过 bind/call/apply 函数方法设置 this 值时无效的,会被忽略;

  • 因为箭头函数没有自己的 this 上下文, 所以箭头函数的 this 上下文等于定义函数处的this上下文,也就是最近的一个 this 上下文;

  • 你可以认为箭头函数的 this 和调用者无关,只和其定义时所在的 this 上下文相关;

  • 如下代码: 在对象 obj 中使用箭头函数定义 log 函数, 那么因为箭头函数没有自己的 this 上下文, 所以 log 函数的 this 上下文等于定义箭头函数处的 this 上下文, 等于 对象 obj 所处的 this 上下文(window)

const name = 'linheng';
const obj = {name: 'qianyin',log: () => {console.log(this.name);}
};
obj.log();  // linheng
复制代码
  • 那么如果我一定要在 obj 中定义一个 log 函数并且使得 this 指向对象 obj 呢?
  • 方法一: 使用 function 定义函数
const name = 'linheng';
const obj = {name: 'qianyin',log: function(){console.log(this.name);}
};
obj.log();  // qianyin
复制代码
  • 方法二: 多此一举, 在函数 log 中声明箭头函数并调用, 那么箭头函数的 this 上下文等于定义箭头函数处的 this 上下文, 等于 log 函数的上下文(对象 obj )
const name = 'linheng';
const obj = {name: 'qianyin',log: function(){(() => {console.log(this.name);})();},
};
obj.log();  // qianyin
复制代码

Function.prototype.apply(thisArg [, Array])

Apply() 简述

  • apply() 方法 调用 一个具有给定 this 值的函数,以及作为一个 数组(或类似数组对象) 提供的参数
  • call() 方法的作用和 apply() 方法类似,区别就是除第一参数 call() 方法接受的是 参数列表 ,而apply()方法接受的是一个参数 数组(或类数组)

Apply() 简单实例

const name = 'qianyin';
const product = {name: 'linheng',
};function log(...args){console.log(this.name, ...args);
}log([1, 2, 3]);                 // qianyin [1 2 3]
log.apply(null, [1, 2, 3]);     // qianyin 1 2 3
log.apply(product, [1, 2, 3]);  // linheng 1 2 3
复制代码

Apply() 对箭头函数无效

const name = 'qianyin';
const product = {name: 'linheng',
};const log = (...args) => {console.log(this.name, ...args);
}log([1, 2, 3]);                 // qianyin [1 2 3]
log.apply(null, [1, 2, 3]);     // qianyin 1 2 3
log.apply(product, [1, 2, 3]);  // qianyin 1 2 3
复制代码

Function.prototype.bind(thisArg [, arg1, arg2, ...])

bidn() 简述

  • bind() 方法 创建(拷贝)一个新的函数 , 当这个新函数被调用时 this 指向 thisArg,其 参数列表前几项值 为创建时指定的 参数序列
  • thisArg: 绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用 new 操作符调用绑定函数时,该参数无效。

bind() 绑定 this 上下文

  • bind() 最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的 this 上下文。
  • JavaScript 新手经常犯的一个错误是将一个方法从对象中拿出来,然后再调用,却又希望方法中的 this 是原来的对象(比如在回调中传入这个方法)。
  • 如果不做特殊处理的话,一般会丢失原来的对象。从原来的函数和原来的对象创建一个绑定函数,则能很漂亮地解决这个问题:
  • 如果只是单纯绑定 this 上下文, 完全可以使用箭头函数进行替代
// 例一
this.x = 9;var module = {x: 81,getX: function() { return this.x; }
};
module.getX();  // 返回 81 (通过对象调用函数, 上下文为该对象)
var retrieveX = module.getX;  // 获取对象中函数的引用地址
retrieveX();    // 返回 9, 在这种情况下, "this" 指向全局作用域(在全局对象下调用函数)
// 永久为函数 boundGetX 绑定 this 上下文
var boundGetX = retrieveX.bind(module);
boundGetX();   // 返回 81 (函数 this 上下文永久绑定为 module)
复制代码
// 例二为回调函数绑定 this 上下文
var x = 10;
var obj = {x: 20,get: ffunction(){console.log(this.x);}
};
// 将对象中方法取出(函数的引用地址),作为回调函数, 又因为 setTimeout 回调函数执行的上下文是 window
setTimeout(obj.get, 1000);            // 打印 10
// 将对象中方法取出(函数的引用地址),作为回调函数并绑定 this 上下文
setTimeout(obj.get.bind(obj), 1000);  // 打印 20
复制代码

为函数永久绑定固定参数

  • bind() 的另一个最简单的用法是使一个函数 拥有预设的初始参数
  • 这些参数(如果有的话)作为bind()的第二个参数跟在 this(或其他对象)后面。
  • 之后它们会 被插入到目标函数的参数列表的开始位置 ,传递给绑定函数的参数会跟在它们的后面。
function list() {return Array.prototype.slice.call(arguments);
}var list1 = list(1, 2, 3); // [1, 2, 3]// 为拷贝 list 方法并绑定初始参数
var leadingThirtysevenList = list.bind(undefined, 37);var list2 = leadingThirtysevenList();         // [37]
var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]
复制代码

总结

  • 当我们使用一个函数需要改变 this 指向的时候才会用到 call() apply() bind() 当然也别忘记了箭头函数
  • call() 和 apply() 是对函数的调用,在调用的同时绑定 this 上下文并传递参数列表
  • bind() 是对函数的拷贝进一步的封装, 为函数永久绑定 this 上下文并赋予固定参数
  • call() 和 bind() 以参数列表形式给函数指定参数, apply() 则以数组的形式给函数指定参数

apply call bind 的一些运用

类数组转为数组

  • 方法一:
  const obj = {0: 'q', 1: 'i', 2: 'q', 3: 'a',  4:'n', 5: 'y', 6:'i', 7:'n', length: 8};const arr = [];Array.prototype.push.apply(arr, obj);console.log(arr); // ["q", "i", "q", "a", "n", "y", "i", "n"]
复制代码
  • 方法二:
  const obj = {0: 'q', 1: 'i', length: 2};const arr = Array.prototype.slice.call(obj);  // [q, i]
复制代码

为伪数组添加新的元素

  • 方法一: 当然你也可以使用 apply
  const obj = {0: 'q', length: 1};Array.prototype.push.call(obj, 'i', 'a', 'n');console.log(obj);   // {0: 'q', 1: 'i', 2: 'a', 3: 'n'}
复制代码
  • 方法二:
  const obj = {0: 'q', length: 1};const push = Array.prototype.push.bind(obj);push('i', 'a', 'n');console.log(obj);   // {0: 'q', 1: 'i', 2: 'a', 3: 'n'}
复制代码

求数组中最大值(最小值一样做法)

const arr = [1,2,3,4,5,6];
const max = Math.max.apply(null, arr);
// 或 const max = Math.max.call(null, ...arr)
console.log(max);    // 6
复制代码

数组合并追加

const arr = [1, 2];
const brr = [3, 4];
Array.prototype.push.apply(arr, brr);
// 或者 Array.prototype.push.call(arr, ...brr);
// 当然还可以这样 arr.push(...brr);
console.log(arr);
复制代码

使用 log 代理 console.log

function log(...args){// 在可以通过配置, 或者判断当前开发环境来控制是否需要在控制台打印输出if(true){console.log.apply(console, args);}
}
复制代码

相关文章:

自定义控件的构建(5)

Share 在ASP.NET框架中支持在回传中保存值的有2种方式:视图状态和控件状态 视图状态 ASP.NET中几个对象属性与控件最为密切的,就是ViewState了。 这里对其做下说明,任何可序列化类的实例均可添加到视图状态中,但是实际上&#xff…

Javascript之旅——第一站:从变量说起

原文出处: 一线码农的博客 欢迎分享原创到伯乐头条 工作这几年,js学的不是很好,正好周末有些闲时间,索性买本《js权威指南》,大名鼎鼎的犀牛书,好好的把js深入的看一看。买过这本书的第一印象就是贼厚&am…

从浏览器发展史读懂user-agent

世界上第一个浏览器:WorldWideWeb(和万维网重名),改名Nexus,只能在NeXT系统运行。 世界上第二个浏览器:Line Mode Browser,C语言编写,只能显示文本,可以移植到不同系统。 世界上第三个浏览器(…

在把 png 或者 gif“储存为 web 所用格式”时,勾选“交错”选项

选择“交错”可创建在整个图像文件的下载过程中,在浏览器中以低分辨率显示的图像。“交错”可以使下载时间显得较短,并使查看者确信下载正在进行。但是交错也会增大文件大小。转载于:https://www.cnblogs.com/dongzhiquan/archive/2010/07/28/1994585.ht…

学习GraphX

首先准备如下社交图形数据:打开spark-shell;导入相关包:import org.apache.spark._ import org.apache.spark.graphx._ import org.apache.spark.rdd.RDD创建如上graph对象:// Create an RDD for the vertices val users: RDD[(Ve…

安装NodeJS环境报错

Failures - (exited 1) - Error while running C:\ProgramData\chocolatey\lib\visualstudio2019-workload-vctools\tools\ChocolateyInstall.ps1. 待解决

Eureka单机高可用伪集群配置

Eureka Server高可用集群理论上来讲,因为服务消费者本地缓存了服务提供者的地址,即使Eureka Server宕机,也不会影响服务之间的调用,但是一旦新服务上线,已经缓存在本地的服务提供者不可用了,服务消费者也无…

小小21点模拟

#include<iostream> #include<string> #include<cstdlib> #include<ctime> using namespace std; struct Card //一张扑克牌 { int value; //点数 string color; //花色 string face; //1-10、J、Q、K面值 }; void initCards(Card *cards) { for(int i…

BZOJ-1005 明明的烦恼

Prufer编码练习题&#xff0c;这个编码是跟树的生成计数有关系的。 推荐这篇博文&#xff1a;http://www.cnblogs.com/zhj5chengfeng/archive/2013/08/23/3278557.html 介绍地挺全面生动形象 会了Prufer之后这道题还要用上组合数学来高精度计算。 #include <cstdlib> #in…

使用npm打包后生成的package.json中重要字段含义

{"name": "demo",// 包名称,不能和npm平台上其他包重复"version": "1.0.0",// 版本号"description": "","main": "index.js",// 执行入口"scripts": {// 自定义脚本"test&quo…

Winform窗体应用程序的自动更新功能

本文将演示一种桌面程序自动更新方案&#xff0c;其步骤比较多&#xff0c;但原理非常简单&#xff0c;通用性尚可&#xff0c;对于小型应用来说&#xff0c;直接拿去就可以用了。原理服务器端的结构是这样的&#xff1a;其工作原理如下&#xff1a;Update.asmx 仅提供一个功能…

[UWP] 用 AudioGraph 来增强 UWP 的音频处理能力——AudioFrameInputNode

原文:[UWP] 用 AudioGraph 来增强 UWP 的音频处理能力——AudioFrameInputNode上一篇心得记录中提到了 AudioGraph, 描述了一下 什么是 AudioGraph 以及其中涉及到的各种类型的 节点&#xff08;Node&#xff09;。 这一篇就其中比较有意思的 AudioFrameInputNode 来详细展开一…

Png透明背景的电话图标。

转载于:https://www.cnblogs.com/li0566/p/4343427.html

CSS改变nth-child()和nth-last-child()的参数灵活选择元素编号

注&#xff1a;下面的所有示例 1. div可以更换成任意标签 2. k是变量&#xff0c;可以换成特定数值&#xff0c;n保持不变 选中偶数行 div: nth-child(2n)div: nth-child(even) 选中奇数行 div :nth-child(odd)div :nth-child(2n-1) 选中前k行 div :nth-child(-nk) 选…

关于Silverlight中多项目共享DLL文件的讨论

假如你的解决方案中有两个Silverlight项目&#xff0c;其中的DLL文件时两个SL项目都使用到的&#xff0c;为了能够最大程度的减小XAP包的体积&#xff0c;你选择了系统的这个选项 编译后在Web的ClientBin文件夹下会出现这样的结构 这样呢&#xff0c;两个项目共享这些DLL的压缩…

核方法---径向基函数网络

为什么80%的码农都做不了架构师&#xff1f;>>> Nadarayas-Watson模型 转载于:https://my.oschina.net/liyangke/blog/2986510

c# 获取客户端IP地址方法

客户端ip: Request.ServerVariables.Get("Remote_Addr").ToString(); 客户端主机名: Request.ServerVariables.Get("Remote_Host").ToString(); 客户端浏览器IE&#xff1a; Request.Browser.Browser; 客户端浏览器 版本号&#xff1a; Request.Browser.M…

CSS结构选择器四种结构关系的范围

1. 空格&#xff1a; 表示<div>标签下所有的<h1>标签 div h1 2. >: 表示<div>标签下直接的<h1>标签 div>h1 3. ~:表示与<div>并列的所有<h1>标签 div~h1 4. :表示与<div>并列且紧邻的<h1>标签 divh1 注&#xff…

VMware前路难测,多个厂家群雄逐鹿

2019独角兽企业重金招聘Python工程师标准>>> 在人们高谈Salesforce、亚马逊等新兴云计算厂商取得的成就时&#xff0c;以VMware、HPE和Cisco为代表的老牌厂商也在进行着自己的转型和变化&#xff0c;而且还取得一定的进展。以VMware为例&#xff0c;虚拟机巨头公布了…

Silverlight学习笔记十七BingMap(六)之获取图片系统的图片信息ImageryService的应用...

BIngMap的ImageryService服务是一个微软发布的WCF服务&#xff0c;它用来获取图片系统的图片信息.服务地址&#xff1a;http://dev.virtualearth.net/webservices/v1/imageryservice/ImageryService.svc 本例中使用的是中文图片系统 效果如图 一、获取中文图片系统类&#xff0…

c++ stack 的使用

(1) stack::empty bool empty ( ) const; 判断是否为空。 return Value : true if the container size is 0, false otherwise; (2) stack::pop void pop ( ); 在栈的顶部移除元素。 (3) stack::push void push ( const T& x ); 在栈顶添加元素 (4) stack::size size_type …

ES和JS的区别,以及JavaScript的基本组成

JavaScript是语言&#xff0c;而ECMAScript(即ECMA-262,ECMA是欧洲计算机制造商协会)是为了规范JS而制定的标准&#xff0c;ECMAScript有不同版本&#xff0c;最近的版本是第10版&#xff0c;发布于2019.6。 完整的JavaScript的实现包含以下几个部分 核心(ECMAScript)&#x…

微软职位内部推荐-Senior Software Engineer-Eco

微软近期Open的职位:The MOD Ecosystem team is dedicated to expanding the reach and value of Office by enabling developers to create solutions built on the Office suite of applications or powered by the O365 services. &nbsp We have an exciting mix of cha…

转Meta的http-equiv属性详解

http-equiv顾名思义&#xff0c;相当于http的文件头作用&#xff0c;它可以向浏览器传回一些有用的信息&#xff0c;以帮助正确和精确地显示网页内容&#xff0c;与之对应的属性值为content&#xff0c;content中的内容其实就是各个参数的变量值。 meat标签的http-eq…

bzoj 2946 [Poi2000]公共串——后缀自动机

题目&#xff1a;https://www.lydsy.com/JudgeOnline/problem.php?id2946 对每个串都建一个后缀自动机&#xff0c;然后 dfs 其中一个自动机&#xff0c;记录同步的话在别的自动机上走到哪些点了&#xff1b;只要有一个自动机上走不下去了&#xff0c;就都走不下去了。每走到一…

CSS:当子元素皆浮动,撑开父元素的3种方式

1. 在子元素后面补充同级的空元素&#xff0c;并定义清除浮动样式 html文件 <main><div><span>肥水东流无尽期。当初不合种相思。梦中未比丹青见&#xff0c;暗里忽惊山鸟啼。</span><br><br><span>春未绿&#xff0c;鬓先丝。人间…

js正则表达式的使用详解

本文转自&#xff1a;http://www.jb51.net/article/39623.htm 1定义正则表达式2关于验证的三个这则表达式方法3正则表达式式的转义字符1定义正则表达式在js中定义正则表达式很简单&#xff0c;有两种方式&#xff0c;一种是通过构造函数&#xff0c;一种是通过//&#xff0c;也…

Python安装及netcdf数据读写

为什么80%的码农都做不了架构师&#xff1f;>>> 一、在CentOS7系统上安装Python3 在anaconda官网下载&#xff08;http://https://www.anaconda.com/download/#linux&#xff09;&#xff08;Anaconda指的是一个开源的Python发行版本&#xff0c;是Python的包管理器…

用Visio进行数据库建模、设计和实现

用Visio进行数据库建模、设计和实现 摘要&#xff1a;Visio是微软著名的图形软件&#xff0c;功能强大。使用Visio完成绘图任务时能够显著地提高工作效率和质量。目前功能最全的Visio版本是VSEA(Visual Studio Enterprise Architect)2003所自带的2003版。 原文发表在中科院网络…

JavaScript如何声明对象、函数以及对象中的函数(即方法)

目录 声明对象的2种最常见方法 声明函数的2种最常见方法 在对象中声明函数 声明对象的2种最常见方法 1&#xff09; var Zhihuijun {name:彭志辉,age:28,upName:稚晖君,company:Huawei,};console.log(Zhihuijun.name目前在Zhihuijun.company工作); 2&#xff09; var Zhi…