手写call
call的核心是改变了函数的this指向,最简单的实现方法,就是把要执行的函数作为要call的目标的方式使用,上代码
//这里不能用箭头函数哦,因为箭头函数没有this,会导致错误
Function.prototype.myCall = function(thisArg, ...args) {
//thisArg是要改变this指向的目标
//this指向调用myCall的函数
const func = this
if (typeof thisArg === "undefined" || thisArg === null) {
//thisArg是null或者undefined直接执行func
func(...args)
return false;
}
//将函数作为thisArg的方法
thisArg.func = func
//接受func的返回值
const result = thisArg.func(...args)
//删掉func方法
delete thisArg.func
return result
}
但是这里还是有一点小问题,如果thisArg.func本来就存在呢,那么在我们给func属性赋值时,会把原有的值覆盖掉,所以利用原始数据类型Symbol(Symbol表示独一无二的值,最大的用法是用来定义对象的唯一属性名)来解决这个问题
//这里不能用箭头函数哦,因为箭头函数没有this,会导致错误
Function.prototype.myCall = function(thisArg, ...args) {
//thisArg是要改变this指向的目标
//this指向调用myCall的函数
const func = this
if (typeof thisArg === "undefined" || thisArg === null) {
//thisArg是null或者undefined直接执行func
func(...args)
return false;
}
//我symbol是独一无二哒
const func = Symbol['func'];
//将函数作为thisArg的方法
thisArg[func] = func;
//接受func的返回值
const result = thisArg[func](...args)
//删掉func方法
delete thisArg[func]
return result
}
手写apply
apply很简单,就把形参改改就行了
Function.prototype.myApply = function(thisArg, args) {
......
}
手写bind
bind方法返回的是一个函数,可以再传参
Function.prototype.myBind = function(thisArg, ...args) {
const func = this;
const reFunc = function(...args1) {
args = [...args, ...args1];
func.myCall(thisArg, ...args);
};
return reFunc;
}
手写new
new是运算符,所以这里只是采用函数的方式实现new的功能,先分析一下new的具体作用
- 创建一个新对象,并让这个对象的__proto__指向构造函数的prototype原型对象
- 执行构造函数,并让其this指向对象
- 根据构造函数return的值决定最终返回的值,这里不多说,后面代码再细说
const myNew = (func,...arg)=>{
//创建一个新对象,让其__proto__等于构造函数的原型对象prototype
const obj = Object.create(func.prototype)
//执行构造函数func,并让其this指向obj
const result = func.call(obj,...arg)
const isFunOrObj = (typeof result !==null&&typeof result ==="object")||typeof result==="function"
//如果构造函数return了object和function,则直接返回这这个值否则返回实例对象
return isFunOrObj?result:obj
}