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 zconsole.log(y) //1console.log(z) //undefinedconsole.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 = 1this.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 = 2this.change = function() {this.b.push(this.a)this.a = this.b.lengththis.c.demo = this.a++}
}
Child.prototype = new Parent()//Child继承了Parentvar 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__=Parentparent.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中的achild1.change()//b[1,2,1,11] a=5 c.demo=4
child2.change()//b[1,2,1,11,12] a=6 c.demo=5parent.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 adelete obj.xdelete 2console.log(a, obj.x, 2)//1 undefined 2
delete方法只有在删除对象成员这种引用才有意义,或者说只能删除一种引用即对象成员,其余情况并没有太大的意义
function A(x) {this.x = x}A.prototype.x = 1function B(x) {this.x = x}B.prototype = new A()var a = new A(2),b = new B(3)delete b.xconsole.log(a.x, b.x)//2 undefined