Output 输出类
类型转换类
- 题目
- 答案
'true' == true
'true' == true // false
// ==> NaN == 1
// ==> false
- 题目
- 答案
'false' == false
'false' == false // false
// ==> NaN == 0
// ==> false
== 运算符执行 number 类型转换,true 转换为 NaN,boolean 类型 true 转换为 1
- 题目
- 答案
null == ''
null == '' // false
null 不等于任何值除了 null 和 undefined
- 题目
- 答案
['x'] == 'x'
['x'] == 'x' // true
== 运算符对数组类型执行 number 转换,先调用对象的 valueOf() 方法,结果是数组本身,不是原始类型值,所以执行对象的 toString() 方法,得到字符串 'x'。
- 题目
- 答案
[1, 2, 3] == [1, 2, 3]
[1, 2, 3] == [1, 2, 3] // false
当运算符两边类型相同时,不会执行类型转换,两个数组的内存地址不一样,所以返回 false。
- 题目
- 答案
true + false
true + false // 1
+ 运算符会触发 number 类型转换,因此上面转为 1 + 0。
- 题目
- 答案
[1] > null
[1] > null // true
// ==> '1' > 0
// ==> 1 > 0
// ==> true
比较运算符 > 执行 number 类型隐式转换。
- 题目
- 答案
"foo" + + "bar"
"foo" + + "bar" // "fooNaN"
// ==> "foo" + (+"bar")
// ==> "foo" + NaN
// ==> "fooNaN"
一元 + 运算符比二元 + 运算符具有更高的优先级。所以 + bar 表达式先求值。一元加号执行字符串 bar 的 number 类型转换。因为字符串不代表一个有效的数字,所以结果是 NaN。在第二步中,计算表达式 'foo' + NaN。
- 题目
- 答案
0 || "0" && {}
0 || "0" && {} // {}
// ==> (0 || '0') && {}
// ==> (false || true) && true
// ==> true && true
// ==> true
逻辑运算符 || 和 && 将值转为 boolean 型,但是会返回原始值(不是 boolean)
- 题目
- 答案
{} + [] + {} + [1]
{} + [] + {} + [1] // '0[object Object]1'
// ==> +[] + {} + [1]
// ==> 0 + {} + [1]
// ==> 0 + '[object Object]' + '1'
// ==> '0[object Object]1'
所有的操作数都不是原始类型,所以会按照从左到右的顺序执行 number 类型的隐式转换,object 和 array 类型的 valueOf() 方法返回它们本身,所以直接忽略,执行 toString() 方法。 这里的技巧是,第一个 {} 不被视为 object,而是块声明语句,因此它被忽略。计算从 +[] 表达式开始,该表达式通过 toString() 方法转换为空字符串,然后转换为 0
- 题目
- 答案
! + [] + [] + ![]
! + [] + [] + ![] // 'truefalse'
// ==> !(+[]) + [] + (![])
// ==> !0 + [] + false
// ==> true + [] + false
// ==> true + '' + false
// ==> 'truefalse'
一元运算符优先执行,+[] 转为 number 类型 0,![] 转为 boolean 型 false。
- 题目
- 答案
new Date(0) - 0
new Date(0) - 0 // 0
// ==> 0 - 0
// ==> 0
'-' 运算符执行 number 类型隐式转换对于 Date 型的值,Date.valueOf() 返回到毫秒的时间戳。
- 题目
- 答案
new Date(0) + 0
new Date(0) + 0 // 'Thu Jan 01 1970 02:00:00 GMT+0200 (EET)0'
// ==> 'Thu Jan 01 1970 02:00:00 GMT+0200 (EET)' + 0
// ==> 'Thu Jan 01 1970 02:00:00 GMT+0200 (EET)0'
'+' 运算符触发默认转换,因此使用 toString() 方法,而不是 valueOf()。
- 题目
- 答案
'ca' < 'bd'
'ca' < 'bd' // false
比较符两边都是字符串时,会比较字母表顺序。
- 题目
- 答案
Boolean(new Boolean(false))
Boolean(new Boolean(false)) // true
this 类
- 题目
- 答案
var a = 10
var obj = {
a: 20,
say: () => {
console.log(this.a)
}
}
obj.say()
var anotherObj = {
a: 30
}
obj.say.apply(anotherObj)
var a = 10
var obj = {
a: 20,
say: () => {
console.log(this.a)
}
}
obj.say()
var anotherObj = {
a: 30
}
obj.say.apply(anotherObj)
// 10
// 10
箭头函数时不绑定 this,且 this 来自原其父级所处的上下文,所以首先会打印全局中的 a 的值 10。后面虽然让 say 方法指向了另外一个对象,但是仍不能改变箭头函数的特性,它的 this 仍然是指向全局的,所以依旧会输出 10。
- 题目
- 答案
var obj = {
say: function () {
var f1 = () => {
console.log("1111", this);
}
f1();
},
pro: {
getPro: () => {
console.log(this);
}
}
}
var o = obj.say;
o();
obj.say();
obj.pro.getPro();
var obj = {
say: function () {
var f1 = () => {
console.log("1111", this);
}
f1();
},
pro: {
getPro: () => {
console.log(this);
}
}
}
var o = obj.say;
o();
obj.say();
obj.pro.getPro();
// 1111 window 对象
// 1111 obj 对象
// window 对象
o():o 在全局执行,而 f1 是箭头函数,this 指向其父级的 this,其父级 say 方法的 this 指向的是全局作用域,所以会打印出window;obj.say():谁调用 say,say 的 this 就指向谁,所以此时 this 指向的是 obj 对象;obj.pro.getPro():箭头函数时不绑定 this,getPro 处于 pro 中,而对象不构成单独的作用域,所以箭头函数的 this 就指向了全局作用域 window。
- 题目
- 答案
var myObject = {
foo: "bar",
func: function () {
var self = this;
console.log(this.foo);
console.log(self.foo);
(function () {
console.log(this.foo);
console.log(self.foo);
}());
}
};
myObject.func();
var myObject = {
foo: "bar",
func: function () {
var self = this;
console.log(this.foo);
console.log(self.foo);
(function () {
console.log(this.foo);
console.log(self.foo);
}());
}
};
myObject.func();
// bar
// bar
// undefined
// bar
- 首先 func 由 myObject 调用,this 指向 myObject。又因为 var self = this; 所以 self 指向 myObject。
- 而立即执行匿名函数表达式由 window 调用的,this 指向 window。立即执行匿名函数的作用域处于 myObject.func 的作用域中,在这个作用域找不到 self 变量,沿着作用域链向上查找 self 变量,找到了指向 myObject 对象的 self。
- 题目
- 答案
var a = 1;
function printA() {
console.log(this.a);
}
var obj = {
a: 2,
foo: printA,
bar: function () {
printA();
}
}
obj.foo();
obj.bar();
var foo = obj.foo;
foo();
var a = 1;
function printA() {
console.log(this.a);
}
var obj = {
a: 2,
foo: printA,
bar: function () {
printA();
}
}
obj.foo();
obj.bar();
var foo = obj.foo;
foo();
// 2
// 1
// 1
obj.foo():foo 的 this 指向 obj 对象,所以 a 会输出 2;obj.bar():printA 在 bar 方法中执行,所以此时 printA 的 this 指向的是 window,所以会输出 1;foo():foo 是在全局对象中执行的,所以其 this 指向的是 window,所以会输出 1。
- 题目
- 答案
var x = 3;
var y = 4;
var obj = {
x: 1,
y: 6,
getX: function () {
var x = 5;
return function () {
return this.x;
}();
},
getY: function () {
var y = 7;
return this.y;
}
}
console.log(obj.getX())
console.log(obj.getY())
var x = 3;
var y = 4;
var obj = {
x: 1,
y: 6,
getX: function () {
var x = 5;
return function () {
return this.x;
}();
},
getY: function () {
var y = 7;
return this.y;
}
}
console.log(obj.getX())
console.log(obj.getY())
// 3
// 6
- 匿名函数的 this 指向全局对象,所以 this 指向 window,打印出 3;
- getY 由 obj 调用,所以其 this 指向 obj 对象,打印出 6。
作用域类
- 题目
- 答案
(function(){
var x = y = 1;
})();
var z;
console.log(y);
console.log(z);
console.log(x);
(function(){
var x = y = 1;
})();
var z;
console.log(y); // 1
console.log(z); // undefined
console.log(x); // Uncaught ReferenceError: x is not defined
这段代码的关键在于:var x = y = 1; 实际上这里是从右往左执行的,首先执行 y = 1, 因为y没有使用 var 声明,所以它是一个全局变量,然后第二步是将 y 赋值给 x,将一个全局变量赋值给一个局部变量,最终,x 是个局部变量,y 是个全局变量,所以打印 x 报错。
- 题目
- 答案
// a
function Foo() {
getName = function () {
console.log(1);
}
return this;
}
// b
Foo.getName = function () {
console.log(2);
}
// c
Foo.prototype.getName = function () {
console.log(3);
}
// d
var getName = function () {
console.log(4);
}
// e
function getName() {
console.log(5);
}
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
// a
function Foo() {
getName = function () {
console.log(1);
}
return this;
}
// b
Foo.getName = function () {
console.log(2);
}
// c
Foo.prototype.getName = function () {
console.log(3);
}
// d
var getName = function () {
console.log(4);
}
// e
function getName() {
console.log(5);
}
Foo.getName(); // 2
getName(); // 4
Foo().getName(); // 1
getName(); // 1
new Foo.getName(); // 2
new Foo().getName(); // 3
new new Foo().getName(); // 3
Foo.getName():Foo 为一个函数对象,对象都可以有属性,b 处定义 Foo 的 getName 属性为函数,输出 2;getName():这里看 d、e 处,d 为函数表达式,e 为函数声明,两者区别在于变量提升,函数声明的 5 会被后边函数表达式的 4 覆盖;Foo().getName():这里要看 a 处,在 Foo 内部将全局的 getName 重新赋值为 console.log(1) 的函数,执行 Foo()返回 this,这个 this 指向 window,Foo().getName() 即为 window.getName(),输出 1;getName():上面 3 中,全局的 getName 已经被重新赋值,所以这里依然输出 1;new Foo.getName():这里等价于new (Foo.getName()),先执行 Foo.getName(),输出 2,然后 new 一个实例;new Foo().getName():这里等价于(new Foo()).getName(), 先 new 一个 Foo 的实例,再执行这个实例的 getName 方法,但是这个实例本身没有这个方法,所以去原型链__protot__上边找,实例.protot === Foo.prototype,所以输出 3;new new Foo().getName():这里等价于new (new Foo().getName()),如上述 6,先输出 3,然后 new 一个new Foo().getName()的实例。
setTimeout 类 + 怎么解决
- 题目
- 答案
for (var i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i)
}, i * 1000)
}
回答:
for (var i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i)
}, i * 1000)
}
// 5 5 5 5 5
因为 setTimeout 是异步函数,所以会先把循环全部执行完毕,这时候 i 已经是 5 了,再依次执行 setTimeout 输出一堆 5。
解决方式:可以通过 var 改为 let 的方式,在每次循环时产生独立的块级作用域,重新声明和赋值:
for (let i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i)
}, i * 1000)
}
也可以通过 setTimeout 的第三个参数,在定时器执行时作为参数传入执行函数来实现:
for (var i = 0; i < 5; i++) {
setTimeout(
(j) => {
console.log(j)
},
i * 1000,
i
)
}
还可以使用闭包的方式,使用立即执行函数将当前 i 的值固定在参数上,然后通过闭包执行函数执行参数来实现:
for (var i = 0; i < 5; i++) {
;
(function (j) {
setTimeout(() => {
console.log(j)
}, j * 1000)
})(i)
}
Promise 类
- 题目
- 答案
const promise = new Promise((resolve, reject) => {
console.log(1);
console.log(2);
});
promise.then(() => {
console.log(3);
});
console.log(4);
const promise = new Promise((resolve, reject) => {
console.log(1);
console.log(2);
});
promise.then(() => {
console.log(3);
});
console.log(4);
// 1
// 2
// 4
- 因为 promise.then 是微任务
- 微任务会在所有的宏任务执行完成后执行,同时需要 Promise 内部的状态发生变化
- 而这里 Promise 内部没有发生变化,一直处于 pending 状态,因此不输出 3
- 题目
- 答案
const promise = new Promise((resolve, reject) => {
console.log(1);
setTimeout(() => {
console.log("timerStart");
resolve("success");
console.log("timerEnd");
}, 0);
console.log(2);
});
promise.then((res) => {
console.log(res);
});
console.log(4);
const promise = new Promise((resolve, reject) => {
console.log(1);
setTimeout(() => {
console.log("timerStart");
resolve("success");
console.log("timerEnd");
}, 0);
console.log(2);
});
promise.then((res) => {
console.log(res);
});
console.log(4);
// 1
// 2
// 4
// timerStart
// timerEnd
// success
- 首先遇到 Promise 构造函数,会先执行里面的内容,打印 1
- 遇到定时器 steTimeout,它是一个宏任务,放入宏任务队列
- 继续向下执行,打印出 2
- 由于 Promise 的状态此时还是 pending,所以 promise.then 先不执行
- 继续执行下面的同步任务,打印出 4
- 此时微任务队列没有任务,继续执行下一轮宏任务,执行 steTimeout
- 首先执行 timerStart,然后遇到了 resolve,将 promise 的状态改为 resolved
- 且保存结果并将之前的 promise.then 推入微任务队列,再执行 timerEnd
- 执行完这个宏任务,就去执行微任务 promise.then,打印出 resolve 的结果
- 题目
- 答案
Promise.resolve().then(() => {
console.log('promise1');
const timer2 = setTimeout(() => {
console.log('timer2')
}, 0)
});
const timer1 = setTimeout(() => {
console.log('timer1')
Promise.resolve().then(() => {
console.log('promise2')
})
}, 0)
console.log('start');
Promise.resolve().then(() => {
console.log('promise1');
const timer2 = setTimeout(() => {
console.log('timer2')
}, 0)
});
const timer1 = setTimeout(() => {
console.log('timer1')
Promise.resolve().then(() => {
console.log('promise2')
})
}, 0)
console.log('start');
// start
// promise1
// timer1
// promise2
// timer2
- 首先,Promise.resolve().then 是一个微任务,加入微任务队列
- 执行 timer1,它是一个宏任务,加入宏任务队列
- 继续执行下面的同步代码,打印出 start
- 第一轮宏任务执行完
- 开始执行微任务 Promise.resolve().then,打印出 promise1
- 遇到 timer2,它是一个宏任务,将其加入宏任务队列
- 此时宏任务队列有两个任务,分别是 timer1、timer2
- 第一轮微任务就执行完
- 开始执行第二轮宏任务,首先执行定时器 timer1,打印 timer1
- 遇到 Promise.resolve().then,它是一个微任务,加入微任务队列
- 开始执行微任务队列中的任务,打印 promise2
- 最后执行宏任务 timer2 定时器,打印出 timer2
- 题目
- 答案
const promise = new Promise((resolve, reject) => {
resolve('success1');
reject('error');
resolve('success2');
});
promise.then((res) => {
console.log('then:', res);
}).catch((err) => {
console.log('catch:', err);
})
const promise = new Promise((resolve, reject) => {
resolve('success1');
reject('error');
resolve('success2');
});
promise.then((res) => {
console.log('then:', res);
}).catch((err) => {
console.log('catch:', err);
})
// then:success1
- 这个题目考察的是 Promise 的状态在发生变化之后,就不会再发生变化
- 开始状态由 pending 变为 resolve,说明已经变为已完成状态
- 下面的两个状态的就不会再执行,同时下面的 catch 也不会捕获到错误
- 题目
- 答案
Promise.resolve('1')
.then(res => {
console.log(res)
})
.finally(() => {
console.log('finally1')
})
Promise.resolve('2')
.finally(() => {
console.log('finally2')
return '我是finally2返回的值'
})
.then(res => {
console.log(res)
})
Promise.resolve('1')
.then(res => {
console.log(res)
})
.finally(() => {
console.log('finally1')
})
Promise.resolve('2')
.finally(() => {
console.log('finally2')
return '我是finally2返回的值'
})
.then(res => {
console.log(res)
})
// 1
// finally2
// finally1
// 2
- .finally() 方法不管 Promise 对象最后的状态如何都会执行
- .finally() 方法的回调函数不接受任何的参数
- 也就是说在 .finally() 函数中无法知道 Promise 最终的状态是 resolved 还是 rejected
- 它最终返回的默认会是一个上一次的 Promise 对象值
- 不过如果抛出的是一个异常则返回异常的 Promise 对象
- finally 本质上是 then 方法的特例
- 题目
- 答案
console.log(1)
setTimeout(() => {
console.log(2)
})
new Promise(resolve => {
console.log(3)
resolve(4)
}).then(d => console.log(d))
setTimeout(() => {
console.log(5)
new Promise(resolve => {
resolve(6)
}).then(d => console.log(d))
})
setTimeout(() => {
console.log(7)
})
console.log(8)
console.log(1)
setTimeout(() => {
console.log(2)
})
new Promise(resolve => {
console.log(3)
resolve(4)
}).then(d => console.log(d))
setTimeout(() => {
console.log(5)
new Promise(resolve => {
resolve(6)
}).then(d => console.log(d))
})
setTimeout(() => {
console.log(7)
})
console.log(8)
// 1
// 3
// 8
// 4
// 2
// 5
// 6
// 7
- 首先执行 script 代码,打印出 1;
- 遇到第一个定时器,加入到宏任务队列;
- 遇到 Promise,执行代码,打印出 3,遇到 resolve,将其加入到微任务队列;
- 遇到第二个定时器,加入到宏任务队列;
- 遇到第三个定时器,加入到宏任务队列;
- 继续执行 script 代码,打印出 8,第一轮执行结束;
- 执行微任务队列,打印出第一个 Promise 的 resolve 结果:4;
- 开始执行宏任务队列,执行第一个定时器,打印出 2;
- 此时没有微任务,继续执行宏任务中的第二个定时器,首先打印出 5,遇到 Promise,首选打印出 6,遇到 resolve,将其加入到微任务队列;
- 执行微任务队列,打印出 6;
- 执行宏任务队列中的最后一个定时器,打印出 7。
- 题目
- 答案
Promise.resolve().then(() => {
console.log('1');
throw 'Error';
}).then(() => {
console.log('2');
}).catch(() => {
console.log('3');
throw 'Error';
}).then(() => {
console.log('4');
}).catch(() => {
console.log('5');
}).then(() => {
console.log('6');
});
Promise.resolve().then(() => {
console.log('1');
throw 'Error';
}).then(() => {
console.log('2');
}).catch(() => {
console.log('3');
throw 'Error';
}).then(() => {
console.log('4');
}).catch(() => {
console.log('5');
}).then(() => {
console.log('6');
});
// 1
// 3
// 5
// 6
在这道题目中,我们需要知道,无论是 thne 还是 catch 中,只要 throw 抛出了错误,就会被 catch 捕获,如果没有 throw 出错误,就继续执行后面的 then。
- 题目
- 答案
setTimeout(function () {
console.log(1);
}, 100);
new Promise(function (resolve) {
console.log(2);
resolve();
console.log(3);
}).then(function () {
console.log(4);
new Promise((resove, reject) => {
console.log(5);
setTimeout(() => {
console.log(6);
}, 10);
})
});
console.log(7);
console.log(8);
setTimeout(function () {
console.log(1);
}, 100);
new Promise(function (resolve) {
console.log(2);
resolve();
console.log(3);
}).then(function () {
console.log(4);
new Promise((resove, reject) => {
console.log(5);
setTimeout(() => {
console.log(6);
}, 10);
})
});
console.log(7);
console.log(8);
// 2
// 3
// 7
// 8
// 4
// 5
// 6
// 1
- 首先遇到定时器,将其加入到宏任务队列;
- 遇到 Promise,首先执行里面的同步代码,打印出 2,遇到 resolve,将其加入到微任务队列,执行后面同步代码,打印出 3;
- 继续执行 script 中的代码,打印出 7 和 8,至此第一轮代码执行完成;
- 执行微任务队列中的代码,首先打印出 4,如遇到 Promise,执行其中的同步代码,打印出 5,遇到定时器,将其加入到宏任务队列中,此时宏任务队列中有两个定时器;
- 执行宏任务队列中的代码,这里我们需要注意是的第一个定时器的时间为 100ms,第二个定时器的时间为 10ms,所以先执行第二个定时器,打印出 6;
- 此时微任务队列为空,继续执行宏任务队列,打印出 1。
Async / Await 类
- 题目
- 答案
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
async function async2() {
console.log("async2");
}
async1();
console.log('start')
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
async function async2() {
console.log("async2");
}
async1();
console.log('start')
// async1 start
// async2
// start
// async1 end
- 首先执行函数中的同步代码 async1 start
- 之后遇到了 await,它会阻塞 async1 后面代码的执行
- 因此会先去执行 async2 中的同步代码 async2,然后跳出 async1;
- 跳出 async1 函数后,执行同步代码 start;
- 在一轮宏任务全部执行完之后,再来执行 await 后面的内容 async1 end
- 题目
- 答案
async function async1() {
console.log('async1 start');
await new Promise(resolve => {
console.log('promise1')
})
console.log('async1 success');
return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')
async function async1() {
console.log('async1 start');
await new Promise(resolve => {
console.log('promise1')
})
console.log('async1 success');
return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')
// script start
// async1 start
// promise1
// script end
这里需要注意的是在 async1 中 await 后面的 Promise 是没有返回值的,也就是它的状态始终是 pending 状态,所以在 await 之后的内容不会执行,包括 async1 后面的 .then。
- 题目
- 答案
async function async1() {
console.log('async1 start');
await new Promise(resolve => {
console.log('promise1')
resolve('promise1 resolve')
}).then(res => console.log(res))
console.log('async1 success');
return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')
async function async1() {
console.log('async1 start');
await new Promise(resolve => {
console.log('promise1')
resolve('promise1 resolve')
}).then(res => console.log(res))
console.log('async1 success');
return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')
// script start
// async1 start
// promise1
// script end
// promise1 resolve
// async1 success
// async1 end
这里是对上面一题进行了改造,加上了 resolve。
- 题目
- 答案
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
async function async2() {
console.log("async2");
}
console.log("script start");
setTimeout(function () {
console.log("setTimeout");
}, 0);
async1();
new Promise(resolve => {
console.log("promise1");
resolve();
}).then(function () {
console.log("promise2");
});
console.log('script end')
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
async function async2() {
console.log("async2");
}
console.log("script start");
setTimeout(function () {
console.log("setTimeout");
}, 0);
async1();
new Promise(resolve => {
console.log("promise1");
resolve();
}).then(function () {
console.log("promise2");
});
console.log('script end')
// script start
// async1 start
// async2
// promise1
// script end
// async1 end
// promise2
// setTimeout
- 开头定义了 async1 和 async2 两个函数,但是并未执行,执行 script 中的代码,所以打印出 script start;
- 遇到定时器 setTimeout,它是一个宏任务,将其加入到宏任务队列;
- 之后执行函数 async1,首先打印出 async1 start;
- 遇到 await,执行 async2,打印出 async2,并阻断后面代码的执行,将后面的代码加入到微任务队列;
- 然后跳出 async1 和 async2,遇到 Promise,打印出 promise1;
- 遇到 resolve,将其加入到微任务队列,然后执行后面的 script 代码,打印出 script end;
- 之后就该执行微任务队列了,首先打印出 async1 end,然后打印出 promise2;
- 执行完微任务队列,就开始执行宏任务队列中的定时器,打印出 setTimeout。
process.nextTick 类
- 题目
- 答案
console.log('1');
setTimeout(function () {
console.log('2');
process.nextTick(function () {
console.log('3');
})
new Promise(function (resolve) {
console.log('4');
resolve();
}).then(function () {
console.log('5')
})
})
process.nextTick(function () {
console.log('6');
})
new Promise(function (resolve) {
console.log('7');
resolve();
}).then(function () {
console.log('8')
})
setTimeout(function () {
console.log('9');
process.nextTick(function () {
console.log('10');
})
new Promise(function (resolve) {
console.log('11');
resolve();
}).then(function () {
console.log('12')
})
})
console.log('1');
setTimeout(function () {
console.log('2');
process.nextTick(function () {
console.log('3');
})
new Promise(function (resolve) {
console.log('4');
resolve();
}).then(function () {
console.log('5')
})
})
process.nextTick(function () {
console.log('6');
})
new Promise(function (resolve) {
console.log('7');
resolve();
}).then(function () {
console.log('8')
})
setTimeout(function () {
console.log('9');
process.nextTick(function () {
console.log('10');
})
new Promise(function (resolve) {
console.log('11');
resolve();
}).then(function () {
console.log('12')
})
})
// 1
// 7
// 6
// 8
// 2
// 4
// 3
// 5
// 9
// 11
// 10
// 12