sunny-117 / js-challenges Goto Github PK
View Code? Open in Web Editor NEW✨✨✨ Challenge your JavaScript programming limits step by step
Home Page: https://juejin.cn/column/7244788137410560055
✨✨✨ Challenge your JavaScript programming limits step by step
Home Page: https://juejin.cn/column/7244788137410560055
Array.prototype.myIncludes = function (value, start = 0) {
start = start < 0 ? this.length + start : start;
for (let i = start; i < this.length; i++) {
if (this[i] == value || (Number.isNaN(value) && Number.isNaN(this[i])))
return true;
}
return false;
};
Array.prototype.myFilter = function (callback) {
const res = [];
for (let i = 0; i < this.length; i++) {
callback(this[i], i, this) && res.push(this[i]);
}
return res;
};
function toJSON(data){
}
// test
toJSON(""); // -> ""
toJSON("abc"); // -> "abc"
toJSON(123); // -> 123
toJSON({a:1, b:2}); // -> {"a":1, "b":2}
toJSON(["1", 3, {name:"monica", age:18}]); //-> ["1", 3, {"name":"monica", "age":18}]
Array.prototype.myReduce = function (callback, ...args) {
let start = 0,
pre;
if (args.length) {
//有参数的话pre等于参数第0项
pre = args[0];
} else {
//没参数的话,默认从数组0项开始
pre = this[0];
start = 1;
}
for (let i = start; i < this.length; i++) {
pre = callback(pre, this[i], i, this);
}
return pre;
};
/**
* 得到一个被拒绝的Promise
* @param {*} reason
*/
Promise.reject=function(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
let str = "QIANDUANGOngchengshi猕猴桃Jquery很帅!哈哈 haha";
str = str.replace(/[a-zA-Z]/g, (content) => {
return content.toUpperCase() === content
? content.toLowerCase()
: content.toUpperCase();
});
console.log(str);
/**
* 等待所有的Promise有结果后
* 该方法返回的Promise完成
* 并且按照顺序将所有结果汇总
* @param {Iterable} proms
*/
Promise.allSettled=function(proms) {
const ps = [];
for (const p of proms) {
ps.push(
MyPromise.resolve(p).then(
(value) => ({
status: FULFILLED,
value,
}),
(reason) => ({
status: REJECTED,
reason,
})
)
);
}
return MyPromise.all(ps);
}
const tree = {
name: 'root',
children: [
{
name: 'c1',
children: [
{
name: 'c11',
children: []
},
{
name: 'c12',
children: []
}
]
},
{
name: 'c2',
children: [
{
name: 'c21',
children: []
},
{
name: 'c22',
children: []
}
]
}
]
}
// 深度优先的方式遍历 打印 name
// ['root', 'c1','c11', 'c12', 'c2', 'c21', 'c22']
// 我写的
function solve(root) {
const res = []
function dfs(root) {
for (const key in root) {
if (key === 'name') {
res.push(root[key])
} else if (key === 'children') {
root[key].forEach(ele => {
dfs(ele)
});
}
}
}
dfs(root)
return res;
}
console.log(solve(tree));
Object.create2 = function(proto, propertyObject = undefined) {
function F() {}
F.prototype = proto
const obj = new F()
if (propertyObject != undefined) {
Object.defineProperties(obj, propertyObject)
}
if (proto === null) {
// 创建一个没有原型对象的对象,Object.create(null)
obj.__proto__ = null
}
return obj
}
Array.prototype.copy = function () {
return [...this, ...this]
}
console.log([1, 2, 3, 4, 5].copy());
String.prototype.render = function (data) {
return this.replace(/{{[.\s\S]*?}}/g, match => {
if ((match = match.substring(2, match.length - 2).trim()) == "") {
return "";
} else if (match.startsWith("#")) {
return eval(match.substr(1, match.length - 1));
} else {
return data[match] ? data[match] : "";
}
})
}
const data = {
name: "小明",
age: 16,
school: "第三中学",
classroom: "教室2"
}
console.log(
"{{ name }} 今年 {{ age }} 岁,就读于 {{ school }} 今天在 {{ classroom }} 上课,{{ name }} {{ #data.age >= 18 ? '成年了' : '未成年' }}".render(data)
);
// 小明 今年 16 岁,就读于 第三中学 今天在 教室2 上课,小明 未成年
console.log(
`{{name}}说了句{{#
if (data.age >= 18) {
"我已经成年了!"
} else {
"我还没有成年!"
}
}}`.render(data)
);
// 小明说了句我还没有成年!
const tree = {
name: 'root',
children: [
{ name: '叶子1-1' },
{ name: '叶子1-2' },
{
name: '叶子2-1',
children: [{
name: '叶子3-1',
children: [{
name: '叶子4-1',
children: [{}]
}]
}]
}
]
}
function getLevel(tree) {
if (tree == null) return 0;
const queue = [tree]
let dep = 0;
while (queue.length) {
dep++;
const size = queue.length
for (let i = 0; i < size; i++) {
const node = queue.shift()
if (node.children) {
for (const child of node.children) {
queue.push(child)
}
}
}
}
return dep
}
console.log(getLevel(tree));
正则写就可以
return str.replace(/(^\s+)|(\s+$)/g,'')//将前空格和后空格替换为空
var tree = {
name: '**',
children: [
{
name: '北京',
children: [
{
name: '朝阳群众'
},
{
name: '海淀区'
},
{
name: '昌平区'
}
]
},
{
name: '浙江省',
children: [
{
name: '杭州市',
code: '0571',
},
{
name: '嘉兴市'
},
{
name: '绍兴市'
},
{
name: '宁波市'
}
]
}
]
};
function fn(tree, name) {
//bfs
let Queue = [[tree.name, tree.children]];
while (Queue.length > 0) {
//出队当前节点
let cur = Queue.shift();
if (cur[0] === name) return { name: name, code: cur[1] }
//将children入队
if (cur.length === 1) continue;
for (let node of cur[1]) {
let obj = [node.name];
if (node.hasOwnProperty("children")) obj.push(node.children);
if (node.hasOwnProperty("code")) obj.push(node.code);
Queue.push(obj);
}
}
return -1;
}
var node = fn(tree, '杭州市');
console.log(node); // { name: '杭州市', code: 0571 }
let arr = [
{ id: 1, name: '部门1', pid: 0 },
{ id: 2, name: '部门2', pid: 1 },
{ id: 3, name: '部门3', pid: 1 },
{ id: 4, name: '部门4', pid: 3 },
{ id: 5, name: '部门5', pid: 4 },
{ id: 6, name: '部门6', pid: 0 },
]
function getTreeList(rootList, id, list) {
for (const item of rootList) {
if (item.parent === id) {
list.push(item);
}
}
for (const i of list) {
i.children = [];
getTreeList(rootList, i.id, i.children);
if (i.children.length === 0) {
delete i.children;
}
}
return list;
}
const res = getTreeList(rootList, null, []);
console.log("res", res);
// 记录Promise的三种状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
/**
* 运行一个微队列任务
* 把传递的函数放到微队列中
* @param {Function} callback
*/
function runMicroTask(callback) {
// 判断node环境
// 为了避免「变量未定义」的错误,这里最好加上前缀globalThis
// globalThis是一个关键字,指代全局对象,浏览器环境为window,node环境为global
if (globalThis.process && globalThis.process.nextTick) {
process.nextTick(callback);
} else if (globalThis.MutationObserver) {
const p = document.createElement("p");
const observer = new MutationObserver(callback);
observer.observe(p, {
childList: true, // 观察该元素内部的变化
});
p.innerHTML = "1";
} else {
setTimeout(callback, 0);
}
}
/**
* 判断一个数据是否是Promise对象
* @param {any} obj
* @returns
*/
function isPromise(obj) {
return !!(obj && typeof obj === "object" && typeof obj.then === "function");
}
class MyPromise {
/**
* 创建一个Promise
* @param {Function} executor 任务执行器,立即执行
*/
constructor(executor) {
this._state = PENDING; // 状态
this._value = undefined; // 数据
this._handlers = []; // 处理函数形成的队列
try {
executor(this._resolve.bind(this), this._reject.bind(this));
} catch (error) {
this._reject(error);
console.error(error);
}
}
/**
* 向处理队列中添加一个函数
* @param {Function} executor 添加的函数
* @param {String} state 该函数什么状态下执行
* @param {Function} resolve 让then函数返回的Promise成功
* @param {Function} reject 让then函数返回的Promise失败
*/
_pushHandler(executor, state, resolve, reject) {
this._handlers.push({
executor,
state,
resolve,
reject,
});
}
/**
* 根据实际情况,执行队列
*/
_runHandlers() {
if (this._state === PENDING) {
// 目前任务仍在挂起
return;
}
while (this._handlers[0]) {
const handler = this._handlers[0];
this._runOneHandler(handler);
this._handlers.shift();
}
}
/**
* 处理一个handler
* @param {Object} handler
*/
_runOneHandler({ executor, state, resolve, reject }) {
runMicroTask(() => {
if (this._state !== state) {
// 状态不一致,不处理
return;
}
if (typeof executor !== "function") {
// 传递后续处理并非一个函数
this._state === FULFILLED ? resolve(this._value) : reject(this._value);
return;
}
try {
const result = executor(this._value);
if (isPromise(result)) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
console.error(error);
}
});
}
/**
* Promise A+规范的then
* @param {Function} onFulfilled
* @param {Function} onRejected
*/
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
this._pushHandler(onFulfilled, FULFILLED, resolve, reject);
this._pushHandler(onRejected, REJECTED, resolve, reject);
this._runHandlers(); // 执行队列
});
}
/**
* 仅处理失败的场景
* @param {Function} onRejected
*/
catch(onRejected) {
return this.then(null, onRejected);
}
/**
* 无论成功还是失败都会执行回调
* @param {Function} onSettled
*/
finally(onSettled) {
return this.then(
(data) => {
onSettled();
return data;
},
(reason) => {
onSettled();
throw reason;
}
);
}
/**
* 更改任务状态
* @param {String} newState 新状态
* @param {any} value 相关数据
*/
_changeState(newState, value) {
if (this._state !== PENDING) {
// 目前状态已经更改
return;
}
this._state = newState;
this._value = value;
this._runHandlers(); // 状态变化,执行队列
}
/**
* 标记当前任务完成
* @param {any} data 任务完成的相关数据
*/
_resolve(data) {
this._changeState(FULFILLED, data);
}
/**
* 标记当前任务失败
* @param {any} reason 任务失败的相关数据
*/
_reject(reason) {
this._changeState(REJECTED, reason);
}
}
// 手机号
let reg1 = /^1[44578]\d{9}$/g;
let str1 = '15928229999'
console.log(reg1.test(str1));
// qq号
let reg2 = /^[1-9][0-9]{4,9}$/g;
let str2 = '159222'
console.log(reg2.test(str2));
// 颜色
let reg3 = /#?([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;
let str3 = '#abc'
console.log(reg3.test(str3));
// 邮箱
let reg4 = /^([A-za-z0-9_\-\.]+)+@([A-za-z0-9_\-\.]+)\.([A-Za-z]{2, 6})$/g;//+一到多
var reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
let str4 = '[email protected]'
console.log(reg4.test(str4));
const data3 = [
{
id: 1,
name: '前端',
children: [
{
id: 2,
name: 'html',
children: [
{ id: 5, name: 'vue', children: [] },
{ id: 6, name: 're', children: [] },
]
},
{
id: 3,
name: 'html',
children: [
{ id: 7, name: 'vue', children: [] },
{ id: 8, name: 're', children: [] },
]
}
]
}
]
/**
* 无论成功还是失败都会执行回调
* @param {Function} onSettled
*/
Promise.prototype.finally = function (onSettled) {
return this.then(
(data) => {
onSettled(); // 实现了收不到参数了
return data;
},
(reason) => {
onSettled();
throw reason;
}
);
// finally函数 返回结果应该是无效的
}
/******test finally*******/
// 无论什么结果,都会运行
const pro = new Promise((resolve, reject) => {
resolve(1);
});
const pro2 = pro.finally((d) => {
console.log("finally", d); // 收不到d参数
// 本身不改变状态,但是抛出一个错误,数据就会变成它的错误
// throw 123;
return 123; //不起作用
});
setTimeout(() => {
console.log(pro2);
});
String.prototype.repeat= function (n) {
let str = this;
let res = ''
while (n) {
res += str;
n--
}
return res
}
console.log('abc'.repeat(3));
/**
* 返回的Promise与第一个有结果的一致
* @param {iterator} proms
*/
Promise.race=function(proms) {
return new MyPromise((resolve, reject) => {
for (const p of proms) {
MyPromise.resolve(p).then(resolve, reject);
}
});
}
const arr = [1, [2, 3, [4, 5]], 1, 2, [6, 7]]
Array.prototype.flat = function (deep = 1) {
let res = []
deep--
for (const p of this) {
if (Array.isArray(p) && deep >= 0) {
res = res.concat(p.flat(deep))
} else {
res.push(p)
}
}
return res
}
console.log(arr.flat(1))
const treeData = [
{
name: "root",
children: [
{ name: "src", children: [{ name: "index.html" }] },
{ name: "public", children: [] },
],
},
];
const RecursiveTree = (data) => {
const res = []
const dfs = (data) => {
data.forEach(ele => {
res.push(ele.name)
ele.children && dfs(ele.children)
});
}
dfs(data)
return res;
}
console.log(RecursiveTree(treeData));
Array.prototype.myFill = function (initValue, start = 0, end) {
end = end < 0 ? this.length + end : end;
for (let i = start; i < end; i++) {
this[i] = initValue;
}
return this;
};
let arr = [3, 3, 21, 3, 14, 12, 4, 1, 2];
console.log(arr.fill(1, 3, 5));
Array.prototype.myPush = function (...arg) {
for (let i = 0; i < arg.length; i++) {
this[this.length] = arg[i];
}
return this.length;
};
class MySet {
constructor(iterator = []) {//不传默认空数组
if (typeof iterator[Symbol.iterator] !== "function") {
throw new TypeError(`你提供的${iterator}不是一个可迭代的对象`)
}
this._datas = [];
for (const item of iterator) {
this.add(item);
}
}
get size() {
return this._datas.length;
}
add(data) {
if (!this.has(data)) {// 不包含data,才加入
this._datas.push(data);
}
}
has(data) {// 是否有data
for (const item of this._datas) {
if (this.isEqual(data, item)) {// isEqual判断两个数据是否相等
return true;
}
}
return false;
}
delete(data) {
for (let i = 0; i < this._datas.length; i++) {
const element = this._datas[i];
if (this.isEqual(element, data)) {
//删除
this._datas.splice(i, 1);
return true;
}
}
return false;
}
clear() {
this._datas.length = 0;
}
*[Symbol.iterator]() {// 遍历效果
for (const item of this._datas) {
yield item;
}
}
forEach(callback) {
for (const item of this._datas) {
callback(item, item, this);
}
}
/**
* 判断两个数据是否相等
* @param {*} data1
* @param {*} data2
*/
isEqual(data1, data2) {
if (data1 === 0 && data2 === 0) {
return true;
}
return Object.is(data1, data2);
}
}
手动实现一个promisify函数的意思是:我们把一个异步请求的函数,封装成一个可以具有 then方法的函数,并且在then方法中返回异步方法执行结果的这么一个函数
// 首先定一个需要进行 promisify 的函数
function asyncFn(a, b, callback) {
// 异步操作,使用 setTimeout 模拟
console.log('异步请求参数', a, b)
setTimeout(function() {
callback('异步请求结果')
}, 3000)
}
// 我们希望调用的方式是
const proxy = promisify(asyncFn)
proxy(11,22).then(res => {
// 此处输出异步函数执行结果
console.log(res)
})
// 定义一个方法, 需要针对异步方法做封装,所以需要一个入参,既需要promisify的原异步方法
function promisify(func) {
return function(...args) {
return new Promise((resolve, reject) => {
const callback = (err, data) => {
if (err) {
reject(err);
} else {
resolve(data)
}
};
func.call(this, ...args, callback);
});
}
}
Promise.resolve = function (data) {
if (data instanceof MyPromise) {
return data;
}
return new MyPromise((resolve, reject) => {
if (isPromise(data)) {
data.then(resolve, reject);
} else {
resolve(data);
}
});
}
Array.prototype.getLevel = function () {
let max = 1
for (const a of this) {
if (a instanceof Array) {
const depth = a.getLevel() + 1
if (max < depth) max = depth
}
}
return max
};
const a1 = [1, 2, [1], [1, [2, [3]]]];
console.log(a1.getLevel()); //4
{
tag: 'DIV',
children: [
{
tag: 'SPAN',
children: [
{ tag: 'A', children: [] }
]
},
{
tag: 'SPAN',
children: [
{ tag: 'A', children: [] },
{ tag: 'A', children: [] }
]
}
]
}
function dom2Json(domtree) {
let obj = {};
obj.name = domtree.tagName;
obj.children = [];
domtree.childNodes.forEach((child) => obj.children.push(dom2Json(child)));
return obj;
}
/**
* 本质就是then,只是少传了一个onFulfilled
* 所以仅处理失败的场景
* @param {*} onRejected
*/
Promise.prototype.catch = function(onRejected) {
return this.then(null, onRejected);
}
let data = [
{
"name": "1-1",
"kind": "oo",
"children": [
{
"name": "2-2",
"kind": "ii",
},
{
"name": "3-3",
"children": [
{
"name": "4-4",
"children": [
{
"name": '707'
}
]
}
]
}
]
},
{
"name": "5-5",
},
{
"name": "6-6"
}
]
function getName(data, key = "name") {
let result = [];
if (Array.isArray(data)) {
for (let item of data) {
if (item[key]) {
result.push(item[key]);
}
if (item.children) {
result = result.concat(getName(item.children));
}
}
return result;
} else {
return result;
}
}
console.log(getName(data))
Array.prototype.myUnshift = function (...items) {
this.reverse().push(...items.reverse())
this.reverse()
return this.length
}
// eval 实现
var json = '{"a":"1", "b":2}';
var obj = eval("(" + json + ")"); // obj 就是 json 反序列化之后得到的对象
// New Function
var json = '{"name":"小姐姐", "age":20}';
var obj = (new Function('return ' + json))();
(1)首先创建了一个新的空对象
(2)设置原型,将对象的原型设置为函数的 prototype 对象。
(3)让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性)
(4)判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。
function myNew(constructorFn, ...args) {
let newObj = {}
newObj.__proto__ = constructorFn.prototype;
// newObj = Object.create(constructor.prototype);
let result = constructorFn.apply(newObj, args)
return result instanceof Object ? result : newObj
}
function Animal(name) {
this.name = name;
}
let animal = myNew(Animal, 'dog')
console.log(animal);
{
tag: 'DIV',
attrs:{
id:'app'
},
children: [
{
tag: 'SPAN',
children: [
{ tag: 'A', children: [] }
]
},
{
tag: 'SPAN',
children: [
{ tag: 'A', children: [] },
{ tag: 'A', children: [] }
]
}
]
}
把上诉虚拟Dom转化成下方真实Dom
<div id="app">
<span>
<a></a>
</span>
<span>
<a></a>
<a></a>
</span>
</div>
Object.assign2 = function(target, ...source) {
let ret = Object(target)
source.forEach(function(obj) {
if (obj) {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
ret[key] = obj[key]
}
}
}
})
return ret
}
const obj1 = {a: 1}
const obj2 = {b: 2}
const res = Object.assign2(obj1, obj2)
console.log(obj1);
function isPlainObject(obj) {
if (typeof obj !== "object") {
return false;
}
return Object.getPrototypeOf(obj) === Object.prototype;
}
Object.is = function (x, y) {
if (x === y) {
// 当前情况下,只有一种情况是特殊的,即 +0 -0
// 如果 x !== 0,则返回true
// 如果 x === 0,则需要判断+0和-0,则可以直接使用 1/+0 === Infinity 和 1/-0 === -Infinity来进行判断
return x !== 0 || 1 / x === 1 / y;
}
// x !== y 的情况下,只需要判断是否为NaN,如果x!==x,则说明x是NaN,同理y也一样
// x和y同时为NaN时,返回true
return x !== x && y !== y;
};
class MyMap {
constructor(iterable = []) {
//验证是否是可迭代的对象
if (typeof iterable[Symbol.iterator] !== "function") {
throw new TypeError(`你提供的${iterable}不是一个可迭代的对象`)
}
this._datas = [];
for (const item of iterable) {
// item 也得是一个可迭代对象
if (typeof item[Symbol.iterator] !== "function") {
throw new TypeError(`你提供的${item}不是一个可迭代的对象`);
}
const iterator = item[Symbol.iterator]();
//不一定是数组,所以用这种方式
const key = iterator.next().value;
const value = iterator.next().value;
this.set(key, value);
}
}
set(key, value) {
const obj = this._getObj(key);
if (obj) {//已经有了就是要修改
//修改
obj.value = value;
}
else {//没有的话添加
this._datas.push({
key,
value
})
}
}
get(key) {
const item = this._getObj(key);
if (item) {
return item.value;
}
return undefined;// 找不到
}
get size() {
return this._datas.length;
}
delete(key) {
for (let i = 0; i < this._datas.length; i++) {
const element = this._datas[i];
if (this.isEqual(element.key, key)) {
this._datas.splice(i, 1);
return true;
}
}
return false;
}
clear() {
this._datas.length = 0;
}
/**
* 根据key值从内部数组中,找到对应的数组项
* @param {*} key
*/
_getObj(key) {
for (const item of this._datas) {
if (this.isEqual(item.key, key)) {
return item;
}
}
}
has(key) {
return this._getObj(key) !== undefined;
}
/**
* 判断两个数据是否相等
* @param {*} data1
* @param {*} data2
*/
isEqual(data1, data2) {
if (data1 === 0 && data2 === 0) {
return true;
}
return Object.is(data1, data2);
}
*[Symbol.iterator]() {//迭代器创建函数本身就是生成器函数 *
for (const item of this._datas) {
yield [item.key, item.value];
}
}
forEach(callback) {
for (const item of this._datas) {
callback(item.value, item.key, this);
}
}
}
// 无返回值,调用callback
Array.prototype.myForEach = function (callback) {
if (typeof callback !== "function") {
throw new TypeError(callback + " is not a function");
}
for (let i = 0; i < this.length; i++) {
callback(this[i], i, this);
}
};
const obj = {
a: {
b: 123
},
arr: [
{
demo: 'demo'
}
]
}
function getKey(obj, str) {
}
console.log(getKey(obj, 'a.b'));
console.log(getKey(obj, 'arr[0].demo'));
const data = [
{
id: 1,
text: '节点1',
parentId: 0,
children: [
{
id: 2,
text: '节点1_1',
parentId: 1
}
]
}
]
function treeToList(data) {
let res = [];
const dfs = (tree) => {
tree.forEach((item) => {
if (item.children) {
dfs(item.children);
delete item.children;
}
res.push(item);
});
};
dfs(data);
return res;
}
function myInstanceof(left, right) {
let proto = Object.getPrototypeOf(left), // 获取对象的原型
prototype = right.prototype; // 获取构造函数的 prototype 对象
// 判断构造函数的 prototype 对象是否在对象的原型链上
while (true) {
if (!proto) return false;
if (proto === prototype) return true;
proto = Object.getPrototypeOf(proto);
}
}
function Person() { };
var p = new Person();
console.log(myInstanceof(p, Object));
// console.log(p instanceof Person);//true
let strarr = {
'a-b-c-d':1,
'a-b-c-e':2,
'a-b-f':3,
'a-j':4
}
let obj = {
a:{
b:{
c:{
d:1,
e:2
},
f:3
},
j:4
}
}
String.prototype.zpadStart = function (targetLength, padString) {
let string = this
while (string.length < targetLength) {
string = padString + string
}
return string
}
const res = 'abc'.padStart(8, "0");
const arr = [1, 2, 3]
Array.prototype.map = function (callback) {
const res = [];
for (let i = 0; i < this.length; i++) {
res.push(callback(this[i], i, this))
}
return res;
}
const res = arr.map((ele, index, arr) => {
return ele * 2
})
console.log(res)
现有如下json(简化为对象),已知每个节点id唯一,编写findNode(id),返回路径,如findNode(5 输出 1->4->5
json = {
id: 1,
children: [
{ id: 2, children: [{ id: 3, children: [] }] },
{
id: 4,
children: [
{ id: 5, children: [] },
{ id: 6, children: [] },
],
},
{ id: 7, children: [] },
],
};
function findNode(obj) {
const res = []
function dfs(obj, currPath, target) {
if (!obj) return;
if (obj.id === target) {
currPath += obj.id
res.push(currPath)
return
}
currPath += obj.id + '->'
obj.children && obj.children.forEach(ele => {
dfs(ele, currPath, target)
});
}
dfs(obj, '', 5)
return res;
}
Function.prototype.call2 = function(context, ...args) {
context = (context === undefined || context === null) ? window : context
context.__fn = this
let result = context.__fn(...args)
delete context.__fn
return result
}
Function.prototype.apply2 = function(context, args) {
context = (context === undefined || context === null) ? window : context
context.__fn = this
let result = context.__fn(...args)
delete context.__fn
return result
}
Function.prototype.bind2 = function(context, ...args1) {
context = (context === undefined || context === null) ? window : context
let _this = this
return function(...args2) {
context.__fn = _this
let result = context.__fn(...[...args1, ...args2])
delete context.__fn
return result
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.