在这里想总结比较一下直接赋值和函数式赋值的一些特点和用途

  • 直接赋值是及时的,二次调用可能不变
  • 函数式赋值延迟性的,二次调用会刷新值,获得最新的

一、简单类型数据赋值比较

  • 假设有一个数据 100 传给 a、b
  • 这里通过直接赋值和函数式赋值两种方式传递
  1. data = 100
  2. let a = data
  3. let b = function(){return data}
  4. // data 更新为 101
  5. data = 101
  6. console.log(`a:${a},b:${b()}`)
  7. // a:100,b:101

可以得到结论

  • 简单类型的数据的赋值是“完完整整”的复制
  • 第二种方式是复制函数,它的复制的是函数的地址,指向同一个内容

二、换成对象试试?

  1. data2 = {n:100}
  2. let c = data2
  3. let d = ()=>{return data2}
  4. data2.n = 101
  5. console.log("c:",c,",d:",d())
  6. // c:{n:101},d:{n:101}
  • 对象和函数一样,赋值是复制的地址,指向同一个内容

三、函数式赋值的“刷新”

假设 a 被赋值给了一个数值和函数(不要问为什么同时能被赋值一个数值和函数),它就有这样一个特性

  • 数值更新了,a 的数值不会更新
  • 函数更新了,a 的函数会更新

我想让它们都更新,怎么办?把数值和函数包起来变成一个函数

  • a ()=>{ ←(数值 + 函数)}

我无法自己写出一个这样的例子,但我在 React 中见到过这样的情况

  1. let App = React.createElement('div', {className: test}, n)

这里的 n 就是赋值给了实例,想要实时“刷新”,就把它改造成函数

  1. let App = ()={React.createElement('div', {className: test}, n)}

四、setTimeout 函数

  • 看一看循环语句和 setTimeout 函数的配合
  1. let i = 1
  2. for (i=1;i<=6;i++){
  3. setTimeout(()=>console.log(i),0)
  4. }
  5. // 打印出 6 个 7
  6. 7 7 7 7 7 7 7

这是怎么回事?怎么不打印出 1 2 3 4 5 6?

setTimeout 函数意思是立即执行,i 等于 1 ~ 6 的时候,发生 6 次立即打印 i 但没有执行,当循环结束,i 的值等于 7 的时候,前面的立即打印 i 开始执行,取得 i 的值为 7,于是打印出 6 个 7。

  • console.log(i) 只在函数调用的时候执行
  • i = 7 后,前面提前准备好的 6 个 console.log(i) 获得 i 的值并开始执行
  • 这就是函数赋值延迟性

如果想预期打印出 1 2 3 4 5 6,可以再设置一个变量存起来

  1. let i = 1
  2. for (i=1;i<=6;i++){
  3. let j = i
  4. setTimeout(()=>console.log(j),1000)
  5. }

「@浪里淘沙的小法师」