javascript const 真的是不变的吗?在还原?

Posted

技术标签:

【中文标题】javascript const 真的是不变的吗?在还原?【英文标题】:are javascript const really constant? in redux? 【发布时间】:2019-12-27 20:40:58 【问题描述】:

我的商店里有这个 reducer,初始状态 initialProcessingState 是从另一个源文件导入的。

import 
  ACTN_IS_PROCESSING
 from '../config/action-types.js';

import  initialProcessingState  from "./redProcessing-initial.js";

export default function (state = initialProcessingState, action) 
  switch (action.type) 

    case ACTN_IS_PROCESSING:
      return 
        ...state,
        ...action.isProcessing
      

    default:
      return state;
  

源文件中的定义如下:

export const initialProcessingState = 
  keys: [],
  mostRecentStatus: false,
  neverStale: true

现在我的商店通过订阅将状态保存到本地存储中

  store.subscribe(() => 
    updateLocalStorage(store);
  )

像这样……

import  initialProcessingState  from "../reducers/redProcessing-initial.js";

var updateLocalStorage = debounce((store) => 
  const state = store.getState();
  var _state = 
    ...state,
    isProcessing:  ...initialProcessingState 
  ;
  localStorage.setItem('reduxState', JSON.stringify(_state))
, 100);

我的意图是用它的初始状态覆盖isProcessing,在initialProcessingState中定义为const

很遗憾不起作用。因为每次调用updateLocalStorageinitialProcessingState 的值不是初始值,而是后续reducer 调用的当前更新状态。

这怎么可能?这是const

我的临时解决办法是涉及JSON.parse(JSON.stringify(initialProcessingState))

const _initialProcessingState = JSON.parse(JSON.stringify(initialProcessingState));

var updateLocalStorage = debounce((store) => 
  const state = store.getState();
  //this is not the best way
  console.log("updateLocalStorage", "initialProcessingState", initialProcessingState, _initialProcessingState);
  var _state = 
    ...state,
    isProcessing:  ..._initialProcessingState 
  ;
  localStorage.setItem('reduxState', JSON.stringify(_state))
, 100);

以下还不足以使其正常工作:

const _initialProcessingState = initialProcessingState;

有人可以帮忙吗?

【问题讨论】:

javascript 常量与其他语言不同。常量不是一成不变的。如果你的常量是指一个对象或数组,这个对象可以改变,你不能重新分配常量。 澄清这一点:const 的不变之处是对对象/值的引用。这是无法改变的。对象本身及其属性可以被改变。想想const biologicalFather = ...; 这是不变的,永远不会改变。 biologicalFather.facialHair 不是恒定的。并且所有更改都将适用于/对所有引用他的人可见。 【参考方案1】:

const 声明创建一个对值的只读引用。它 并不意味着它持有的值是不可变的,只是变量 无法重新分配标识符。例如,在 content 是一个对象,这意味着对象的内容(例如,它的 属性)可以更改。

来源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

编辑

@Apolo 在他的评论中指出,提及 Object.freeze() 可能很重要。

对象

Object.freeze() 方法冻结一个对象。冻结的物体不能 不再改变;冻结对象可防止新属性 被添加到它,现有的属性被删除,防止 改变可枚举性、可配置性或可写性 现有属性,并阻止现有属性的值 从被改变。此外,冻结一个物体也可以防止它 原型不会被改变。

但是对于Object.freeze(),同样重要的是要注意它没有扩展到冻结的object持有的值:

请注意,作为对象的 [对象] 值仍然可以修改,除非它们 也被冻结了。

数组

作为一个对象,数组可以被冻结;这样做之后,它的元素 不能更改,也不能添加或删除任何元素 数组。

EDIT部分中的来源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze

【讨论】:

为那些正在寻找创建不可变对象的方法的人添加一个关于 Object.freeze 的词会很高兴 (developer.mozilla.org/fr/docs/Web/JavaScript/Reference/…)【参考方案2】:

initialProcessingState 的值是对对象的引用。该值不能改变。

它引用的对象可以变异

【讨论】:

【参考方案3】:

const 表示无法重新分配引用。这就是为什么在分配字符串或数字的情况下,它们保持不可变,但在分配对象和数组时,可以通过它们的引用来修改其内容,使它们不是不可变的。

【讨论】:

【参考方案4】:

来自MDN:

const 声明创建一个对值的只读引用。它 并不意味着它持有的值是不可变的,只是变量 无法重新分配标识符。例如,在 content 是一个对象,这意味着对象的内容(例如,它的 属性)可以更改。

const foo =  bar : 'baz' ;
foo.bar = 'foo'; // works, because it doesn't change what foo is.
foo = null; // will fail, since it tries to change what foo is

您可以查看Object.freeze,但这只会冻结第一级:

const foo = Object.freeze(
  bar : 'baz',
  baz :  foo : 'bar'
);

foo.bar = 'foo'; // will not change since foo is frozen
foo.baz.foo = 'foo';  // will change, since foo.baz is not frozen 
console.dir(foo) 

【讨论】:

以上是关于javascript const 真的是不变的吗?在还原?的主要内容,如果未能解决你的问题,请参考以下文章

javascript真的是异步的吗?且看setTimeout的实现原理以及setTimeout的使用场景

Async.js - 并行真的是并行的吗?

Async.js - 并行真的是并行的吗?

JS 这次真的可以禁止常量修改了!

将 const int 分配给指向 int 的 const 指针是非法的吗?

按值传递时“const”不是多余的吗? [复制]