• Apply的理解


    Apply 和 Call一样在 函数调用的时候会改变函数内的this指向,让this变成 Apply或Call的第一个参数。

    举个例子:

     var ObjEngineer = {
        name:'程序员努力的一天',
        age:19
     };
    
     function fn2() {
         console.log(this.name);
     }
    
    fn2.Apply(ObjEngineer )
    
    输出:
       程序员努力的一天

    是不是感觉 this.name 的值被 ObjEnginner中的 name给覆盖了呢,就是的。

    解刨一下原理:

    自定一个 myCall吧,把 myCall 挂载到 Function上,这样每个函数都可以使用myCall

    Function.prototype.myCall = function(context){ 
        context.fn = this; //这里的this是指谁调用 myCall 就指向谁,比如: b.myCall ,这个 this 就指向 b
        context.fn();
        delete context.fn;
     }

    上面代码是先给context对象添加一个 fn的函数,把外面调用 myCall的函数传给 context.fn, 当 context.fn() 执行完之后就可以把他删除掉了不用了。 

    如果带有参数的方式呢? 

    升级一下

     Function.prototype.myCall = function(context,arr){
        let fn = Symbol() //ES6中的Symbol唯一性,就是防止 this中的函数明和 自定的函数明(fn)重名
        context[fn] = this; //this 指向调用者,比如下面的fn2
        context[fn](...arr); //传递参数
        delete context[fn];
     }
    
     var ObjEngineer = {
        name:'程序员努力的一天',
        age:19
     };
    
     function fn2(age,email) {
         console.log(this.name+" 年龄:"+age+" Email: "+email);
     }
    
     fn2.myCall(ObjEngineer,[19,'189@qq.com']) //第二个参数接收数组方式

    输出:

    程序员努力的一天 年龄:19 Email: 189@qq.com

    如果调用的函数有返回值咋办?

     在升级一下

     Function.prototype.myCall = function(context,arr){
        let fn = Symbol() //ES6中的Symbol唯一性,就是防止 this中的函数明和 自定的函数明(fn)重名
        context[fn] = this;
        let res = context[fn](...arr); //传递参数
        delete context[fn];
        return res;
     }
    
     var ObjEngineer = {
        name:'程序员努力的一天',
        age:19
     };
    
     //带有返回值的
     function fn2(age,email) {
         console.log(this.name+" 年龄:"+age+" Email: "+email);
         return {age,email} 
     }
    
     let res = fn2.myCall(ObjEngineer,[19,'189@qq.com']) //第二个参数接收数组方式
     console.log(res);
     

    输出:

    程序员努力的一天 年龄:19 Email: 189@qq.com
    {age: 19, email: '189@qq.com'}

    上面的myCall还不够完善,当没有 obj 和 arr 参数的时候就有问题,在完善一下。

     Function.prototype.myCall = function(context,arr){
        context = context || window //没有contenxt的时候,就指向window
        let fn = Symbol() //ES6中的Symbol唯一性,就是防止 this中的函数明和 自定的函数明(fn)重名
        context[fn] = this;
        let res =  !arr ? context[fn]() : context[fn](...arr); //传递参数,没有参数的时候也要处理一下
        delete context[fn];
        return res;
     }

    参考:https://www.bilibili.com/video/BV1s3411g7gU/?spm_id_from=333.337.search-card.all.click&vd_source=02f2aad32c21e62474c9d52666b96f92

    https://www.cnblogs.com/GoodPingGe/p/16145199.html

  • 相关阅读:
    setTimeout和setInterval的使用
    (7)javascript的程序控制结构及语句------(2)循环控制语句、跳转语句、对话框
    (6)javascript的程序控制结构及语句-----(1)条件判断
    (5)Javascript的表达式
    (4)javascript的运算符以及运算符的优先级
    (3)javascript的数据类型
    (2)javascript的基本语法、数据结构、变量
    (1)认识javascript
    (14)网页布局剖析与制作(下)
    (13)网页布局剖析与制作(上)
  • 原文地址:https://www.cnblogs.com/youmingkuang/p/16745448.html
Copyright © 2020-2023  润新知