08-12 call-apply的总结

  • call,apply作用:改变this指向
  • 两者区别就是传参:call传参数直接写,apply传参要用数组包起来
  • call,apply应用场景:

js继承:子构造函数通过调用父构造函数的 call 方法来实现继承

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

function Toy(name, price) {
  Product.call(this, name, price);
  this.category = 'toy';
}

var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);

判断复杂数据类型对象/数组(typeof 对{ },[ ]都是返回结果Obejct)

//typeof [] //object
   //typeof {} //object
   console.log(Object.prototype.toString.call({}) === '[object Object]') //[object Object]
   console.log(Object.prototype.toString.call([]) === '[object Array]') //[object Array]

es5 把伪数组转换成数组

 //伪数组转数组
    function get() {
        console.log(arguments)
        console.log([...arguments])
        console.log(Array.prototype.slice.call(arguments))
        console.log(Array.from(arguments))
    }
    get(1,2,3)
  • 手写call方法
// call作用 改变this指向
    let person = {
        getName:function () {
            return this.name
        }
    }

    //实现手写call
    // function myCall(obj) {
    //    直接声明是不行的,getName这个函数对象里找不到这个属性
    // }

    //解决:对函数对象的原型链添加新的属性myCall
    //参数接受的是改变this指向的参数
    Function.prototype.myCall = function (context) {
        //这里面的this是谁?(getName进行调用,因此正常情况下是getName自身,也就是function)
        //这里的this必须是一个function
        console.log(typeof this)//function
        if (typeof this !== 'function'){
            throw new Error('error')
        }

        console.log(...arguments)//这里是获取了全部的参数
        //按照call里的参数获取,我们需要拿到除了第一个参数之外的参数
        let args = [...arguments].slice(1)

        context = {...context} || window//避免对象浅复制的问题
        //在传入的对象里,假设有一个方法
        context.tmp = this //显式改变指向
        return context.tmp(...args)
    }
    let p = {
        name:'sikara'
    }
    console.log(person.getName.call(p))
    

    console.log(person.getName.myCall(p,1,2,3))
    console.log(p)
  • 手写apply
 //手写apply
    Function.prototype.myApply = function (context) {
        //这里面的this是谁?(getName进行调用,因此正常情况下是getName自身,也就是function)
        //这里的this必须是一个function
        if (typeof this !== 'function'){
            throw new Error('error')
        }

        console.log(...arguments)//这里是获取了全部的参数

        let res

        //在传入的对象里,假设有一个方法
        context.tmp = this //显式改变指向

        if (arguments[1]){
            res = context.tmp(...arguments[1])
        }else {
            res = context.tmp()
        }
        
        delete context.tmp //删除对象属性,保证代码严谨
        return res
    }