zoukankan      html  css  js  c++  java
  • 模拟实现js的call和apply

    call方法

    call() 方法在使用一个指定的this和若干个指定的参数值的前提下调用某个函数或方法。

    call的使用

    /* 
    *   call语法  
    *   function.call(thisArg, arg1, arg2, ...)
    *   thisArg 可选参数,在function函数运行时的this值。注意 this可能不是该方法看到的实际值:如果这个函数处于非严格模式,则指定
    *   为null或者undefined时会自动替换为指向全局对象,原始值会被包装
    *   (数字,字符串,布尔值)的this会执行该原始值的自动包装对象
    *   
    *   arg1,arg2... 指定的参数列表
    */
    
    function greet() {
        let reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' ')
        console.log(reply)
    }
    
    let obj = {
        animal: 'cats',
        sleepDuration: '12 and 16 huors'
    }
    
    greet.call(obj);          // cat typically sleep between 12 and 16 hours
    

    call方法的实现

    Function.prototype.callFn = function(context){
        // 只有function类型才可以调用call方法
        if(typeof this !== 'function'){
            throw new TypeError('must be function')
        }
    
        // 有context时,指定为context,没有指向全局对象,浏览器里为
        // windows,node下需要修改为global
        context = context ? Object(context) : window
        // context = context ? Object(context) : global
    
        // 此时的this为调用callFn方法的函数的this 
        context.fn = this;
    
        // 取出函数执行需要的参数
        let args = [...arguments].slice(1)
        
        let r = context.fn(args)
    
        delete context.fn
    
        return r
    }
    
    // test
    let value = 2;
    
    let obj = {
        value: 1
    }
    
    function bar(name, age) {
        console.log(this.value);
        return {
            value: this.value,
            name: name,
            age: age
        }
    }
    
    bar.callFn(null); // 2
    
    console.log(bar.callFn(obj, 'kevin', 18));
    // 1
    // Object {
    //    value: 1,
    //    name: 'kevin',
    //    age: 18
    // }
    

    apply方法

    call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。

    /* func.apply(thisArg, [argsArray])
    参数
    thisArg
    必选的。在 func 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:
    如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对
    象,原始值会被包装。
    argsArray
    可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果
    该参数的值为 null 或  undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可
    以使用类数组对象。
    */
    
    window.val = 'window'
    var obj = {
     val: 'obj'
    }
    function getVal(p1, p2) {
      console.log(p1, p2)
      console.log(this.val)
    }
    getVal('param1', 'param2')       // param1,param2,window
    getVal.apply(obj, ['param1', 'param2'])   // param1,param2,obj
    

    apply实现

    Function.prototype.applyFn = function(context) {
        if (typeof this !== 'function') {
          throw new TypeError('Error')
        }
        context = context || window
        // context = context || global    // node环境下
        context.fn = this
        let result
    
        if (arguments[1]) {
          result = context.fn(...arguments[1])
        } else {
          result = context.fn()
        }
        delete context.fn
        return result
    }
      
    // test node环境测试
    global.val = 'window'
    var obj = {
     val: 'obj'
    }
    function getVal(p1, p2) {
      console.log(p1, p2)
      console.log(this.val)
    }
    getVal('param1', 'param2') 
    getVal.apply(obj, ['param1', 'param2'])
    

    参考文章: https://juejin.im/post/5c4592faf265da617265c60b#heading-2
    参考文章: https://segmentfault.com/a/1190000017206223
    参考文章: https://github.com/mqyqingfeng/Blog/issues/11

  • 相关阅读:
    走线规范-标识
    python学习之网路操作
    python学习之函数
    RTT学习之软件包
    RT_THREAD之组件学习
    RT_THREAD之nano学习
    物联网相关的模块
    JavaScript学习笔记之二
    javascript完美实现图片拖动改变顺序
    响应式WEB设计的9项基本原则
  • 原文地址:https://www.cnblogs.com/qiqiloved/p/13475780.html
Copyright © 2011-2022 走看看