美文网首页
如何理解js中的call和apply?

如何理解js中的call和apply?

作者: Demon_0481 | 来源:发表于2017-12-30 14:48 被阅读0次

    大家好,我是IT修真院萌新分院第3期的学员张晓琳,一枚正直、纯洁、善良的前端程序员今天给大家分享一下,修真院官网js任务2深度思考中的知识点——如何理解js中call和apply?

    1.背景介绍

    call 和 apply 都是为了改变某个函数运行时的 

    context 即上下文而存在的,换句话说,

    就是为了改变函数体内部 this 的指向。

    因为 JavaScript 的函数存在

    「定义时上下文」和「运行时上下文」

    以及「上下文是可以改变的」这样的概念。

    2.知识剖析

    1. apply: 

    方法能劫持另外一个对象的方法,继承另外一个对象的属性. 

    Function.apply(obj,args)方法能接收两个参数

    obj:这个对象将代替Function类里this对象

    args:这个是数组,它将作为参数传给Function(args-->arguments)

    2. call 

    和apply的意思一样,只不过是参数列表不一样

    Function.call(obj,[param1[,param2[,…[,paramN] ] ] ] )

    obj:这个对象将代替Function类里this对象

    params:这个是一个参数列表

    3.常见问题

    如何使用call和apply?

    4.解决方案

    call 和 apply 的作用基本类似, 

    都是去执行function并将这个function 

    的context替换成第一个参数带入。 

    两者的不同是call 必须将function 的参数一一带入,接受的是连续参数

    而 apply 接受的是数组参数 只要在第二个参数带入一个数列。

    //控制台运行:

    //j  k  形參

    function add(j, k) {

        return j + k;

    }

    function sub(j, k) {

        return j - k;

    }

    // 5 3  實參

    add(5, 3); //8

    add.call(sub, 5, 3); //8

    add.apply(sub, [5, 3]); //8

    sub(5, 3); //2

    sub.call(add, 5, 3); //2

    sub.apply(add, [5, 3]); //2

    //通过call和apply实现对象继承。

    var Parent = function () {

        this.name = "yjc";

        this.age = 22;

    }

    var child = {};

    console.log(child);//Object {} ,空对象

    Parent.call(child);

    console.log(child); //Object {name: "yjc", age: 22}

    //call方法1

    window.color = 'red';

    document.color = 'yellow';

    var s1 = {color: 'blue' };

    function changeColor(){

        console.log(this.color);

    }

    //2

    changeColor.call();        //red (默认传递参数)

    changeColor.call(window);  //red

    changeColor.call(document); //yellow

    changeColor.call(this);    //red

    changeColor.call(s1);      //blue

    var Pet = {

        words : '...',

        speak : function (say) {

            console.log(say + ''+ this.words)

    }

    }

    Pet.speak('Speak'); // 结果:Speak...

    var Dog = {

        words:'Wang'

    }

    //将this的指向改变成了Dog

    Pet.speak.call(Dog, 'Speak'); //结果:SpeakWang

    //apply方法1

    window.number = 'one';

    document.number = 'two';

    var s1 = {number: 'three' };

    function changeColor(){

        console.log(this.number);

    }

    changeColor.apply();        //one (默认传参)

    changeColor.apply(window);  //one

    changeColor.apply(document); //two

    changeColor.apply(this);    //one

    changeColor.apply(s1);      //three

    //方法2

    function Pet(words){

        this.words = words;

        this.speak = function () {

            console.log( this.words)

    }

    }

    function Dog(words){

        //Pet.call(this, words); //结果:Wang

        Pet.apply(this, arguments); //结果:Wang

    }

    var dog = new Dog('Wang');

    dog.speak();

    5.编码实战

    // call方法可以用来代替另一个对象调用一个方法,

    // call方法可以将一个函数的对象上下文从初始的上下文改变为thisObj指定的新对象,

    // 如果没有提供thisObj参数,那么Global对象被用于thisObj。

    //1:

        function add(c,d){

            return this.a + this.b + c + d;

    }

    var s = {a:1, b:2};

    console.log(add.call(s,3,4)); // 1+2+3+4 = 10

    console.log(add.apply(s,[5,6])); // 1+2+5+6 = 14

    //2:

    window.firstName = "Cynthia";

    window.lastName = "_xie";

    var myObject = {firstName:'my', lastName:'Object'};

    function getName(){

        console.log(this.firstName + this.lastName);

    }

    function getMessage(sex,age){

        console.log(this.firstName + this.lastName + " 性别: " + sex + " age: " + age );

    }

    getName.call(window); // Cynthia_xie

    getName.call(myObject); // myObject

    getName.apply(window); // Cynthia_xie

    getName.apply(myObject);// myObject

    getMessage.call(window,"女",21); //Cynthia_xie 性别: 女age: 21

    getMessage.apply(window,["女",21]); // Cynthia_xie 性别: 女age: 21

    getMessage.call(myObject,"未知",22); //myObject 性别: 未知age: 22

    getMessage.apply(myObject,["未知",22]); // myObject 性别: 未知 age: 22

    6.扩展思考

    call()和apply()两种方法的区别? 

    相同点:两个方法产生的作用是完全一样的

    不同点:方法传递的参数不同

    call()接受的是一个参数列表,而apply()接受一个参数数组。

    func.call(this, arg1, arg2);

    func.apply(this, [arg1, arg2])

    其中 this 是你想指定的上下文,他可以是任何一个 JavaScript 对象(JavaScript 中一切皆对象),

    call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。

    因此要说适用条件的话,当你的参数是明确知道数量时用 call 。

    而不确定的时候用 apply,然后把参数 push 进数组传递进去。

    7.参考文献

    參考

    8.更多讨论

    问题:

    Q1:王姣妍:是call还是apply能改变this的指向?

    A1:张晓琳:两个都能改,就是传参数方式不一样呀,apply传数组,call传字符串。

    Q2:王栋:apply的应用场景呢??

    A2:其他人:

    我首先从网上查到关于apply和call的定义,然后用示例来解释这两个方法的意思和如何去用.  

             apply:方法能劫持另外一个对象的方法,继承另外一个对象的属性.  

     Function.apply(obj,args)方法能接收两个参数  

    obj:这个对象将代替Function类里this对象  

    args:这个是数组,它将作为参数传给Function(args-->arguments)  

             call:和apply的意思一样,只不过是参数列表不一样.  

     Function.call(obj,[param1[,param2[,…[,paramN]]]])  

    obj:这个对象将代替Function类里this对象  

    params:这个是一个参数列表  

    1.apply示例:  

    /*定义一个人类*/   

    function Person(name,age) {   

    this.name=name; this.age=age;   

    }   

    /*定义一个学生类*/   

    functionStudent(name,age,grade) {   

    Person.apply(this,arguments); this.grade=grade;   

    }   

    //创建一个学生类   

    var student=new Student("qian",21,"一年级");   

    //测试   

    alert("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade);   

    //大家可以看到测试结果name:qian age:21 grade:一年级   

    //学生类里面我没有给name和age属性赋值啊,为什么又存在这两个属性的值呢,这个就是apply的神奇之处.   

    分析: Person.apply(this,arguments);  

    this:在创建对象在这个时候代表的是student  

    arguments:是一个数组,也就是[“qian”,”21”,”一年级”];  

    也就是通俗一点讲就是:用student去执行Person这个类里面的内容,在Person这个类里面存在this.name等之类的语句,这样就将属性创建到了student对象里面 

    Q3:王栋:call的应用场景呢??

    A3:其他人:在给对象参数的情况下,如果参数的形式是数组的时候,比如apply示例里面传递了参数arguments,这个参数是数组类型,并且在调用Person的时候参数的列表是对应一致的(也就是Person和Student的参数列表前两位是一致的) 就可以采用 apply , 如果我的Person的参数列表是这样的(age,name),而Student的参数列表是(name,age,grade),这样就可以用call来实现了,也就是直接指定参数列表对应值的位置(Person.call(this,age,name,grade)); 

    PPT

    如何理解js中call和apply视频


    undefined_腾讯视频

    相关文章

      网友评论

          本文标题:如何理解js中的call和apply?

          本文链接:https://www.haomeiwen.com/subject/qtoggxtx.html