new方法
- 创建一个新对象且将其隐式原型__proto__指向构造函数原型
- 执行构造函数修改this指向
- 返回该对象
function myNew(fun){
return (...args)=>{
let obj = {
__proto__:fun.prototype
};
fun.call(obj,...args);
return obj;
}
}
apply
- 将要修改this方法的函数绑定到传入的对象上并且执行绑定的函数 、
核心内容
// 为了让所有函数都有该方法,所以需要绑定到Function的原型上
Function.prototype.myApply = function(context){
context.fn = this; // 为了让函数中的this指向传入的对象,需要让对象来调用该方法
context.fn(...arguments[1])
return res;
}
完整实现
Function.prototype.myApply = function(context){
// 判断调用者是否为函数
if(typeof this !=='function'){
throw new TypeError('not function')
}
context = context || window;
context.fn = this; // 为了让函数中的this指向传入的对象,需要让对象来调用该方法
let res = null;
if(arguments[1]){
res = context.fn(...arguments[1])
}else{
res = context.fn();
}
// 删除绑定
delete context.fn;
return res;
}
call
- 与apply的区别就是传参的方式不一样,apply第二个参数是数组,call方法是一个个的传递
核心内容
// 将方法挂载到目标上执行并返回
Function.prototype.mycall = function(context){
console.log(arguments); // {0:{name:bonly},1:1,2:2}
console.log(...arguments); // { name: 'bonly' } 1 2 3
console.log([...arguments].slice(1)); // [1,2,3]
let args = [...arguments].slice(1);
context.fn = this;
context.fn(...args);
}
完整版
// 思路:将要改变this指向的方法挂到目标this上执行并返回
Function.prototype.mycall = function (context) {
if (typeof this !== 'function') {
throw new TypeError('not funciton')
}
context = context || window
context.fn = this
let arg = [...arguments].slice(1)
let result = context.fn(...arg)
delete context.fn
return result
}
bind
- 与call和apply的不同就是只是修改this指向,并且返回函数等待执行
核心内容
Function.prototype.myBind = function(context){
context.fn = this;
return () => {
let args = [...arguments].slice(1);
context.fn(...args);
}
}
完整版
// 思路:类似call,但返回的是函数
Function.prototype.mybind = function (context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
let _this = this
let arg = [...arguments].slice(1)
return function F() {
// 处理函数使用new的情况
if (this instanceof F) {
return new _this(...arg, ...arguments)
} else {
return _this.apply(context, arg.concat(...arguments))
}
}
}