连续赋值
let a = { n: 1 }
let b = a
a.x = a = { n: 2 }
console.log(a.x)
console.log(b.x)
考察重点
- 堆栈内存:堆存储引用类型,栈存储值类型和指针(堆的引用)
- .的优先级要大于 = 分析执行过程
- 首先执行a.x,即 { n: 1 } 这个堆内存中添加x,变成 { n: 1, x: undefined }
- a.x = a = { n: 2 } ==> a和b共同指向的堆内存.x = a = { n: 2 }。左边操作的是堆的x属性,和a没关系了。从始至终a和b只是个引用
// 输出:undefined { n: 2 }
['1', '2', '3'].map(parseInt)
// 执行过程
const arr = ['1', '2', '3'];
arr.map((v, i) => {
return parseInt(v, i)
})
// parseInt(1, 0) // 10进制表示的1,转成10进制,返回1
// parseInt(2, 1) // 1不在2-36范围内,返回NaN
// parseInt(3, 2) // 2进制只有0 | 1,表示不了3,返回NaN
- parseInt(string, radix),radix表示string是多少进制的
- 当参数 radix 的值为 0,或没有设置该参数时, 会根据string来判断基数, 除了2-36,都是NaN
- 0x: 16进制, 0: 8进制(旧的浏览器默认使用八进制基数,各个浏览器不一定都是, es5禁止了)
promise执行顺序
多个fulfilled状态的promise实例,会交替执行then的回调,防止某个promise占用时间过长
Promise.resolve().then(() => {
console.log(1)
}).then(() => {
console.log(2)
}).then(() => {
console.log(3)
})
Promise.resolve().then(() => {
console.log(10)
}).then(() => {
console.log(20)
}).then(() => {
console.log(30)
})
// 输出:1, 10, 2, 20, 3, 30
在then回调返回一个新的fulfilled状态的promise,当前promise会比其他另外promise少走两步
- promise状态由pending变成fulfilled
- promise.then回调注册到微任务队列
Promise.resolve().then(() => {
console.log(0)
return Promise.resolve(4)
}).then((res) => {
console.log(res)
})
Promise.resolve().then(() => {
console.log(1)
}).then(() => {
console.log(2)
}).then(() => {
console.log(3)
}).then(() => {
console.log(5)
}).then(() => {
console.log(6)
})
console.log(-1)
// 输出:-1, 0, 1, 2, 3, 4, 5, 6
setState
import React from 'react' // version: 16.13.1
class SetStateTest extends React.Component {
constructor() {
super()
this.state = {
val: 0
}
}
render() {
return (
<div id='div1'>{this.state.val}</div>
)
}
}
export default SetStateTest
默认多个会合并
componentDidMount() {
this.setState({ val: this.state.val + 1 })
this.setState({ val: this.state.val + 1 })
this.setState({ val: this.state.val + 1 })
// 页面最终展示还是1
}
默认异步更新
componentDidMount() {
this.setState({ val: this.state.val + 1 }, () => {
console.log("1.callback.val", this.state.val)
})
// 可以在回调里打印最新值
this.setState({ val: this.state.val + 10 }, () => {
console.log("2.callback.val", this.state.val)
})
// 页面最终展示10,但这里打印0
console.log("val", this.state.val)
// 以上两个setState的回调,打印的都是10。(第二个+10会覆盖掉+1,默认合并)
// 可以知道所有setState的回调,都是一起执行的。这也是为了性能,不管setState了多少次,都是最后一起执行回调
}
同步更新情况
setTimeout,setInterval,Promise,ajax, 自定义事件。总之就是非react上下文
componentDidMount() {
setTimeout(() => {
this.setState({ val: this.state.val + 1 })
console.log("setTimeout.val", this.state.val)
})
Promise.resolve().then(() => {
this.setState({ val: this.state.val + 1 })
console.log("Promise.val", this.state.val)
})
// 使用原生点击事件注册回调,展示的state就是最新的
document.getElementById("div1").addEventListener("click", this.fnAdd)
}
fnAdd = () => {
this.setState({ val: this.state.val + 1 })
this.setState({ val: this.state.val + 1 })
console.log("fnAdd.val", this.state.val) // 4
}
不会合并情况
同步更新(场景同上)、传入函数
// 传入函数,不会合并
fnSyncAdd = () => {
this.setState((prev, next) => {
return { val: prev.val + 1 }
})
this.setState((prev, next) => {
return { val: prev.val + 1 }
})
}
componentDidMount() {
this.setState({ val: this.state.val + 1 })
console.log(this.state.val)
this.setState({ val: this.state.val + 1 })
console.log(this.state.val)
setTimeout(() => {
this.setState({ val: this.state.val + 1 })
console.log(this.state.val)
this.setState({ val: this.state.val + 1 })
console.log(this.state.val)
}, 0)
// 输出:0, 0, 2, 3
// react18输出的是:0, 0, 1, 1
}
宏任务还是微任务
- 既不是宏任务也不是微任务,只是同步执行,看起来像是微任务。
- 执行完后立即调用注册的回调,所以会出现在Promise之前
fnTestQueue = () => {
console.log("start")
setTimeout(() => {
console.log("setTimeout");
})
Promise.resolve().then(() => {
console.log("Promise.resolve")
})
this.setState({ val: this.state.val + 1 }, () => {
console.log("setState.callback")
})
console.log("end")
}
// 输出:
// start
// end
// setState.callback
// Promise.resolve
// setTimeout