1.将数组中的子对象加入到对应的父对象中,也就是parent_id为id 的,就将其加入进去。
function listToTree(list) {
let map = {};
list.forEach(item => {
if (!map[item.id]) {
map[item.id] = item;
}
});
list.forEach(item => {
if (item.parent_id !== 0) {
map[item.parent_id].children ? map[item.parent_id].children.push(item) :
map[item.parent_id].children = [item];
}
});
return list.filter(item => {
if (item.parent_id === 0) {
return item;
}
})
}
let array = [{
id: 1,
parent_id: 0,
name: '11'
}, {
id: 2,
parent_id: 1,
name: '111'
}]
console.log(listToTree(array));
结果:
2.全局和局部变量问题
(function() {
var x = y = 1
})()
var z
console.log(y) //1
console.log(z) //undefined
console.log(x) // error
从右向左赋值,可分解为:y = 1;var x = y;可见 y 为全局变量,x为闭包函数内的局部变量,在console.log输出时是在闭包函数外部获取变量,所以获取不到 x 而直接输出error,y 为全局变量且值为 1,故输出1
而对于z由于只声明了未赋值,因此输出undefined
3.异步问题
const promise = new Promise((resolve, reject) => {
console.log(1)
setTimeout(() => {
console.log("begin")
resolve("suss")
console.log("end")
}, 0)
console.log(2)
})
promise.then((data) => {
console.log(data)
})
console.log(4)
//1 2 4 begin end suss
主线程输出1,setTimeout加入宏任务队列,主线程输出2,4。读取宏任务队列,输出begin ,promise.then 加入微任务队列,继续输出end,读取微任务队列,输出suss
4.this指向问题
function Parent() {
this.a = 1
this.b = [1, 2, this.a]
this.c = {
demo: 5
}
this.show = function() {
console.log(this.a, this.b, this.c.demo)
}
}
function Child() {
this.a = 2
this.change = function() {
this.b.push(this.a)
this.a = this.b.length
this.c.demo = this.a++
}
}
Child.prototype = new Parent()//Child继承了Parent
var parent = new Parent()
var child1 = new Child()//a:2 change() 其中__proto__=Parent
var child2 = new Child()//a:2 change() 其中__proto__=Parent
child1.a = 11//a:11 change() 其中__proto__=Parent
child2.a = 12//a:12 change() 其中__proto__=Parent
parent.show() //1 [1,2,1] 5
child1.show()//11 [1,2,1] 5
child2.show()//12 [1,2,1] 5
//由于child1本身有a了,所以this.a=11 ,由于child1中没有b,因此在原型对象中查找,查找到运行对象parent上,此时调用者为parent,所以b中的this.a引用parent中的a
child1.change()//b[1,2,1,11] a=5 c.demo=4
child2.change()//b[1,2,1,11,12] a=6 c.demo=5
parent.show()//1 [1,2,1] 5
child1.show()//5 [1,2,1,11,12] 5
child2.show()//6 [1,2,1,11,12] 5
- child1.change()时,this.b.push(this.a),push进去的依然是chid里面的a而不是parent里的a。因为这次的this.a所处的上下文是child,首先会在child里面查找,如果没有才会去原型里找。
- child2.change()时,改动继续被沿用了,对child2实例也产生了改动。因为他们原型里指向的对象parent是同一个对象。parent在Child.prototype = new Parent()这个时候已经新建了实例对象并绑定在了child上面作为它的原型对象,child新建实例的时候并不会影响原型对象,因为就算child不创建实例,我们一样可以通过child.prototype操作赋进去的parent对象
对于a和c.demo,举一个简单的例子:
let b = [1, 2, 3]
let a = b.length
let c = a++
console.log(a, c)
//4,3
5.null和undefined
var one
var two = null
console.log(one == two, one === two)
6.delete和原型问题
let a = 1
let obj = {
x: 1
}
delete a
delete obj.x
delete 2
console.log(a, obj.x, 2)
//1 undefined 2
delete方法只有在删除对象成员这种引用才有意义,或者说只能删除一种引用即对象成员,其余情况并没有太大的意义
function A(x) {
this.x = x
}
A.prototype.x = 1
function B(x) {
this.x = x
}
B.prototype = new A()
var a = new A(2),
b = new B(3)
delete b.x
console.log(a.x, b.x)
//2 undefined