call, apply, bind 函数能干啥?如何在日常搬砖中使用?(全)

call(),apply(),bind() 函数大家可能都有所了解,但是在平时搬砖过程中很可能或者基本没用过,学过但都淡忘了。

但是在大量第三方的框架(库),甚至js自己都在 源码中大量使用 call,apply 函数。所以今天和大家仔细讨论下它们在 开发中的应用场景

1 . 它们是啥意思

1.1 作用

  1. 他们的作用都是改变函数内部的this
  2. 这三个函数都是函数对象的方法,也就是说只有函数才可以直接调用这些方法。

ps:call,apply,bing属于this显示绑定,还有好几种其他的this绑定方式,感兴趣的可以点这里

1.2 三者区别

  • 参数: 三个函数的第一个参数都是需要绑定的 this

call: 可以有n个参数,从第二个参数开始的所有参数都是原函数的参数。

`apply`:只有两个参数,并且第二个参数必须为数组,数组中的所有元素一一对应原函数的参数。

`bind`: 只有一个参数,即要绑定的this。

    call 语法:  foo.call(this, arg1,arg2, ... ,argn );
    apply 语法: foo.apply(this, [ arg1,arg2, ... ,argn ] );
    bind 语法:  foo.bind(this);
  • 调用:

call,apply: 调用后立即执行原函数。

`bind`: 调用后返回已经绑定好this的函数。

小例子一枚:


    function foo(a,b){
        console.log(a+b);
    }
    foo.call(null,‘海洋‘,‘饼干‘);        // 海洋饼干  这里this指向不重要就写null了
    foo.apply(null, [‘海洋‘,‘饼干‘] );   // 海洋饼干
    var fun = foo.bind(null);
    fun(‘海洋‘,‘饼干‘);                  // 海洋饼干

2 .它们能干啥事

这是我们今天讨论的主题,这三个函数如何应用?什么情况下使用?能改变this指向又能咋滴?

2 .1 处理伪数组 (最常用)

先考虑一个问题,如果你使用var arr = document.getElementsByTagName(‘li‘)获取了5个li元素,你现在需要获取其中的第2,3,4三个元素,你会怎么做?

这样arr.slice(1,4);? 啊哦,TypeError -- arr.slice is not a function(slice不是函数),数组操作在日常搬砖中非常常见,我见过最傻的解决这个问题的方式是使用循环,将需要的元素一个个添加到一个新数组里0.0,下面我介绍的方法完全可以在实战中使用,可以给你的代码加分哦,非常方便简洁(中高级前端程序员中,算是基本操作了)。

先要介绍一个概念( 伪数组 ),这也是为什么我们刚刚slice切割数组时出错的原因: (对新手来说算是干货了,知道的可以跳过)

什么是伪数组?( 字面的意思已经呼之欲出了 )

  1. 有length属性
  2. 能按索引存储数据
  3. 能像遍历数组一样来遍历
  4. 不能使用数组的push()、slice()等方法

简单来说就是可以像数组一样操作的对象,但是没有数组的方法。

js中存在大量伪数组,如 :

1. function的arguments对象。
2. getElementsByName(),getElementsByTagName(),childNodes/children 等方法的返回值。
3. 还有比较常见的jquery,使用它获取的元素也是伪数组。

回到原来的问题,如何截取伪数组中的元素:伪数组没有这些方法,我们‘借用‘Array的slice不就行了

[].slice.call(arr,1,4);  // 推荐写法

不想借用你可以直接给伪数组添加一个slice函数,如

arr.slice = [].slice;
arr.slice(1,4);

当然,‘借用‘ 更方便,直接添加会导致伪数组对象‘污染‘。

如果可以随意改变原对象,可以 直接将其转成真正的数组对象

[].slice.call(arr);

2 .2 继承

继承方式多种多样,我们现在讨论的这种是其中很重要的一种实现方式,用call实现 js 构造函数继承

  • 单继承
function person(name){
    this.name = name
}
function man(name){
    this.age = ‘男‘;
    person.call(this,name);              // 继承 man
}
var me = new man(‘海洋饼干‘);

console.log(me.name,me.age);             // ‘海洋饼干‘ ‘男‘
  • 多继承
function person(name){
    this.name = name
}
function man(name){
    this.age = ‘男‘;
}
function manProgrammer(name){
    this.girlfriend = null;
    person.call(this,name);  // 继承 person
    man.call(this,name);     // 继承 man
}
var me = new manProgrammer(‘海洋饼干‘);

console.log(me.name,me.age,me.girlfriend);   // ‘海洋饼干‘ ‘男‘ null

2 .3 this 硬绑定 --- bind

将一个对象强制且永久性绑定到函数的this上,使用call,apply或者其他的绑定方式都无法改变(除了new绑定,当然,可以手动撸一个new都无法改变的硬绑定)

直接看例子:

var fun ;
var obj = {
    a : 1,
    foo : function(){
        var _this = this;            //平时有没有过这种写法? 为了防止this指向问题
                                     //将this赋值给一个变量,间接维持了this的安全性
       fun = function(){
            console.log(_this.a);
        }
    }
}
obj.foo();
fun();                 // 1

var obj1 = { a : 2}
obj.foo.call(obj1);    // 直接修改_this所绑定的值,boom了
fun();                 // 2

但是这种方法感觉上是在逃避问题,直接不使用this了 ? 这真的不是什么好的解决问题的态度。下面使用我们的bind来优化一下:

var fun ;
var obj = {
    a : 1,
    foo : function(){            // 不使用 _this, 避免无谓的变量声明
        fun = function(){
            console.log(this.a);
        }.bind(this);            // 代码很简洁,很漂亮(b格)
    }
}
var obj1 = { a : 2}
obj.foo();
fun();             // 1
fun.call(obj1);    // 1  call ,apply等绑定 无法修改
                   // 这里和上面call的位置不同是因为this所处于不同的位置

这样替代 _this 很规(zhuang)范(b)

ps:call,apply,bing属于this显示绑定,还有好几种其他的this绑定方式,感兴趣的可以点这里

2 .4 取数组最大最小值

Math.max和min方法,接收多个参数,比较出极值,这里用到apply的一个默认功能:展开数组传入一个数组参数就可以默认将这个数组转成一个个参数的形式赋给原函数

var num = [6,9,-3,-5];
console.log(Math.max.apply(Math,num)); // 9  等价  console.log(Math.max(6,9,-3,-5));
console.log(Math.min.apply(Math,num)); // -5 等价  console.log(Math.min(6,9,-3,-5));

2 .5 合并数组

合并数组常见有三种方式,1.循环 2.Array的concat() 3. 使用apply()合并

这里是使用最简便的apply

var a = [1,2,3];
var b = [4,5,6];
[].push.apply(a,b);    // 借用数组的push方法 等价 a.push(4,5,6);
console.log(a);        // [1, 2, 3, 4, 5, 6]




觉得对你有帮助点个赞呗555

大家有什么实用点的黑科技欢迎私信评论 分享,我会贴上id和你的分享 >_<

原文地址:https://www.cnblogs.com/10yearsmanong/p/12208180.html

时间: 2024-11-08 02:50:11

call, apply, bind 函数能干啥?如何在日常搬砖中使用?(全)的相关文章

原生JS实现call,apply,bind函数

1. 前言 使用原生JS实现call和apply函数,充分了解其内部原理.call和apply都是为了解决改变this的指向.作用都相同,只是传参的方式不同.除了第一个参数外,call可以接受一个参数列表,apply只接受一个参数数组. 2. call函数 2.1 描述 call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数. 2.2 语法 fun.call(thisArg, arg1, arg2, ...) 2.3 参数 thisArg:可选的.在 fun 函数

理解bind函数

前言:之前一直不懂这个函数是干嘛的,最近慢慢有点懂了,说一说自己的理解~ 本文按以下3个方面来谈谈bind函数 1)对bind函数的理解: 2)如何使用bind函数 3)自定义bind函数 (https://msdn.microsoft.com/zh-cn/library/ff841995中有bind函数较详细的说明) (1)bind函数的理解 语法: function.bind(thisArg[,arg1[,arg2[,argN]]]) 首先不看传的参数,bind函数实现的功能就是将funct

javascript 的bind/apply/call函数

javascript有三个使用频率非常高的内建函数:bind/apply/call.许多高级点的技巧都是基于这几个函数来实现的.这三个函数都用于改变函数的执行环境.从而达到代码复用的目的. 先来所说bind函数, bind,函数通常有两个用途: 1. 创建新函数,指定函数的this指针. name = 'global'; var obj1 = {name: 'foo'}; var showName = function() { console.log(this.name); } showName

call,apply,bind

call,apply,bind 一.call&apply call, apply都属于Function.prototype的方法,因为属于Function.prototype,所以每个Function对象实例,也就是每个方法都有call, apply属性啦. 如果不明白,请见“Javascript之一切皆为对象3”. 而且它们的作用都是一样的,只是使用方式不同而已. 作用:借用别人的方法来调用,就像自己有这个方法一样. 咦,那它们怎样才能达到这目的呢? 对象. 对象? 是的,其实就是改变执行上下

call() , apply() , bind() 方法,

先来说说call() 和 apply()方法: 在<javascript高级程序设计>中有提到:函数也是对象,函数原型链的顶层实际上是指向Object的.既然函数是对象,那么自然就具有属性和方法." 每个函数都包含两个非继承而来的方法  call() , apply() " call() , apply() , 这两个方法其本质就是设置函数体内this对象指向的值,换个说法来理解这句话,一个对象可以通过call() 和 apply() 来调用其他对象的方法.比如说对象A拥有

别真以为JavaScript中func.call/apply/bind是万能的!

自从学会call/apply/bind这三个方法后我就各种场合各种使用各种得心应手至今还没踩过什么坑,怎么用?说直白点就是我自己的对象没有某个方法但别人有,我就可以通过call/apply/bind去调用执行别人家的方法,不太懂具体用法的同学可移至MDN学习一下Function.prototype.call() Function.prototype.apply() Function.prototype.bind() ,本文不讲解使用,但是这三个方法并不是万能的,并不一定会执行你想要的那个函数,因

模拟实现兼容低版本IE浏览器的原生bind()函数功能

模拟实现兼容低版本IE浏览器的原生bind()函数功能: 代码如下: if(!Function.prototype.bind){   Function.prototype.bind=function(oThis){     if (typeof this !== 'function'){       throw new TypeError('调用者不是当前函数对象');     }       var aArgs = Array.prototype.slice.call(arguments, 1

《Javascript高级程序设计》读书笔记之bind函数详解

为什么需要bind var name = "The Window"; var object = { name: "My Object", getNameFunc: function () { return function () { return this.name; } } }; alert(object.getNameFunc()()); //"The Window" object.getNameFunc()返回一个匿名函数,在全局环境调用该

call,apply,bind的用法

关于call,apply,bind这三个函数的用法,是学习javascript这门语言无法越过的知识点.下边我就来好好总结一下它们三者各自的用法,及常见的应用场景. 首先看call这个函数,可以理解成"借用“,"请求".想像一下如下的情景:你孤单一人漂泊在外,有急事想往家里打电话,可是很不巧,手机欠费了,或者没电了,或者掉坑里了,总之你的手机就是用不成.可是你非打这个电话不可,于是你可以去借一下朋友的手机,或者借用一下邻居的手机,或者公用电话,这样呢,你就可以在自己没有手机可