new、call、apply、bind的模拟实现
分类:javascript
1. new 的模拟实现
function newFactory(fn,...arguments) {
var obj = {};
obj.__proto__ = fn.prototype;
const ret = fn.call(obj, ...arguments);
return typeof ret === 'object' ? ret : obj;
};
- 创建一个空对象 obj;
- 将新创建的空对象的隐式原型指向其构造函数的显示原型。
- 使用 call 改变 this 的指向
- 如果无返回值或者返回一个非对象值,则将 obj 返回作为新对象;如果返回值是一个新对象的话那么直接直接返回该对象。
验证:
function Person(age, name) {
this.age = age;
this.name = name;
return "new car";
}
var person = newFactory (Person,18, "Tom");
2. call 的模拟实现
Function.prototype.callFun = function (context, ...args) {
var context = context || window;
context.fn = this;
const result = context.fn(...args);
delete context.fn;
return result;
};
- 将函数设为对象的属性
- 执行该函数
- 删除该函数
验证:
const value2 = 2;
const obj2 = {
value: 1
};
function bar(name, age) {
console.log(this.value);
return {
value: this.value,
name: name,
age: age
};
}
console.log(bar.call(obj2, 'kevin', 18]);
3. apply 的模拟实现
apply与call的不同,接收的是数组参数。
Function.prototype.apply = function (context, arr) {
var context = Object(context) || window;
context.fn = this;
var result;
if (!arr) {
result = context.fn();
}
else {
result = context.fn(...arr);
}
delete context.fn
return result;
}
验证:
const value2 = 2;
const obj2 = {
value: 1
};
function bar(name, age) {
console.log(this.value);
return {
value: this.value,
name: name,
age: age
};
}
console.log(bar.apply(obj2, ['kevin', 18]));
4. bind 的模拟实现
bind返回的是一个函数,而不是执行结果。
Function.prototype.bindFun = function (context,...args) {
if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
var self = this;
var fNOP = function () {};
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
bar.bindFun(obj, 'kevin', 18)()
- JavaScript深入之new的模拟实现
- JavaScript深入之call和apply的模拟实现
原文链接:https://juejin.cn/post/6943434817878884382