JavaScript手写系列之call
/** * @author haiyuan.wang * @date 2021.04.01 * @vision 1.0 * * @description call 方法主要的作用是改变函数的执行环境 * @example fn.call(thisArg, arg1, arg2, ...) * @param {Object} thisArg 必选的。运行时的 this 值,非严格模式下,null 和 undefined 会自动指向 window * @param {*} arg1, arg2, ... 可选的。执行过程中要传入的参数 */ // 第一个例子,使用 call 方法调用父构造方法,实现继承 // 基类 Goods function Goods(goods, amount, price) { this.goods = goods this.amount = amount this.price = price } // 子类,继承基类的属性 function Fruit(goods, amount, price) { Goods.call(this, goods, amount, price) } let fruit = new Fruit('orange', 100, 50) console.log('fruit :>> ', fruit); // Fruit { goods: 'orange', amount: 100, price: 50 } // 第二个例子,使用 call 调用函数的,并且指定上下文的 this let tempObj = { language: 'JavaScript', } function getLanguage() { return this.language } console.log(getLanguage.call(tempObj)); // JavaScript // 实现一个自己的 call 方法 ;(function() { if(!Function.prototype.myCall) { // 给 Fuction 类的原型上加 myCall 属性 Function.prototype.myCall = function myCall(context, ...args) { let fn = this; // 谁调用myCall谁就是this,所以this就是原函数 console.log(fn); // getLanguage 函数 if(typeof fn !== 'function') throw TypeError `${fn} is not a funtion` // 如果不是函数,抛出一个类型错误 let key = Symbol('key') if (typeof context === 'undefined' || context === null) { // 判断是否是undefined和null context = window } context[key] = fn // 将 fn 挂在到 context 的属性上,通过 context.fn() 这种形式调用,就实现了改变this(谁调用fn,谁就是this) let result = context[key](...args) delete context[key] return result } } })() console.log(getLanguage.myCall(tempObj)); // JavaScript // console.log(/sdf/.myCall(tempObj)); // /sdf/.myCall is not a function // 复杂数据类型 Object: Date regExp function Array // 基本数据类型: string number Boolean null undefined