资讯专栏INFORMATION COLUMN

前端小伙伴如何应对面试中的 call() 和 apply()

Pines_Cheng / 2477人阅读

摘要:和的基本作用改变对象的执行上下文改变什么是执行上下文我们在写一个方法的时候,总是会用到一个关键字,而的指向就是我们这里所说的执行上下文执行环境,首先,指向的永远是调用该方法的对象,如何证明的指向就是当前对象呢看下面这段代码代码中方法执行

【call() 和 apply() 的基本作用】 改变对象的执行上下文--改变(this)
什么是执行上下文?
我们在写一个方法的时候,总是会用到一个关键字this,而this的指向就是我们这里所说的执行上下文(执行环境),

首先,this指向的永远是调用该方法的对象,如何证明this的指向就是当前对象呢?看下面这段代码:

function func () {
    this.a = 1;
    console.log(this.a);
}
func();  // 1

代码中方法执行后控制台输出1,由于func是全局对象window下的一个方法,那么调用该方法的对象就应该是全局对象window,所以this理论上指向的对象就应该是window

如果理论成立,而this.a==1,也就是说变量a是一个全局变量。在控制台上直接输入a或window.a后回车,会发现输出了1,所以在func这个方法中,this的指向就是window

换个方式来验证下:

var person = {
    name: "xiao ming",
    age: 18,
    who: function () {
        console.log( "my name is " + this.name + " , " + this.age + " years old" );
        console.log( person === this);
    }
}

person.who();
// my name is xiao ming , 18 years old
// true

上面这段代码中who方法是person对象的一个属性,被person对象调用,所以this的指向也就是person
那么在知道什么是执行上下文以后,就可以比较好的理解改变执行上下文的含义了,举个不恰当的栗子:

小明有一个炒菜的铲子,小明的室友小刚今天突然想自己做菜吃,但是小刚没有铲子。小刚又不想为了做个菜多带带买把铲子,于是就借用了小明的铲子,这样既达到了目的,又节省了开支,一举两得

改变执行上下文也是一样,A对象有一个方法,而B对象因为某种不可言说的情况也需要用到一样的方法,那么这时候我们是多带带为B扩展个方法呢,还是借用一下A的方法呢?当然是借用A的啦,既完成了需求,又减少了内存的占用

【call()与apply()异同】 基本使用

call()

function.call(obj[,arg1[, arg2[, [,.argN]]]]])

调用call的对象必须是个函数function,call的第一个参数将会是function改变上下文后指向的对象,也就是上面例子里的小刚,如果不传,将会默认是全局对象window,第二个参数开始可以接收任意个参数,这些参数将会作为function的参数传入function,调用call的方法会立即执行

apply()

function.apply(obj[,argArray])

与call方法的使用基本一致,但是只接收两个参数,其中第二个参数必须是一个数组或者类数组,这也是这两个方法很重要的一个区别

异同

相同点

都能够改变方法的执行上下文(执行环境),将一个对象的方法交给另一个对象来执行,并且是立即执行

不同点

call方法从第二个参数开始可以接收任意个参数,每个参数会映射到相应位置的func的参数上,可以通过参数名调用,但是如果将所有的参数作为数组传入,它们会作为一个整体映射到func对应的第一个参数上,之后参数都为空

function func (a,b,c) {}
func.call(obj, 1,2,3)
// function接收到的参数实际上是 1,2,3
func.call(obj, [1,2,3])
// function接收到的参数实际上是 [1,2,3],undefined,undefined

apply方法最多只有两个参数,第二个参数接收数组或者类数组,但是都会被转换成类数组传入func中,并且会被映射到func对应的参数上

func.apply(obj, [1,2,3])
// function接收到的参数实际上是 1,2,3

func.apply(obj, {
    0: 1,
    1: 2,
    2: 3,
    length: 3
})
// function接收到的参数实际上是 1,2,3

两个方法该如何选择?

简单的说,根据你要传入的参数来做选择,不需要传参或者只有1个参数的时候,用apply,当要传入多个对象时,用call,或者,如果需要传入的参数已经是一个数组或者类数组了,就用apply,如果还是多带带的需要逐个传入的,可以考虑使用call(如果你不嫌麻烦的话 )

【对象继承】

由于可以改变this的指向,所以也就可以实现对象的继承

function superClass () {
    this.a = 1;
    this.print = function () {
        console.log(this.a);
    }
}

function subClass () {
    superClass.call(this);
    this.print();
}

subClass();
// 1

subClass通过call方法,继承了superClass的print方法和a变量,同时subClass还可以扩展自己的其他方法

本文借鉴了一些其他小伙伴的栗子,简单做了归纳总结及梳理

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89051.html

相关文章

  • 前端笔试题面试题记录(下)

    摘要:前言接上篇前端笔试题面试题记录上。默认值,不脱离文档流,,,,等属性不生效。。不脱离文档流,依据自身位置进行偏离,当子元素设置,将依据它进行偏离。。 前言 接上篇前端笔试题面试题记录(上)。趁清明小长假,把上篇剩下的部分也写一下,因为最近比较忙这篇已经拖了很久了。现在刚刚开始银四了,应该还是有些小伙伴在找工作,时间还不算太晚,希望本篇可以帮到这些小伙伴。 个人博客了解一下:obkoro...

    Lin_YT 评论0 收藏0
  • 前端笔试题面试题记录(下)

    摘要:前言接上篇前端笔试题面试题记录上。默认值,不脱离文档流,,,,等属性不生效。。不脱离文档流,依据自身位置进行偏离,当子元素设置,将依据它进行偏离。。 前言 接上篇前端笔试题面试题记录(上)。趁清明小长假,把上篇剩下的部分也写一下,因为最近比较忙这篇已经拖了很久了。现在刚刚开始银四了,应该还是有些小伙伴在找工作,时间还不算太晚,希望本篇可以帮到这些小伙伴。 个人博客了解一下:obkoro...

    suemi 评论0 收藏0
  • 前端基础进阶(八):深入详解函数的柯里化

    摘要:函数被转化之后得到柯里化函数,能够处理的所有剩余参数。因此柯里化也被称为部分求值。那么函数的柯里化函数则可以如下因此下面的运算方式是等价的。而这里对于函数参数的自由处理,正是柯里化的核心所在。额外知识补充无限参数的柯里化。 showImg(https://segmentfault.com/img/remote/1460000008493346); 柯里化是函数的一个比较高级的应用,想要...

    kk_miles 评论0 收藏0
  • 【周刊-1】三年大厂面试官-面试题精选及答案

    摘要:前言在阿里和腾讯工作了年,当了年的前端面试官,把期间我和我的同事常问的面试题和答案汇总在我的中。项目地址是我是小蝌蚪,腾讯高级前端工程师,跟着我一起每周攻克几个前端技术难点。 前言 在阿里和腾讯工作了6年,当了3年的前端面试官,把期间我和我的同事常问的面试题和答案汇总在我 Github 的 Weekly-FE-Interview 中。希望对大家有所帮助。 如果你在bat面试的时候遇到了...

    Bamboy 评论0 收藏0

发表评论

0条评论

Pines_Cheng

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<