call、bind、apply的区别
- call、bind、apply都是函数原型上的方法,作用都是改变函数调用的this指向
- call和apply传的参数类型不同,apply接收的是个参数数组,call可以接收多个参数,call的执行效率更高
- call和apply调用后会立即执行,bind会绑定函数的this指向,不会立即执行,只对第一次绑定的生效
Apply
- call和apply的实现原理类似,
- 给传入的context对象上添加fn属性,指向当前调用的方法this
- 调用当前方法,并传入参数
- 删除context对象上添加的fn属性,返回执行结果
Function.prototype.apply = function (context = window, args) {
context.fn = this;
const result = context.fn(...args);
delete context.fn
return result;
}
Call
Function.prototype.call = function (context = window, ...args) {
context.fn = this;
const result = context.fn(...args);
delete context.fn
return result;
}
bind
Function.prototype.bind = function(target, ...args){
return (...args2) => {
this.call(target,...args,...args2)
}
}
deepClone
- 遍历对象的属性,如果属性值是基本数据类型或null,则直接返回
- 如果属性值是引用数据类型,则递归调用
function clone(obj){
if(obj === null || typeof obj !== 'object') return
const newObj = new obj.constructor();
for(let key in Object.getOwnPropertyDescriptors(obj)){
newObj[key] = clone(obj[key]);
}
return newObj;
}
深度比较两个对象
/**
* 深度比较两个对象
* @param {*} a, b 要比较的两个对象
*/
function deepCompare(a, b) {
if ([a, b].includes(null) || [typeof a, typeof b].includes("object"))
return a === b;
const propsA = Object.getOwnPropertyDescriptors(a);
const propsB = Object.getOwnPropertyDescriptors(b);
if (Object.keys(propsA).length !== Object.keys(propsB).length) return false;
return Object.keys(propsA).every((key) => deepCompare(a[key], b[key]));
}
函数柯理化
- 判断函数参数的个数,如果达到,就返回执行结果,否则继续返回curry函数
function curry(fn, ...args){
return args.length < fn.length ?
(...extraArgs) => curry(fn, ...args, ...extraArgs)
: fn(...args);
}
function addFn(a, b, c, d, e){
return a + b + c + d + e;
}
const add = curry(addFn);
console.log(add(1, 2, 3, 4, 5))
console.log(add(1, 2)(3, 4)(5))
console.log(add(1)(2)(3)(4)(5))
深度优先遍历
- 递归实现
/**
* 数据结构
* 0
* 1 2 3
* / \ | |
* 4 5 6 7
* 深度优先: 0, 1, 4, 5, 2, 6, 3, 7
* 广度优先: 0, 1, 2, 3, 4, 5, 6, 7
*/
const rootNode = {
id: 0,
children: [
{
children: [
{ id: 4, title: "node" },
{ id: 5, title: "node" },
],
id: 1,
title: "node",
},
{
children: [{ id: 6, title: "node" }],
id: 2,
title: "node",
},
{
children: [{ id: 7, title: "node" }],
id: 3,
title: "node",
},
],
};
/**
* 深度优先
* @param node
* @param ids
*/
function deepSearch(node: any, ids: number[] = []) {
ids.push(node.id);
if (node.children && node.children.length) {
node.children.forEach((n) => {
deepSearch(n, ids);
});
}
}
const deepRes = [];
deepSearch(rootNode, deepRes);
console.log("深度优先", deepRes);
广度优先遍历
- 栈型结构实现
/**
* 广度优先
* @param root
*/
function wideSearch(root: any) {
const ids: number[] = [];
const stack = [root];
while (stack.length) {
const node = stack.shift();
ids.push(node.id);
if (node.children && node.children.length) {
stack.push(...node.children);
}
}
return ids;
}
console.log("广度优先", wideSearch(rootNode));
构造斐波那契数列
function getFbnq(length: number) {
let a = 1;
let b = 2;
let arr = [a, b];
while (arr.length < length) {
const temp = a;
a = b;
b = temp + b;
arr.push(b);
}
return arr;
}
console.log(getFbnq(10));
未完待续
防抖、节流、手写promise、koa原理...