call、apply、bind方法的作用和区别:

这三个方法的作用都是改变函数的执行上下文,换句话说就是改变函数体内部的this指向,以此来扩充函数依赖的作用域

1.call

作用:用于改变方法内部的this指向

格式:xxx.call(对象名,参数1,参数2,...)  即:将 xxx 方法中的 this 指向 对象名

例子:未使用call方法前,test()中的this指向window,使用后指向obj对象

  1. function test(a,b){
  2. console.log(this);
  3. console.log(a + b);
  4. }
  5. test(1,2); // window 3
  6. var obj = {name:'lqs'};
  7. window.test.call(obj,3,5); // {name:'lqs'} 8

2.apply

作用:和call方法一样是修改内部的 this 指向的,区别在于apply的第二个参数必须是一个数组(部署了Iterator接口的类数组对象也是可以的)

格式:xxx.apply(对象名,[...]) 即:将 xxx 方法中的this 指向 对象名,数组中的元素依次与方法的形参对应

例子:未使用apply方法前,test()中的this指向window,使用后指向obj对象

  1. function test(a,b){
  2. console.log(this);
  3. console.log(a + b);
  4. }
  5. test(1,2); // window 3
  6. var obj = {name:'lqs'};
  7. window.test.call(obj,[3,5]); // {name:'lqs'} 8

3.bind

作用:也是用于改变this的指向

格式:xxx.bind(对象名,参数1,参数2,...)  即:将 xxx 方法中的this 指向 对象名,传参与call一样

例子:未使用bind方法前,foo()中的this指向window,使用后指向obj对象

  1. var obj = {key:"value"}
  2. var foo = function(){
  3. console.log(this)
  4. }
  5. foo.bind(obj)() // obj

区别:

三者的第一个参数都是this需要指向的对象,但在后续的参数上只有apply是接收一个数组,call和bind用逗号分开

call和apply直接调用,返回的是一个值,而bind不直接调用,返回的是一个函数形式,执行:foo.bind(obj)()

应用场景:

通常情况下call用于对象的继承,真伪数组转换、apply用于找出数组中的最大值和最小值以及数组合并、bind用于vue和react中改变函数this指向

对象继承:

在构造函数中调用父构造函数,但是改变this指向,就可以继承父属性

  1. function superClass () {
  2. this.a = 1;
  3. this.print = function () { console.log(this.a); }
  4. }
  5. function subClass () {
  6. superClass.call(this); // 执行superClass,并将superClass方法中的this指向subClass
  7. this.print();
  8. }
  9. subClass();

类数组与真数组的转换:

类数组:具有length属性的对象,且键为数字或string类型的数字;例如:元素检索 api 返回的都是类数组

document.getElementsByTagNamedocument.querySelectorAll 等等。除了dom api中,常见的 function 中的 arguments 也是类数组

数组 ==> 数组:

  1. var arr = [1,3,5];
  2. var obj = {};
  3. [].push.apply(obj,arr); // { 0:1, 1:3 , 2:5 , length:3 }

类数组 ==> 真数组:

ES5:call、apply、Array API

  1. // 系统自带类数组对象
  2. var divs = document.querySelectorAll('div');
  3. // 自定义类数组对象
  4. var obj = {0:'lqs' , 1:18 , length:2};
  5. var arr = []; // 真数组
  6.  
  7. // 在高级的浏览器中使用如下的方法是可以实现类数组对象转换为真数组,但是在 IE8 及其以下是不行的
  8. // [].push.apply(arr,divs);
  9. // [].push.apply(arr,obj);
  10. // 为了兼容 IE8 及其以下的浏览器,需要使用数组的 slice 方法
  11. // 数组的 slice 方法不传递参数的时候是将数组中的元素依次遍历然后放到一个 新的数组 中原样返回
  12. var arr2 = [].slice.call(obj);
  1. // 一切以数组为输入,并以数组为输出的API都可用来做数组转换
  2. Array (借用 arguments)
  3. Array.prototype.concat (借用 arguments)
  4. Array.prototype.slice (借用 this)
  5. Array.prototype.map (借用 this)
  6. Array.prototype.filter (借用 this)
  1. const arrayLike = {0: 3,1: 4,2: 5,length: 3}
  2.  
  3. Array.prototype.slice.call(arrayLike)
  4.  
  5. Array.apply(null, arrayLike)
  6.  
  7. Array.prototype.concat.apply([], arrayLike)
  8.  
  9. Array.prototype.slice.call(arrayLike)
  10.  
  11. Array.prototype.map.call(arrayLike, x => x)
  12.  
  13. Array.prototype.filter.call(arrayLike, x => 1)

ES6:Array.from()、... 扩展运算符

  1. // Array.from();方法用于将类数组对象和可遍历(Iterator)对象转换为真数组
  2. var obj = {0:'lqs' , 1:18 , length:2};
  3. var arr = Array.from(obj) // ['lqs',18]
  1. // ... 扩展运算符
  2. // 适用于 iterable 对象 [...doucmnet.querySelector('div')]
  3. // 但在{length:3}这种情况下会抛出异常
  4. // 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) 都将返回稀疏数组

  1. > [,,,][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的作用及区别? 应用场景?的更多相关文章

  1. call,apply,bind的用法及区别

    <script> function test(){ console.log(this) } // new test(); //函数调用call方法的时候,就会执行. //call的参数:第 ...

  2. bind函数作用、应用场景以及模拟实现

    bind函数 bind 函数挂在 Function 的原型上 Function.prototype.bind 创建的函数都可以直接调用 bind,使用: function func(){ consol ...

  3. apply、bind、call方法的作用与区别

    js中call.apply.bind方法的作用和区别 1. call方法 作用:专门用于修改方法内部的 this 指向 格式:xxx.call( 对象名, 参数1, 参数2 , ...);.即:将 x ...

  4. call() 、 apply() 、bind()方法的作用和区别!

    从一开始,我是在书上看到关于bind().call() 和 apply(), 不过长久以来,在工作中与网上接触到了很多关于这三个方法的使用场景,对这三个方法也算是比较熟悉了.所以把他们的作用和区别简单 ...

  5. call,apply,bind的用法与区别

    1.call/apply/bind方法的来源 首先,在使用call,apply,bind方法时,我们有必要知道这三个方法究竟是来自哪里?为什么可以使用的到这三个方法? call,apply,bind这 ...

  6. js中call、apply、bind到底有什么区别?bind返回的方法还能修改this指向吗?

     壹 ❀ 引 同事最近在看angularjs源码,被源码中各种bind,apply弄的晕头转向:于是他问我,你知道apply,call与bind的区别吗?我说apply与call是函数应用,指定thi ...

  7. call(),apply(),bind() 区别和用法

    call call 方法第一个参数是要绑定给this的值,后面传入的是一个参数列表.当第一个参数为null.undefined的时候,默认指向window. var arr = [1, 2, 3, 8 ...

  8. js的call,apply,bind的使用与区别

    在原生js中会有三个很常见的函数,call,apply,bind 他们的作用就是改变当前函数的this指针, 但是细微来说他们还是有不同的. 1)call,apply都是执行某一函数,发现this有变 ...

  9. Bind、Apply、Call三者的区别

    1)bind与apply.call 的最大区别就是:bind不会立即调用,其他两个会立即调用 var fn = { _int: function(){return 3}, fun: function( ...

随机推荐

  1. 使用ABP SignalR重构消息服务(二)

    使用ABP SignalR重构消息服务(二) 上篇使用ABP SignalR重构消息服务(一)主要讲的是SignalR的基础知识和前端如何使用SignalR,这段时间也是落实方案设计.这篇我主要讲解S ...

  2. 原生的ajax请求

    原生ajax请求的步骤: get 请求: 1,创建一个xhr变量 var xhr=new XMhttpRequest(); 2,设置请求方式和请求地址 xhr.open('url','http//19 ...

  3. Typora+PicGO+Gitee实现图床功能

    Typora+PicGO+Gitee实现图床功能 版本 typora(0.9.86) PicGo(2.3.0) 主要参考链接 出现问题就先看看这个 问题一 打开PicGo后安装github插件会一直安 ...

  4. python基础练习题(题目 模仿静态变量的用法)

    day27 --------------------------------------------------------------- 实例041:类的方法与变量 题目 模仿静态变量的用法. 程序 ...

  5. 【报错解决】Uncaught TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'.

    项目开发日记-bug多多篇(2) 同时也是 实现一些功能(3) 真的痛苦,写一天代码遇到的bug够我写三天博客. 今天是为了做一个头像功能,具体说是用户上传头像文件并且预览的功能. <div c ...

  6. 攻防世界-MISC:坚持60s

    这是攻防世界新手练习区的第六题,题目如下: 点击附件1下载,是一个java文件,点击运行一下: 绿帽子满天飞不知道是怎么回事(还是老老实实去看WP吧),WP说这是编译过的Java代码,但我手里没有反编 ...

  7. JAVA IDEA连接mysql遇到的问题

    Mysql-connector-java驱动问题 因为缺乏驱动而无法成功连接数据库 下载驱动(教程) 相关网址 安装驱动 简单图示

  8. 关于Spring-JDBC测试类的简单封装

    关于Spring-JDBC测试类的简单封装 1.简单封装 /** * Created with IntelliJ IDEA. * * @Author: Suhai * @Date: 2022/04/0 ...

  9. 干货 | LVM快照学习

    一个执着于技术的公众号 前言 在上一章节,我们学习了LVM逻辑卷管理技术,知道了LVM能够通过增减PE的数量来弹性调整文件系统的大小.除此之外,LVM还有另一个重要功能「LVM快照技术」,也就是可以给 ...

  10. Linux虚拟网络技术学习

    一个执着于技术的公众号 地方 背景 在Linux虚拟化技术中,网络层面,通常重要的三个技术分别是Network Namespace.veth pair.以及网桥或虚拟交换机技术.今天就通过实验带大家一 ...