1、手写深拷贝
function deepClone(obj = {}) {
if (typeof obj != "object" || obj == null) {
return obj;
}
let result;
if (obj instanceof Array) {
result = [];
} else {
result = {};
}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key]);
}
}
return result;
}
2、用class实现继承
class Person {
constructor(name) {
this.name = name;
}
say() {
console.log(`hi,${this.name}`);
}
}
class Student extends Person {
constructor(name, subject) {
super(name);
this.subject = subject;
}
study() {
console.log(`${this.name}学习${this.subject}`);
}
}
class Teacher extends Person {
constructor(name, subject) {
super(name);
this.subject = subject;
}
teach() {
console.log(`${this.name}老师教${this.subject}`);
}
}
let laowang = new Teacher('老王','数学')
let xiaowang = new Student('小王','英语')
laowang.__proto__ === Teacher.prototype; // true
Person.prototype === Teacher.prototype.__proto__; // true
3、闭包
闭包:自由变量的查找,是在函数定义的地方,向上级作用域查找不是在执行的地方查找
例如:
函数作为返回值
function returnFn() {
let a = 100;
return function () {
console.log(a);
};
}
let fn = returnFn();
let a = 200;
fn(); // 100
函数作为参数传递
function consoleFn(fn) {
let a = 100;
fn();
}
let a = 200;
function fn() {
console.log(a);
}
consoleFn(fn); // 200
4、this的不同应用场景,如何取值?
当做普通函数被调用(window)
使用call apply bind (改变了this指向)
作为对象方法调用(对象他本身)
在class的方法中调用(当前实例的本身)
箭头函数(他上级作用域去找)
5、手写bind函数
function fn1(a, b, c) {
console.log("this", this);
console.log(a, b, c);
return "this fn1";
}
Function.prototype.bind1 = function () {
let args = Array.prototype.slice.call(arguments);
let t = args.shift(); // 取出this
let self = this; // fn(被执行的函数)
return function () {
return self.apply(t, args);
};
};
let fn2 = fn1.bind({ x: 100 }, 1, 2, 3);
fn2();
let fn3 = fn1.bind1({ x: 200 }, 2, 3, 4);
fn3();
6、promise加载图片
function loadImg(src) {
return new Promise((resolve, reject) => {
let img = document.createElement("img");
img.onload = () => {
resolve(img);
};
img.onerror = () => {
let err = new Error(`图片加载失败${src}`);
reject(err);
};
img.src = src;
});
}
7、手写快速排序
function quickSort(arr = []) {
if (arr.length < 2) {
return arr;
}
let benchmark = arr.shift();
let len = arr.length;
let left = [];
let right = [];
for (let i = 0; i < len; i++) {
if (arr[i] < benchmark) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
function merge(left, benchmark, right) {
return [...left, benchmark, ...right];
}
return merge(quickSort(left), benchmark, quickSort(right));
}
8、选择排序
function selectSort(arr = []) {
if (arr.length < 2) return arr;
let temp = [...arr];
for (let i = 0; i < temp.length - 1; i++) {
let minIndex = i;
for (let j = i + 1; j < temp.length; j++) {
if (temp[minIndex] > temp[j]) {
minIndex = j;
}
}
[temp[i], temp[minIndex]] = [temp[minIndex], temp[i]];
}
return temp;
}
9、插入排序
function insertSort(arr = []) {
if (arr.length < 2) return arr;
let temp = [...arr];
let preIndex = 0;
let currentValeu = temp[0];
for (let i = 1; i < temp.length; i++) {
preIndex = i - 1;
currentValeu = temp[i];
while (preIndex >= 0 && temp[preIndex] > currentValeu) {
temp[preIndex + 1] = temp[preIndex];
preIndex--;
}
temp[preIndex + 1] = currentValeu;
}
return temp;
}
10、冒泡排序
function bubbleSort(arr = []) {
if (arr.length < 2) return arr;
let temp = [...arr];
for (let i = 0; i < temp.length - 1; i++) {
for (let j = 0; j < temp.length - 1 - i; j++) {
if (temp[j] > temp[j + 1]) {
[temp[j], temp[j + 1]] = [temp[j + 1], temp[j]];
}
}
}
return temp;
}
11、判断json环
function hasSycle(obj) {
let arr = [];
let ret = false;
function judge(obj) {
for (let key in obj) {
let value = obj[key];
if (typeof value == "object" && value != null) {
if (arr.includes(value)) {
ret = true;
console.log(1, '"object"')
} else {
arr.push(value);
judge(value);
}
}
}
}
judge(obj);
return ret;
}
12、手写call函数
Function.prototype.myCall = function (context, ...args) {
context.fn = this; // fn(被执行的函数)
console.log(context, args);
let ret = args.length > 1 ? context.fn(...args) : context.fn();
delete context.fn;
return ret;
};
function fn1(a, b, c) {
console.log("this", this);
console.log(a, b, c);
return "this fn1";
}
fn1.myCall({ x: 100 }, 1, 2, 3);
13、add(1)(2)(3,4)
function add() {
let args = Array.prototype.slice.call(arguments);
let fn = function () {
let arg_fn = Array.prototype.slice.call(arguments);
return add.apply(null, args.concat(arg_fn));
}
fn.toString = function () {
return args.reduce(function (a, b) {
return a + b;
})
}
return fn;
}
14、自定义事件监听
class EventListeners {
constructor() {
this.events = {};
}
$on(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = callback;
} else {
console.error('已存在相同事件,请重新定义')
}
}
$emit(eventName, ...args) {
this.events[eventName].apply(this, args);
}
$once(eventName, callback) {
const self = this
function fn() {
self.$off(eventName)
callback.apply(self, arguments)
}
this.$on(eventName, fn)
}
$off(eventName) {
delete this.events[eventName]
}
}
15、时间格式化
function timeFormat(timestamp = null, fmt = "yyyy-mm-dd") {
timestamp = parseInt(timestamp);
// 如果为null,则格式化当前时间
if (!timestamp) timestamp = Number(new Date());
if (timestamp.toString().length == 10) timestamp *= 1000;
let date = new Date(timestamp);
let ret;
let opt = {
"y+": date.getFullYear().toString(), // 年
"m+": (date.getMonth() + 1).toString(), // 月
"d+": date.getDate().toString(), // 日
"h+": date.getHours().toString(), // 时
"M+": date.getMinutes().toString(), // 分
"s+": date.getSeconds().toString(), // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(
ret[1],
ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, "0")
);
}
}
return fmt;
}
16、手写promise
const statusPending = 'pending'
const statusFulfilled = 'fulfilled'
const statusRejected = 'rejected'
class MyPromise {
value = undefined // 成功返回值
reason = undefined// 失败返回值
successCallbacks = [] //pending时 成功回调函数存储
failCallbacks = [] // pending时 失败回调函数存储
status = statusPending
constructor(fn) {
const resolveFun = (value) => {
if (this.status === statusPending) {
this.value = value
this.status = statusFulfilled
this.successCallbacks.forEach(fn => fn(this.value))
}
}
const rejectFun = (reason) => {
if (this.status === statusPending) {
this.reason = reason
this.status = statusRejected
this.failCallbacks.forEach(fn => fn(this.reason))
}
}
try {
fn(resolveFun, rejectFun)
} catch (error) {
rejectFun(error)
}
}
then(fn1, fn2) {
fn1 = typeof fn1 === "function" ? fn1 : (e) => { e }
fn2 = typeof fn2 === "function" ? fn2 : (e) => { e }
return new MyPromise((resolve, reject) => {
const fn3 = () => {
try {
let res = fn1(this.value)
resolve(res)
} catch (error) {
reject(error)
}
}
const fn4 = () => {
try {
let res = fn1(this.reason)
reject(res)
} catch (error) {
reject(error)
}
}
if (this.status == statusPending) {
this.successCallbacks.push(() => {
fn3()
})
this.failCallbacks.push(() => {
fn4()
})
}
if (this.status == statusFulfilled) {
fn3()
}
if (this.status == statusRejected) {
fn4()
}
})
}
catch(fn) {
return this.then(null, fn)
}
finally(fn) {
return this.then(val => {
fn()
return val
}).catch((err) => {
fn()
return err
})
}
}
MyPromise.resolve = (value) => {
return new MyPromise((
resolve, reject
) => {
resolve(value)
})
}
MyPromise.reject = (reason) => {
return new MyPromise((
resolve, reject
) => {
reject(reason)
})
}
MyPromise.all = (promiseList = []) => {
return new MyPromise((resolve, reject) => {
const resP = []// 存储promiseList 结果
const len = promiseList.length
let resolveedCount = 0
promiseList.forEach((p) => {
p.then(data => {
resP.push(data)
resolveedCount++
if (resolveedCount == len) {
resolve(resP)
}
}).catch(err => {
reject(err)
})
})
})
}
MyPromise.race = (promiseList = []) => {
return new MyPromise((resolve, reject) => {
let resolved = false
promiseList.forEach((p) => {
p.then(data => {
if (!resolved) {
resolve(data)
resolved = true
}
}).catch(err => {
reject(err)
})
})
})
}