运算符自加和自减 ++x 和 x++

Frist One

1
2
3
4
var x = 1
console.log(x)
console.log(x++)
console.log(++x)

Second

1
2
3
4
5
6
7
8
9
let a = 0, b = 0;
function fn(a) {
fn = function fn2(b) {
alert(++a+b);
}
alert(a++);
}
fn(1);
fn(2);

对一个数进行加一、减一是最常见的数学运算符之一。

++ 自减相当于给变量+1

1
2
3
let counter = 2;
counter++; // 和 counter = counter + 1 效果一样,但是更简洁
alert( counter ); // 3

注意:
自加/自减只能应用于变量。试一下,将其应用于数值(比如 5++)则会报错
运算符 ++ 和 – 可以置于变量前,也可以置于变量后。

当运算符置于变量后,被称为「后置形式」:counter++
当运算符置于变量前,被称为「前置形式」:++counter

所有的运算符都有返回值,自减自加也不例外,
前置形式都返回一个新的值
后置返回原来的值

注意说的是返回的值

task && microTask

Promise 1

1
2
3
4
5
var b = new Promise(resolve => window.resolve = resolve)
var a = new Promise(resolve => resolve(b))
a.then(() => console.log('a'))
b.then(() => console.log('b'))
resolve()

某学堂的面试题,好基友当时估计没睡醒,没答上来就直接跪了,有点狠

Generator next传参

1
2
3
4
5
6
7
8
9
10
11
12
13
function *foo(x) {
let y = 2 * (yield (x + 1))
let z = yield (y / 3)
return (x + y + z)
}
let it = foo(5)
console.log(it.next(11))
console.log(it.next(12))
console.log(it.next(13))

// {value: 6, done: false}
// {value: 8, done: false}
// {value: 42, done: true}

深呼吸几口,理解理解
yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。

macroTask

1
2
3
4
5
6
7
8
9
10
11
12
13
Promise.resolve().then(()=>{
console.log('Promise1')
setTimeout(()=>{
console.log('setTimeout2')
},0)
});
setTimeout(()=>{
console.log('setTimeout1')
Promise.resolve().then(()=>{
console.log('Promise2')
})
},0);
console.log('start');

微任务产生的宏任务要往后排队

async/await执行顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
// p1
// script end

我们知道async隐式返回 Promise 作为结果的函数,那么可以简单理解为,await后面的函数执行完毕时,await会产生一个微任务(Promise.then是微任务)。但是我们要注意这个微任务产生的时机,它是执行完await之后,直接跳出async函数,执行其他代码(此处就是协程的运作,A暂停执行,控制权交给B)。其他代码执行完毕后,再回到async函数去执行剩下的代码,然后把await后面的代码注册到微任务队列当中。我们来看个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
console.log('script start')
async function async1() {
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2 end')
}
async1()
setTimeout(function() {
console.log('setTimeout')
}, 0)
new Promise(resolve => {
console.log('Promise')
resolve()
})
.then(function() {
console.log('promise1')
})
.then(function() {
console.log('promise2')
})
// start
// async2 end
// promise
// async1 end
// p1
// p2
// setTimeout

如果await后面跟的是一个异步函数的调用,比如上面的代码,将代码改成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
console.log('script start')
async function async1() {
await async2()
console.log('async1 end') // 最后一个微任务
}
async function async2() {
console.log('async2 end')
return Promise.resolve().then(()=>{
console.log('async2 end1')
})
}
async1()
setTimeout(function() {
console.log('setTimeout')
}, 0)
new Promise(resolve => {
console.log('Promise')
resolve()
})
.then(function() {
console.log('promise1')
})
.then(function() {
console.log('promise2')
})
// script start => async2 end => Promise =>async2 end1 => promise1 => promise2 => async1 end => setTimeout

this相关

one

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const o1 = {
text: 'o1',
fn: function() {
return this.text
}
}
const o2 = {
text: 'o2',
fn: function() {
return o1.fn()
}
}
const o3 = {
text: 'o3',
fn: function() {
var fn = o1.fn
return fn()
}
}
console.log(o1.fn()) // 01
console.log(o2.fn()) // 01
console.log(o3.fn()) // undefined

Two

1
2
3
4
5
6
7
8
9
10
var test = {
name: 'cpp',
fn: function() {
console.trace()
console.log(this.name)
}
}
var name = 'wmh'
test.fn() // cpp
test.fn.call(this) // wmh

Three

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var fullName = '1'
var obj = {
fullName: '2',
prop: {
fullName: '3',
getFullName: () => {
console.log(this)
return this.fullName
}
}
}
console.log(obj.prop.getFullName())
var test = obj.prop.getFullName
console.log(test())

作用域相关

one

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var a = 20
var test = {
a: 40,
init: function() {
console.log(this.a)
function go() {
console.log(this, 'new')
console.log(this.a)
}
go.prototype.a = 50
return go
}
}
var p = test.init() //
p() //
new p() //

init改成箭头函数呢

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var a = 20
var test = {
a: 40,
init: () => {
console.log(this.a)
function go() {
console.log(this, 'new')
console.log(this.a)
}
go.prototype.a = 50
return go
}
}
var p = test.init() //
p() //
new p() //

原型链

one

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function A() {
this.a = 1;
}
A.prototype.b = 1;

const a = new A();
console.log(a.a); // 1
console.log(a.b); // 1

const b = new A();
b.__proto__.a = 2;
A.prototype.b = 2;

console.log(a.a); // 1
console.log(a.b); // 2