[解決済み】なぜJavaScriptでは不変性が重要(または必要)なのですか?
質問
現在、私は リアクトJS と リアクトネイティブ フレームワークです。途中から、Immutabilityや、そのための Immutable-JSライブラリ FacebookのFluxとReduxの実装について読んでいたときです。
問題は、なぜ不変性がそれほど重要なのか、ということです。オブジェクトを変異させることの何が問題なのでしょうか?物事を単純にするものではないのでしょうか?
例として、単純な ニュースリーダー アプリのオープニング画面は、ニュースヘッドラインのリストビューです。
例えば オブジェクトの配列 という値で 最初は 操作できないんです。不変性原理はそう言っていますよね?(間違っていたら訂正してください) しかし、新しいNewsオブジェクトを更新しなければならない場合はどうでしょうか?通常の場合、そのオブジェクトを配列に追加するだけでよかったのです。 この場合、どうすればいいのでしょうか?ストアを削除して、再作成しますか? オブジェクトを配列に追加する方が、より安価な処理ではないでしょうか?
どのように解決するのですか?
最近、同じテーマで研究しています。私はあなたの質問(複数可)に答えるために最善を尽くし、私がこれまでに学んだことを共有しようとします。
<ブロッククオート問題は、なぜ不変性がそれほど重要なのか、ということです。何が問題で オブジェクトを変異させる?物事をシンプルにするのではないのでしょうか?
基本的には、不変性が予測可能性を高め、パフォーマンスを(間接的に)向上させ、突然変異の追跡を可能にするという事実に帰結します。
予測可能性
突然変異は変化を隠すので、(予期しない)副作用を生み出し、厄介なバグの原因となる。不変性を強制すると、アプリケーションのアーキテクチャとメンタルモデルをシンプルに保つことができ、アプリケーションに関する推論が容易になります。
パフォーマンス
イミュータブルオブジェクトに値を追加する場合、新しいインスタンスを作成し、既存の値をコピーして、新しい値を新しいオブジェクトに追加する必要があり、メモリコストがかかりますが、イミュータブルオブジェクトは構造共有を利用してメモリのオーバーヘッドを削減することができます。
<ブロッククオートすべての更新は新しい値を返しますが、内部で構造体を共有することで メモリ使用量(とGCスラッシング)を劇的に削減します。これは、もし 1000 要素のベクトルに追加しても、実際に作成されるのは は1001要素の長さの新しいベクトルです。ほとんどの場合、内部ではいくつかの の小さなオブジェクトが割り当てられます。
詳しくはこちらをご覧ください こちら .
ミューテーショントラッキング
メモリ使用量の削減のほか、参照と値の等価性を利用したアプリケーションの最適化も可能です。これにより、何かが変更されたかどうかを実に簡単に確認することができます。例えば、reactコンポーネントの状態が変化した場合。この場合
shouldComponentUpdate
を使用すると、状態オブジェクトの比較によって状態が同一かどうかを確認し、不要なレンダリングを防止することができます。
詳しくはこちら
ここで
.
追加資料です。
オブジェクトの配列に値を初期設定する場合。このままでは それを操作する。不変性原理はそう言っていますよね? 間違っていたら教えてください)。しかし、新しいNewsオブジェクトが必要な場合はどうでしょう。 更新されるのでしょうか?通常の場合、そのオブジェクトを 配列になります。この場合、どうすればいいのでしょうか?ストア&アンプを削除し、それを再作成しますか? オブジェクトを配列に追加する方が、より安価な操作ではないでしょうか?
はい、これは正しいです。もし、あなたのアプリケーションでこれをどのように実装するかで迷っているのであれば、次の方法を見ることをお勧めします。 リデュース を実行することで、核となる概念に精通することができます。
私がReduxを例に挙げるのが好きなのは、Reduxがイミュータビリティを受け入れているからです。Reduxは、単一のイミュータブルなステートツリー(以下、「ステートツリー」と呼ぶ)を持っています。
store
このアクションはreducerによって処理され、reducerは前の状態とアクションを(一度に一つずつ)受け取り、アプリケーションの次の状態を返します。その基本的な原理については、以下の記事をご覧ください。
こちら
.
には素晴らしいreduxのコースがあります。 egghead.io どこ ダン・アブラモフ reduxの作者である某氏は、この原則を以下のように説明しています(シナリオに合うようにコードを少し修正しました)。
import React from 'react';
import ReactDOM from 'react-dom';
// Reducer.
const news = (state=[], action) => {
switch(action.type) {
case 'ADD_NEWS_ITEM': {
return [ ...state, action.newsItem ];
}
default: {
return state;
}
}
};
// Store.
const createStore = (reducer) => {
let state;
let listeners = [];
const subscribe = (listener) => {
listeners.push(listener);
return () => {
listeners = listeners.filter(cb => cb !== listener);
};
};
const getState = () => state;
const dispatch = (action) => {
state = reducer(state, action);
listeners.forEach( cb => cb() );
};
dispatch({});
return { subscribe, getState, dispatch };
};
// Initialize store with reducer.
const store = createStore(news);
// Component.
const News = React.createClass({
onAddNewsItem() {
const { newsTitle } = this.refs;
store.dispatch({
type: 'ADD_NEWS_ITEM',
newsItem: { title: newsTitle.value }
});
},
render() {
const { news } = this.props;
return (
<div>
<input ref="newsTitle" />
<button onClick={ this.onAddNewsItem }>add</button>
<ul>
{ news.map( ({ title }) => <li>{ title }</li>) }
</ul>
</div>
);
}
});
// Handler that will execute when the store dispatches.
const render = () => {
ReactDOM.render(
<News news={ store.getState() } />,
document.getElementById('news')
);
};
// Entry point.
store.subscribe(render);
render();
また、これらのビデオでは、immutability forを実現する方法をさらに詳しく説明しています。
関連
-
[解決済み】document.getElementByIDは関数ではありません。
-
[解決済み】XMLHttpRequestモジュールが定義されていない/見つからない
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] JavaScriptで文字列が部分文字列を含むかどうかを確認する方法は?
-
[解決済み] あるJavaScriptファイルを他のJavaScriptファイルにインクルードするにはどうすればよいですか?
-
[解決済み] JavaScriptでメールアドレスを検証するのに最適な方法は何ですか?
-
[解決済み] JavaScriptでタイムスタンプを取得する方法は?
-
[解決済み】JavaScriptの比較では、どちらの等号演算子(== vs ===)を使うべきですか?
-
[解決済み】JavaScriptで文字列の出現箇所をすべて置換する方法
-
[解決済み】オブジェクトからプロパティを削除する(JavaScript)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Heroku:ノードアプリで「このアプリにはデフォルトの言語が検出されませんでした」エラーがスローされる
-
[解決済み】TypeError: 'undefined'はオブジェクトではありません。
-
[解決済み】SecurityError: オリジンを持つフレームがクロスオリジンフレームにアクセスするのをブロックした
-
[解決済み】ある要素が可視DOMに存在するかどうかを確認するにはどうすればいいですか?
-
[解決済み】コンソールがUnterminated JSX contentsエラーを投げる【終了しました
-
[解決済み】getElementByIdはnullを返す?[クローズド]
-
[解決済み】DOMException: サポートされているソースが見つからなかったため、読み込みに失敗しました。
-
[解決済み】Vueのテンプレートまたはレンダー関数が定義されていない 私はどちらも使っていないのですが?
-
[解決済み】module.exports "モジュールが定義されていません"
-
[解決済み] レースコンディションとは何ですか?