1.Promise
class Promise {
constructor(fn) {
// 三个状态
this.state = 'pending'
this.value = undefined
this.reason = undefined
let resolve = value => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
}
}
let reject = value => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = value
}
}
// 自动执行函数
try {
fn(resolve, reject)
} catch (e) {
reject(e)
}
}
// then
then (onFulfilled, onRejected) {
switch (this.state) {
case 'fulfilled':
onFulfilled(this.value)
break
case 'rejected':
onRejected(this.value)
break
default:
}
}
}
2.new
function newOperator (constructor, ...args) {
// 创建一个空的对象,并链接该对象到构造函数的原型
const obj = Object.create(constructor.prototype);
// 将构造函数的作用域赋给新对象(即绑定构造函数内部的this)
const result = constructor.apply(obj, args);
// 如果构造函数返回一个对象,则返回这个对象
// 注意,如果构造函数返回的是一个非原始类型的值,则无视它
return result instanceof Object ? result : obj;
}
function Person (name, age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function () {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};
const person = newOperator(Person, 'Alice', 30);
person.greet();
console.log("🚀 ~ person:", person)
3.call,参数是以逗号分开的
//实现一个 call 函数
Function.prototype.myCall = function (context) {
if (typeof this !== 'function') {
throw new TypeError('Error');
}
context = context || global;
// 将当前函数(被.myCall调用的函数)作为context的一个临时属性
context.fn = this;
//slice(1) 方法去掉第一个参数,因为在 myCall 函数中第一个参数是指定的 context,后面的参数才是传递给目标函数的参数。
let args = [...arguments].slice(1);
console.log("🚀 ~ ...arguments:", [...arguments].slice(1), args)
let result = context.fn(...args);
delete context.fn;
return result;
}
// 测试函数
function greet (greeting, name,age) {
console.log(greeting, name,age);
}
// 使用自定义的 myCall 方法,并且传递参数
greet.myCall(null, 'Hello', 'Alice','18'); // 打印:['Hello', 'Alice']
4.apply,参数是一个数组
Function.prototype.myApply = function (context, argsArray) {
if (typeof this !== 'function') {
throw new TypeError('Error');
}
context = context || global;
const fnKey = Symbol(); // 创建唯一键,防止属性冲突
context[fnKey] = this;
let result;
if (Array.isArray(argsArray)) {
result = context[fnKey](...argsArray); // 使用展开语法调用函数
} else {
result = context[fnKey](); // 如果没有提供参数或者参数为null/undefined,直接调用函数
}
delete context[fnKey]; // 删除添加的属性
return result;
}
// 示例
function greet(greeting, name) {
console.log(greeting, name);
}
const person = { name: 'John' };
greet.myApply(person, ['Hello', 'Alice']);
5.bind类似call,但返回的是函数
// 思路:类似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))
}
}
}
三种的区别
6.递归拷贝
function deepClone(obj) {
let copy = obj instanceof Array ? [] : {}
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
copy[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
}
}
return copy
}