call apply bind的作用及区别? 应用场景?
call、apply、bind方法的作用和区别:
这三个方法的作用都是改变函数的执行上下文,换句话说就是改变函数体内部的this指向,以此来扩充函数依赖的作用域
1.call
作用:用于改变方法内部的this指向
格式:xxx.call(对象名,参数1,参数2,...) 即:将 xxx 方法中的 this 指向 对象名
例子:未使用call方法前,test()中的this指向window,使用后指向obj对象
function test(a,b){
console.log(this);
console.log(a + b);
}
test(1,2); // window 3
var obj = {name:'lqs'};
window.test.call(obj,3,5); // {name:'lqs'} 8
2.apply
作用:和call方法一样是修改内部的 this 指向的,区别在于apply的第二个参数必须是一个数组(部署了Iterator接口的类数组对象也是可以的)
格式:xxx.apply(对象名,[...]) 即:将 xxx 方法中的this 指向 对象名,数组中的元素依次与方法的形参对应
例子:未使用apply方法前,test()中的this指向window,使用后指向obj对象
function test(a,b){
console.log(this);
console.log(a + b);
}
test(1,2); // window 3
var obj = {name:'lqs'};
window.test.call(obj,[3,5]); // {name:'lqs'} 8
3.bind
作用:也是用于改变this的指向
格式:xxx.bind(对象名,参数1,参数2,...) 即:将 xxx 方法中的this 指向 对象名,传参与call一样
例子:未使用bind方法前,foo()中的this指向window,使用后指向obj对象
var obj = {key:"value"}
var foo = function(){
console.log(this)
}
foo.bind(obj)() // obj
区别:
三者的第一个参数都是this需要指向的对象,但在后续的参数上只有apply是接收一个数组,call和bind用逗号分开
call和apply直接调用,返回的是一个值,而bind不直接调用,返回的是一个函数形式,执行:foo.bind(obj)()
应用场景:
通常情况下call用于对象的继承,真伪数组转换、apply用于找出数组中的最大值和最小值以及数组合并、bind用于vue和react中改变函数this指向
对象继承:
在构造函数中调用父构造函数,但是改变this指向,就可以继承父属性
function superClass () {
this.a = 1;
this.print = function () { console.log(this.a); }
}
function subClass () {
superClass.call(this); // 执行superClass,并将superClass方法中的this指向subClass
this.print();
}
subClass();
类数组与真数组的转换:
类数组:具有length属性的对象,且键为数字或string类型的数字;例如:元素检索 api 返回的都是类数组
document.getElementsByTagName,document.querySelectorAll 等等。除了dom api中,常见的 function 中的 arguments 也是类数组
真数组 ==> 类数组:
var arr = [1,3,5];
var obj = {};
[].push.apply(obj,arr); // { 0:1, 1:3 , 2:5 , length:3 }
类数组 ==> 真数组:
ES5:call、apply、Array API
// 系统自带类数组对象
var divs = document.querySelectorAll('div');
// 自定义类数组对象
var obj = {0:'lqs' , 1:18 , length:2};
var arr = []; // 真数组 // 在高级的浏览器中使用如下的方法是可以实现类数组对象转换为真数组,但是在 IE8 及其以下是不行的
// [].push.apply(arr,divs);
// [].push.apply(arr,obj);
// 为了兼容 IE8 及其以下的浏览器,需要使用数组的 slice 方法
// 数组的 slice 方法不传递参数的时候是将数组中的元素依次遍历然后放到一个 新的数组 中原样返回
var arr2 = [].slice.call(obj);
// 一切以数组为输入,并以数组为输出的API都可用来做数组转换
Array (借用 arguments)
Array.prototype.concat (借用 arguments)
Array.prototype.slice (借用 this)
Array.prototype.map (借用 this)
Array.prototype.filter (借用 this)
const arrayLike = {0: 3,1: 4,2: 5,length: 3}
Array.prototype.slice.call(arrayLike)
Array.apply(null, arrayLike)
Array.prototype.concat.apply([], arrayLike)
Array.prototype.slice.call(arrayLike)
Array.prototype.map.call(arrayLike, x => x)
Array.prototype.filter.call(arrayLike, x => 1)
ES6:Array.from()、... 扩展运算符
// Array.from();方法用于将类数组对象和可遍历(Iterator)对象转换为真数组
var obj = {0:'lqs' , 1:18 , length:2};
var arr = Array.from(obj) // ['lqs',18]
// ... 扩展运算符
// 适用于 iterable 对象 [...doucmnet.querySelector('div')]
// 但在{length:3}这种情况下会抛出异常
// Uncaught TypeError: object is not iterable (cannot read property Symperty Symbol(Symbol.iterator))[...{length:3}]
jQuery:.get() .toArray()和$makeArray(obj)
稀疏数组:
使用Array(n) 将会创建一个稀疏数组,为了节省空间,稀疏数组内含非真实元素,在控制台上将以empty显示
如下:[,,,]与Array(3) 都将返回稀疏数组
> [,,,][empty × 3] > Array(3)[empty × 3]
当类数组为 { length: 3 } 时,一切将类数组做为 this 的方法将都返回稀疏数组,而将类数组做为 arguments 的方法将都返回密集数组
数组中最大最小值及数组合并:
获取数组中最大、最小的一项
let max = Math.max.apply(null, array);
let min = Math.min.apply(null, array);
实现两个数组合并
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
Array.prototype.push.apply(arr1, arr2);
console.log(arr1); // [1, 2, 3, 4, 5, 6]
总结:
以上方法中靠谱的数组转换方法
Array.from(arrayLike)
Array.apply(null, arrayLike)
Array.prototype.concat.apply([], arrayLike)
需要考虑稀疏数组转化
Array.prototype.filter.call(divs, x => 1)
Array.prototype.map.call(arrayLike, x => x)
Array.prototype.filter.call(arrayLike, x => 1)
以下方法要注意是否是 iterable object
[...arrayLike]
参考:
https://www.cnblogs.com/deng-jie/p/15038342.html
https://wenku.baidu.com/view/533ab9c6514de518964bcf84b9d528ea80c72f54.html
https://wenku.baidu.com/view/bfd955c1514de518964bcf84b9d528ea81c72f77.html
https://blog.csdn.net/weixin_39828457/article/details/111701235
call apply bind的作用及区别? 应用场景?的更多相关文章
- call,apply,bind的用法及区别
<script> function test(){ console.log(this) } // new test(); //函数调用call方法的时候,就会执行. //call的参数:第 ...
- bind函数作用、应用场景以及模拟实现
bind函数 bind 函数挂在 Function 的原型上 Function.prototype.bind 创建的函数都可以直接调用 bind,使用: function func(){ consol ...
- apply、bind、call方法的作用与区别
js中call.apply.bind方法的作用和区别 1. call方法 作用:专门用于修改方法内部的 this 指向 格式:xxx.call( 对象名, 参数1, 参数2 , ...);.即:将 x ...
- call() 、 apply() 、bind()方法的作用和区别!
从一开始,我是在书上看到关于bind().call() 和 apply(), 不过长久以来,在工作中与网上接触到了很多关于这三个方法的使用场景,对这三个方法也算是比较熟悉了.所以把他们的作用和区别简单 ...
- call,apply,bind的用法与区别
1.call/apply/bind方法的来源 首先,在使用call,apply,bind方法时,我们有必要知道这三个方法究竟是来自哪里?为什么可以使用的到这三个方法? call,apply,bind这 ...
- js中call、apply、bind到底有什么区别?bind返回的方法还能修改this指向吗?
壹 ❀ 引 同事最近在看angularjs源码,被源码中各种bind,apply弄的晕头转向:于是他问我,你知道apply,call与bind的区别吗?我说apply与call是函数应用,指定thi ...
- call(),apply(),bind() 区别和用法
call call 方法第一个参数是要绑定给this的值,后面传入的是一个参数列表.当第一个参数为null.undefined的时候,默认指向window. var arr = [1, 2, 3, 8 ...
- js的call,apply,bind的使用与区别
在原生js中会有三个很常见的函数,call,apply,bind 他们的作用就是改变当前函数的this指针, 但是细微来说他们还是有不同的. 1)call,apply都是执行某一函数,发现this有变 ...
- Bind、Apply、Call三者的区别
1)bind与apply.call 的最大区别就是:bind不会立即调用,其他两个会立即调用 var fn = { _int: function(){return 3}, fun: function( ...
随机推荐
- linux权限问题,chmod命令
Linux系统中,每个用户的角色和权限划分的很细致也很严格,每个文件(目录)都设有访问许可权限,利用这种机制来决定某个用户通过某种方式对文件(目录)进行读.写.执行等操作. 操作文件或目录的用户,有3 ...
- QT-守护程序
功能:手动选择EXE文件 1.手动开启应用,关闭应用 2.选择是否自动开启应用程序 3.将应用程序名称,操作,时间记入TXT文档 涉及:文件写入操作,基本控件使用.Windows命令使用 Github ...
- 五分钟搭建博客系统 OK?
前言: 请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 概要: 通过 Docker Compose 在使用Docker容器构建的隔离环境中轻松运行 WordPress.在开始之前,请确保已安 ...
- 9.Jenkins进阶之流水线pipeline基础使用实践(2)
目录一览: 0x01 基础实践 0x02 进阶实践 (1) Sonarqube 代码质量检测之 Pipeline Script from SCM (2) Gitlab 自动触发构建之 Pipeline ...
- Codeforces Round #671 (Div. 2) B. Stairs 难度1200
题目链接: Problem - 1419B - Codeforces 题目 题意 给x个格子,你可以用这x个格子去拼成楼梯 好的楼梯的要求如下: 1. 第n列有n个格子 2. 这个楼梯的所有格子可以被 ...
- docker进阶_docker-compose
Docker-compose 为什么使用docker-compose 官方介绍 Compose 是一个用于定义和运行多容器 Docker 应用程序的工具.使用 Compose,您可以使用 YAML ...
- 通过配置文件(.htaccess)实现文件上传
一·什么是服务器配置文件.htaccess 许多服务器还允许开发人员在各个目录中创建特殊的配置文件,以便覆盖或添加一个或多个全局设置.例如,Apache 服务器将从一个名为(.htaccess如果存在 ...
- 用 Docker 快速搭建 Kafka 集群
开源Linux 一个执着于技术的公众号 版本 •JDK 14•Zookeeper•Kafka 安装 Zookeeper 和 Kafka Kafka 依赖 Zookeeper,所以我们需要在安装 Kaf ...
- 年年出妖事,一例由JSON解析导致的"薛定谔BUG"排查过程记录
前言 做开发这么多年,也碰到无数的bug了.不过再复杂的bug,只要仔细去研读代码,加上debug,总能找到原因. 但是最近公司内碰到的这一个bug,这个bug初看很简单,但是非常妖孽,在一段时间内我 ...
- Java 17中对switch的模式匹配增强
还记得Java 16中的instanceof增强 吗? 通过下面这个例子再回忆一下: Map<String, Object> data = new HashMap<>(); d ...