1.call
let obj = {
name: "vinomars",
};
function getName(p1, p2) {
console.log(this.name);
console.log(p1, p2);
}
getName("p1", "p2");
Function.prototype.myCall = function(context = window, ...args) {
if(typeof this !== 'function') {
throw new TypeError('its not a function')
}
let fn = Symbol()
context[fn] = this;
context[fn](...args);
delete context[fn]
}
getName.myCall(obj, "callp1", "callp2");
2.apply
Function.prototype.myApply = function(context = window, arr) {
if(typeof this !== 'function') {
throw new TypeError('its not a function')
}
if(!Array.isArray) {
throw new TypeError('arr is not an Array')
}
let fn = Symbol()
context[fn] = this;
context[fn](...arr);
delete context[fn]
}
getName.myApply(obj, ["callp1", "callp2"]);
3.bind
Function.prototype.myBind = function (context = window) {
if (typeof this !== "function") {
throw new TypeError("its not a function");
}
let self = this;
let args = [...arguments].slice(1);
return function Fn() {
args = [...args, ...arguments];
if (this instanceof Fn) {
return new self(args);
} else {
return self.apply(context, args);
}
};
};
const getBindName = getName.myBind(obj, "callp1", "callp2");
getBindName()
4.new
const myNew = (fn, ...args) => {
if (typeof fn !== "function") {
throw new TypeError("its not a function");
}
let temp = Object.create(fn.prototype);
let res = fn.apply(temp, args);
return res instanceof Object ? res : temp;
};
const Fn = function (name) {
this.name = name;
};
let _fn = myNew(Fn, "HelloVino");
console.log(_fn.name);
function foo() {
this.name = "ciel";
return function () {};
}
console.log(myNew(foo));
function bar() {
this.name = "ciel";
return 1;
}
console.log(myNew(bar));
5.防抖debounce 场景:输入框输入事件 resize等
const debounce = function (fn, delay, immediate) {
if (typeof fn !== "function") {
throw new TypeError("its not a function");
}
let timer = null;
return function () {
let self = this;
let args = [...arguments];
timer && clearTimeout(timer);
if (immediate) {
let callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, delay);
callNow && fn.apply(self, args);
} else {
timer = setTimeout(() => {
fn.apply(self, args);
}, delay);
}
};
};
6.节流throttle 验证码button点击事件
const throttle = (fn, delay) => {
if (typeof fn !== "function") {
throw new TypeError("its not a function")
}
let timer = null
return function () {
let self = this
let args = [...arguments]
// 只有上一次的动作执行完后才会在setTimeout将timer赋为null
if (timer) return
timer = setTimeout(() => {
fn.apply(self, args)
timer = null
}, delay)
}
}
7.深拷贝deepClone/深比较deepEqual
7.1深拷贝deepClone
const isObject = (obj) => obj && typeof obj === "object";
const isFunction = (fn) => typeof fn === "function";
const deepClone = (target, map = new WeakMap()) => {
if (!isObject(target)) {
return target;
}
if (isFunction(target)) {
return target;
}
let copy = Array.isArray(target) ? [] : {};
if (map.has(target)) {
return map.get(target);
}
map.set(target, copy);
let Constructor = target.constructor;
switch (Constructor) {
case String:
case Number:
case Boolean:
case Date:
case Error:
return new Constructor(target);
}
let len = -1;
let keys = Reflect.ownKeys(target);
let _len = keys.length;
while (++len < _len) {
copy[keys[len]] = deepClone(target[keys[len]], map);
}
return copy;
};
const map = new Map();
map.set("key", "value");
map.set("ConardLi", "code秘密花园");
const set = new Set();
set.add("ConardLi");
set.add("code秘密花园");
const symbolName = Symbol();
const target = {
field1: 1,
field2: undefined,
field3: {
child: "child",
},
field4: [[2], 4, 8],
empty: null,
map,
set,
bool: new Boolean(true),
num: new Number(2),
str: new String(2),
[symbolName]: 111,
date: new Date(),
reg: /\d+/,
error: new Error("error!!!"),
func1: () => {
console.log("code秘密花园");
},
func2: function (a, b) {
return a + b;
},
};
const result = deepClone(target);
console.log(JSON.parse(JSON.stringify(target)))
console.log(result);
7.2 深比较deepEqual
let obj1 = { foo: { b: { foo: { c: { foo: null } } } } };
let obj2 = { foo: { b: { foo: { c: { foo: null } } } } };
const isObject = (obj) =>
obj && (typeof obj === "object" || typeof obj === "function");
const deepEqual = (obj1, obj2, map1 = new WeakMap(), map2 = new WeakMap()) => {
if (obj1 === obj2) {
return obj1 !== 0 || 1 / obj1 === 2 / obj2;
}
if (obj1 !== obj1) {
return obj2 !== obj2;
}
let Ctor = obj1.constructor;
if (obj2.constructor !== Ctor) {
return false;
}
switch (Ctor) {
case String:
case Number:
case Boolean:
case Date:
case Error:
return "" + obj1 === "" + obj2;
}
if (map1.has(obj1) && map2.has(obj2)) {
return true;
}
map1.set(obj1, obj1);
map2.set(obj2, obj2);
if (isObject(obj1) && isObject(obj2)) {
let keys1 = Reflect.ownKeys(obj1);
let keys2 = Reflect.ownKeys(obj2);
if (keys1.length !== keys2.length) {
return false;
}
let len = keys1.length;
while (len--) {
let key = keys1[len];
if (
obj1.hasOwnProperty(key) &&
!deepEqual(obj1[key], obj2[key], map1, map2)
) {
return false;
}
}
return true;
}
return false;
};
console.log(deepEqual(0, -0));
console.log(deepEqual(NaN, NaN));
console.log(deepEqual("Curly", new String("Curly")));
obj1.foo.b.foo.c.foo = obj1;
obj2.foo.b.foo.c.foo = obj2;
console.log(deepEqual(obj1, obj2));
8.排序
8.1 快排quickSort
// 1.找基准值 然后遍历对比 小于基准值放到left中,反之放入right,最后递归
const nums = [5, 4, 3, 0, 0, 2, 1]
const quickSort = (nums) => {
if (!Array.isArray(nums) || nums.length < 2) {
return nums
}
let index = Math.floor(nums.length / 2)
let numsIndex = nums.splice(index, 1)[0]
let left = []
let right = []
let i = 0
while (i < nums.length) {
if (nums[i] > numsIndex) {
right.push(nums[i])
}
if (nums[i] <= numsIndex) {
left.push(nums[i])
}
i++
}
return [...quickSort(left), numsIndex, ...quickSort(right)]
}
console.log("quickSort:", quickSort(nums))
8.2 归并排序mergeSort
// 1.主要思想是不停的去比较left[0]和right[0]
const mergeSort = (arr) => {
if (!Array.isArray(arr)) {
return arr
}
let _len = arr.length
if (_len < 2) {
return arr
}
let _middle = Math.floor(_len / 2)
let left = arr.slice(0, _middle)
let right = arr.slice(_middle, _len)
return merge(mergeSort(left), mergeSort(right))
}
const merge = (left, right) => {
let result = []
while (left.length > 0 && right.length > 0) {
if (left[0] < right[0]) {
result.push(left.shift())
} else {
result.push(right.shift())
}
}
while (left.length > 0) {
result.push(left.shift())
}
while (right.length > 0) {
result.push(right.shift())
}
return result
}
const array = [5, 4, 3, 2, 1]
console.log("mergeSort:", mergeSort(array))
9. Promise
9.1 promise.all
Promise.myAll = function (promises) {
promises = Array.from(promises);
const num = promises.length;
const result = new Array(num);
let resolvedCount = 0;
return new Promise((resolve, reject) => {
promises.map((promise, index) => {
Promise.resolve(promise)
.then((value) => {
result[index] = value;
if (resolvedCount === num) {
resolve(result);
}
})
.catch(reject);
});
});
};
let p1 = 1;
let p2 = Promise.reject(2);
let p3 = Promise.resolve(3);
Promise.myAll([p1, p2, p3])
.then((results) => {
console.log(results);
})
.catch((err) => {
console.log(err);
});
Promise.all([p1, p2, p3])
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
9.2 promise.race
const promiseRace = (arr) => {
return new Promise((resolve, reject) => {
if (!Array.isArray(arr)) {
reject("its not an arr");
}
arr.map((item) => {
Promise.resolve(item).then(
(res) => {
resolve(res);
},
(err) => {
reject(err);
}
);
});
});
};
9.3 promise.finally
class Promise {
finally(callback) {
return this.then(
(res) => {
return Promise.resolve(callback()).then(() => res);
},
(err) => {
return Promise.resolve(callback()).then(() => {
throw err;
});
}
);
}
}
9.4 promise.allSettled
const formatSettledResult = (success, value) =>
success
? { status: "fulfilled", value }
: { status: "rejected", reason: value };
Promise.allSettled = function (promises) {
return new Promise((resolve, reject) => {
promises = Array.from(promises);
let len = promises.length;
let results = new Array(len);
let settledCount = 0;
promises.map((promise, index) => {
Promise.resolve(promise)
.then((res) => {
results[index] = formatSettledResult(true, res);
++settledCount === len && resolve(results);
})
.catch((err) => {
results[index] = formatSettledResult(false, err);
++settledCount === len && resolve(results);
});
});
});
};
const PromiseArray = [
Promise.resolve(100),
Promise.reject(null),
Promise.resolve("Data release"),
Promise.reject(new Error("Something went wrong")),
];
Promise.allSettled(PromiseArray)
.then((res) => {
console.log(res);
})
.catch((err) => console.log(err));
9.5 promise.retry
Promise.retry = (fn, times, delay) => {
return new Promise((resolve, reject) => {
let error;
const attempt = () => {
if (times === 0) {
reject(error);
} else {
fn()
.then(resolve)
.catch((err) => {
error = err;
times--;
setTimeout(() => {
attempt();
}, delay);
});
}
};
attempt();
});
};
function fn() {
let p = new Promise(function (resolve, reject) {
setTimeout(function () {
var num = Math.ceil(Math.random() * 20);
console.log("随机数生成的值:", num);
if (num <= 5) {
console.log("符合条件,值为" + num);
resolve(num);
} else {
reject("数字大于5,执行失败");
}
}, 2000);
});
return p;
}
Promise.retry(fn, 3, 100);
9.6 promisily
const promisify = (fn) => {
return function (...args) {
return new Promise((resolve, reject) => {
fn.apply(this, [
...args,
(callback = (err, ...values) => {
return err ? reject(err) : resolve(...values);
}),
]);
});
};
};
var func1 = function (a, b, c, callback) {
callback(null, a + b + c);
};
var func2 = promisify(func1);
func1(1, 2, 3, (err, result) => {
if (!err) {
console.log(result);
}
});
func2(1, 2, 3).then(console.log);
10.扁平化数组
const flattern = (arr) => {
if (!Array.isArray(arr)) {
return arr;
}
let res = [];
arr.map((item) => {
if (Array.isArray(item)) {
res = [...res, ...flattern(item)];
} else {
res.push(item);
}
});
return res;
};
const flattern1 = (arr) => {
return arr.reduce((prev, next) => {
return [...prev, ...(Array.isArray(next) ? flattern1(next) : [next])];
}, []);
};
const flattern2 = (arr) => {
while (arr.some((item) => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
};
var arr = [1, [2, [3, 4]], 56, [123, [22, [33333, [121212, [122122]]]]]];
console.log(flattern2(arr));
11.柯里化累加
const add = (...args) => {
return args.reduce((prev, next) => {
return prev + next;
});
};
const curry = (fn) => {
if (typeof fn !== "function") {
throw new TypeError("its not a function");
}
let args = [];
return function temp(...newArgs) {
if (newArgs.length > 0) {
args = [...args, ...newArgs];
return temp;
} else {
return fn.apply(this, args);
}
};
};
let curryAdd = curry(add)
console.log(curryAdd(11,2)(3)(111)(2,33)())
12.lodash get
const obj = {
selector: { to: { toutiao: "FE Coder" } },
target: [1, 2, { name: "byted" }],
}
const myGet = (obj, ...args) => {
if (Object.prototype.toString.call(obj) !== "[object Object]") {
return obj
}
try {
// 正则 检测表达式是否含有[number]
const reg = /\[[0-9]+\]/gi
let result = []
args.map((item) => {
let paths = item.split(".")
let res = obj
paths.map((path) => {
if (reg.test(path)) {
// match的结果为[[0]]
let match = path.match(reg)[0]
let prev = path.replace(match, "")
// 获取[number]中的数字
let last = match.replace(/\[|\]/gi, "")
res = res[prev][last]
} else {
res = res[path]
}
})
result.push(res)
})
return result
} catch (err) {
return undefined
}
}
// test
console.log(myGet(obj, "selector.to.toutiao", "target[0]", "target[2].name"))
// [ 'FE Coder', 1, 'byted']
13.LazyMan
class LazyManClass {
constructor(name) {
this.tasks = [];
console.log(`Hi I am ${name}`);
setTimeout(() => {
this.next();
}, 0);
}
next() {
let fn = this.tasks.shift();
fn && fn();
}
eat(name) {
let fn = () => {
console.log(`I am eating ${name}`);
this.next();
};
this.tasks.push(fn);
return this;
}
sleep(time) {
this.wrappedSleep(false, time);
return this;
}
sleepFirst(time) {
this.wrappedSleep(true, time);
return this;
}
wrappedSleep(first, time) {
let fn = () => {
setTimeout(() => {
console.log(`等待了${time}秒...`);
this.next();
}, time * 1000);
};
first ? this.tasks.unshift(fn) : this.tasks.push(fn);
}
}
function LazyMan(name) {
return new LazyManClass(name);
}
LazyMan("Tony")
.eat("lunch")
.eat("dinner")
.sleepFirst(5)
.sleep(10)
.eat("junk food");
14.sleep
const sleep = (delay) => {
for (let start = Date.now(); Date.now() - start <= delay; );
};
const sleep = (delay) => {
return new Promise((resolve) => {
setTimeout(resolve, delay);
});
};
let start = Date.now();
sleep(3000).then(() => {
console.log(Date.now() - start);
});
function* sleep(delay) {
yield new Promise((resolve) => {
setTimeout(resolve, delay);
});
}
let start = Date.now();
sleep(3000)
.next()
.value.then(() => {
console.log(Date.now() - start);
});
const sleep = (delay) => {
return new Promise((resolve) => {
setTimeout(resolve, delay);
});
};
async function test() {
let start = Date.now();
const temp = await sleep(3000);
console.log(Date.now() - start);
return temp;
}
test();
15.字符串相关
15.1 最长公共前缀
1.every
const longestCommonPrefix1 = (arr) => {
if (!Array.isArray(arr) || arr.length < 2) {
return "输入不存在公共前缀。"
}
// 将数组第一个字符串取出来,作为对比项
let [start, ...rest] = arr
let result = ""
for (let i = 0
// every当满足条件是返回true
let flag = rest.every((item) => start[i] === item[i])
if (flag) result += start[i]
else break
}
return result === "" ? "输入不存在公共前缀。" : result
}
2.深度优先遍历
const longestCommonPrefix2 = (arr) => {
if (!Array.isArray(arr) || arr.length < 2) {
return "输入不存在公共前缀。"
}
// 取第一个字符串长度
let minLen = arr[0].length
// 获取数组中所有字符串长度最小值
arr.map((item) => {
minLen = Math.min(minLen, item.length)
})
let idx = 1
// 将第一个字符串切割,如该例中长度最小值为9('flooooow'长度为8),则'flooooower'变为'flooooow'
let result = arr[0].substr(0, minLen)
while (idx < arr.length) {
while (arr[idx].indexOf(result)) {
result = result.substr(0, result.length - 1)
if (!result.length) return "输入不存在公共前缀。"
}
idx++
}
return result
}
// test
let arr1 = ["dog", "racecar", "car"]
let arr2 = ["flooooower", "flooooow", "flooooooight"]
console.log(longestCommonPrefix1(arr1))
console.log(longestCommonPrefix2(arr2))
15.2 最长公共子串
16.常见继承
function Parent(name) {
this.name = name;
Parent.prototype.sayName = function () {
console.log("parent name:", this.name);
};
}
16.1 原型链继承
// 共享属性,子类的constructor指向父类
function Child(name) {
this.name = name
}
Child.prototype = new Parent()
let c = new Child("原型继承")
console.log(c.constructor)
c.sayName()
16.2 借用构造函数继承
function Child(name) {
Parent.call(this, name);
}
let c = new Child("借用构造 继承");
console.log(c.name);
16.3 组合继承
// 利用原型链继承原型属性方法,利用构造函数继承实例属性方法,但是调用两次父类构造函数
function Child(name) {
Parent.call(this, name)
}
Child.prototype = new Parent()
let c = new Child("原型继承")
c.sayName()
16.4 寄生组合继承
// 利用空函数F代替调用父类构造函数
function Child(name) {
Parent.call(this, name)
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
let c = new Child("原型继承")
c.sayName()
16.5 ES6继承
class Parent {
constructor(name) {
this.name = name;
}
sayName() {
console.log(`Hi, Im ${this.name}`);
}
}
class Child extends Parent {
constructor(name) {
super();
this.name = name;
}
}
const parent = new Child("Mars");
const child = new Child("Vino");
console.log(parent.name);
console.log(child.name);
parent.sayName();
child.sayName();
16.6 多继承
17. EventBus
class EventEmitter {
constructor() {
this.events = this.events || new Map();
}
addListener(type, fn) {
let handler = this.events.get(type);
if (!handler) {
this.events.set(type, fn);
} else if (typeof handler === "function") {
this.events.set(type, [handler, fn]);
} else {
handler.push(fn);
}
}
removeListener(type, fn) {
let handler = this.events.get(type);
if (handler && typeof handler === "function") {
this.events.delete(type, fn);
} else {
handler = handler.filter((item) => {
console.log(item);
return item !== fn;
});
}
}
emit(type, ...args) {
let handler = this.events.get(type);
if (Array.isArray(handler)) {
handler.map((item) => {
item.apply(this, args);
});
} else {
handler.apply(this, args);
}
}
}
const emitter = new EventEmitter();
emitter.addListener("vino", (man) => {
console.log(`one ${man}`);
});
emitter.addListener("vino", (man) => {
console.log(`two ${man}`);
});
emitter.addListener("vino", (man) => {
console.log(`three ${man}`);
});
emitter.addListener("mars", (man) => {
console.log(`four ${man}`);
});
emitter.addListener("mars", (man) => {
console.log(`five ${man}`);
});
emitter.emit("vino", "hello");
emitter.emit("mars", "world");
18.instanceof
const myInstanceof = (left, right) => {
if (typeof left !== "object" || left === null) {
return false;
}
let proto = Object.getPrototypeOf(left);
while (true) {
if (proto == null) {
return false;
}
if (proto === right.prototype) {
return true;
}
proto = Object.getPrototypeOf(proto);
}
};
console.log(myInstanceof([], Array));
console.log(myInstanceof([], Function));
console.log([] instanceof Function);
console.log([] instanceof Array);
19.版本号比较
const compareVersion = (v1, v2) => {
let arr1 = v1.split(".");
let arr2 = v2.split(".");
let maxLength = Math.max(arr1.length, arr2.length);
let i = 0;
while (i < maxLength) {
arr1[i] = +arr1[i] || 0;
arr2[i] = +arr2[i] || 0;
if (arr1[i] < arr2[i]) {
return -1;
} else if (arr1[i] > arr2[i]) {
return 1;
}
i++;
}
return 0;
};
console.log(compareVersion("0.1", "1.1"));
console.log(compareVersion("1.0.1", "1"));
console.log(compareVersion("7.5.2.4", "7.5.3"));
console.log(compareVersion("1.01", "1.001"));
console.log(compareVersion("1.0", "1.0.0"));
console.log(compareVersion("01", "1"));
// 2.补0 补齐位数 但1.01和1.001与01和1这种未添加判断
const toNum = (v, len) => {
let MAP = ["00000", "0000", "000", "00", "0", ""]
while (v.length < len) {
v.push("0")
}
v.map((item, index) => {
v[index] = MAP[index] + item
})
return v.join("")
}
const compareVersion = (v1, v2) => {
v1 = v1.split(".")
v2 = v2.split(".")
let maxLength = Math.max(v1.length, v2.length)
v1 = toNum(v1, maxLength)
v2 = toNum(v2, maxLength)
if (v1 < v2) {
return -1
} else if (v1 > v2) {
return 1
} else {
return 0
}
}
console.log(compareVersion("0.1", "1.1"))
console.log(compareVersion("1.0.1", "1"))
console.log(compareVersion("7.5.2.4", "7.5.3"))
console.log(compareVersion("1.0", "1.0.0"))
20.缓存入参函数
function memorize(fn) {
let cache = {};
return function (...args) {
console.log(cache);
let _args = JSON.stringify(args);
return cache[_args] || (cache[_args] = fn.apply(this, args));
};
}
const add = function (a) {
return a + 1;
};
const minus = function (a) {
return a - 10;
};
const adder = memorize(add);
const minuser = memorize(minus);
console.log(adder(1));
console.log(adder(1));
console.log(minuser(1));
console.log(minuser(1));
console.log(adder(2));
21.ES6
21.1 const
var __const = function __const(data, value) {
window.data = value
Object.defineProperty(window, data, {
enumerable: false,
configurable: false,
get: function () {
return value
},
set: function (data) {
if (data !== value) {
throw new TypeError('xxx')
} else {
return value
}
}
})
}
__const('a', 10)
console.log(a)
22.爬楼梯
function climbStairs(n) {
if (n == 1 || n == 2) return n;
return climbStairs(n - 1) + climbStairs(n - 2);
}
console.log(climbStairs(3));
23.二分查找
let arr = [1, 2, 3, 5, 6, 7, 8, 21, 31, 222]
// 迭代
const binaryFind1 = (arr, target) => {
let low = 0
let high = arr.length - 1
let mid
while (low < high) {
mid = Math.floor((low + high) / 2)
let cur = arr[mid]
if (cur === target) {
return mid
} else if (cur < arr[mid]) {
low = low + 1
} else {
high = high - 1
}
}
}
// 递归
const binaryFind2 = (arr, target, low = 0, high = arr.length - 1) => {
let mid = Math.floor((low + high) / 2)
let cur = arr[mid]
if (cur === target) {
return mid
} else if (cur < target) {
return binaryFind2(arr, target, mid, high)
} else {
return binaryFind2(arr, target, low, mid)
}
}
console.log(binaryFind1(arr, 3))
console.log(binaryFind2(arr, 21))
24.hooks源码
24.1 useState
let index = 0
let memorizedStates = []
const useState = (init) => {
// 初始值
init = memorizedStates[index] || init
let cur = indexl
function setState(newState) {
// 直接替换新的state,class中的setState是合并新旧state
memorizedStates[cur] = newState
// 更新视图
render()
}
return [memorizedStates[index++], setState]
}
const render = () => {
// index清零
index = 0
ReactDOM.render()
}
25.Array
25.1 打乱有序数组 洗牌算法
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
Array.prototype.shuffle = function () {
let arr = this
for (let i = arr.length - 1
// 取index随机值
let _random = Math.floor(Math.random() * (i + 1))
// 将i和index对应的值对换
[arr[i], arr[_random]] = [arr[_random], arr[i]]
}
return arr
}
console.log(arr.shuffle())
25.2 深度广度优先遍历
const data = [
{
name: "a",
children: [
{ name: "b", children: [{ name: "e" }] },
{ name: "c", children: [{ name: "f" }] },
{ name: "d", children: [{ name: "g" }] },
],
},
{
name: "a2",
children: [
{ name: "b2", children: [{ name: "e2" }] },
{ name: "c2", children: [{ name: "f2" }] },
{ name: "d2", children: [{ name: "g2" }] },
],
},
]
// 深度优先 递归
const deepMap = (data, result = []) => {
data.map((item) => {
result.push(item.name)
item.children && deepMap(item.children, result)
})
return result.join(",")
}
console.log(deepMap(data))
// 广度遍历, 创建一个执行队列, 当队列为空的时候则结束
const breadthMap = (tree) => {
let node,
list = [...tree]
let result = []
while ((node = list.shift())) {
result.push(node.name)
node.children && list.push(...node.children)
}
return result.join(",")
}
console.log(breadthMap(data))
·习题
var tree = {
name: "中国",
children: [
{
name: "北京",
children: [
{
name: "朝阳群众",
children: [
{
name: "西宁市",
code: "0521",
},
],
},
{
name: "海淀区",
},
{
name: "昌平区",
},
],
},
{
name: "浙江省",
children: [
{
name: "杭州市",
code: "0571",
},
{
name: "嘉兴市",
},
{
name: "绍兴市",
},
{
name: "宁波市",
},
],
},
],
}
// 输出: { name: '西宁市', code: '0521' }
const bfs = (data, result) => {
const tmp = data.children
let res
let node,
list = [...tmp]
while ((node = list.shift())) {
if (node.name === result) {
res = node
break
} else {
node.children && list.push(...node.children)
}
}
return res
}
console.log(bfs(tree, "西宁市"))
const deepMap = (data, result) => {
if (data.name === result) {
return data
}
if (data.children) {
for (let i = 0
const res = deepMap(data.children[i], result)
if (res) {
return res
}
}
}
return null
}
console.log(deepMap(tree, "西宁市"))