复习的时候经过整理,发现这些题大致分为如下几类种(持续更新)
- 判断this指向
- 异步,宏任务微任务的顺序
- 闭包
- 原型链
因此分类别整理如下
异步,判断顺序
- 最简单的一种
setTimeout(function () {
console.log(1)
}, 0)
new Promise(function (resolve) {
console.log(2)
for (var i = 0; i < 10000; i++) {
i == 9999 && resolve()
}
console.log(3)
}).then(function () {
console.log(4)
})
console.log(5)
输出为
console.log('a')
setTimeout(() => {
console.log('b')
}, 0)
console.log('c')
Promise.resolve().then(() => {
console.log('d')
}).then(() => {
console.log('e')
})
console.log('f')
- 自己根据题目写的一种,结合宏任务,微任务
console.log('a')
setTimeout(() => {
console.log('b')
setTimeout(() => {
console.log('bbbb')
}, 0)
}, 0)
console.log('c')
Promise.resolve().then(() => {
console.log('d')
setTimeout(() => {
console.log('j')
Promise.resolve().then(() => {
console.log('kj')
})
}, 0)
Promise.resolve().then(() => {
console.log('k')
})
}).then(() => {
console.log('e')
})
console.log('f')
setTimeout(() => {
console.log('q')
setTimeout(() => {
console.log('qqq')
}, 0)
}, 0)
3. 有async的情况下
async function f1() {
setTimeout(() => {
console.log(9);
});
console.log(await 1);
}
async function f2() {
console.log(await 2);
}
async function f3() {
console.log(3);
}
setTimeout(() => {
setTimeout(() => {
console.log(10);
});
Promise.resolve(5).then(console.log)
console.log(6);
});
async function f4() {
new Promise((resolve) => {
console.log(4);
resolve(8)
}).then(console.log)
}
f1()
f2()
f3()
f4()
console.log(7);
this指向
以下是题目
var a = 2
var obj = {
a: 3,
fn: function () {
(() => {
console.log(this);
console.log(this.a)
})()
},
}
var obj1 = {
a: 3,
fn: () => {
console.log(this);
console.log(this.a)
},
}
obj.fn()
obj1.fn()
箭头函数作为对象内部的方法时(obj1),向外找this的时候是找到该对象之外的,此处为window,但是作为对象的属性里面的函数的时候,向外找,就相当于找该属性外面一层,就是该对象,此处就是obj。
原型链
本人原型链文章文章1 文章2 ES6的class类
以下是题目
/* 输出结果 */
function F() { }
F.prototype.arr = [1]
F.prototype.b = 1
let obj1 = new F()
obj1.arr.push(2)
obj1.b = 2
let obj2 = new F()
console.log(obj2.arr, obj2.b)
// [1,2] 1
对于非引用类型的数据结构,obj.xx=xxx,这样并不会顺着原型链去找,会给这个实例对象添加一个xx属性,只有数组、对象等引用类型的,用这种方式,可以去更改原型链上的内容,因为顺着地址去找的
function Person(name) {
this.name = name
}
function Student() {
}
Student.prototype = Person.prototype
Student.prototype.constructor = Student
var s = new Student('Tom')
console.log(s instanceof Person) // true
闭包
/* 输出结果 */
for (var i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i)
}, 0)
}
//10个10
下面都是 0 - 9
// 使用 let
for (let i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i)
}, 0)
}
// 使用闭包
for (var i = 0; i < 10; i++) {
(function (i) {
setTimeout(() => {
console.log(i)
}, 0)
})(i)
}
// 使用 setTimeout 的第三个参数
for (var i = 0; i < 10; i++) {
setTimeout((i) => {
console.log(i)
}, 0, i)
}
下面是本人犯过的错误,以为闭包也能进行传参
function test() {
let a = 1
function change(x) {
x = x + 1
console.log(x);
}
change(a)
console.log(a);
}
test()
此处的change函数,把a传进去了,但是此处只是传递了a的值,后续不会对test里的a进行更改,当初做错了,不知道这个点,导致在做二叉树的递归的时候,还有动态规划的递归的时候,一直得不到想要的值,可见文章
如果想要change函数能改变a的值,就不要把a当做参数传进去,应该做如下修改
function test() {
let a = 1
function change() {
a = a + 1
console.log(a);
}
change(a)
console.log(a);
}
test()