Immutable.js

Nếu bạn quan tâm đến vấn đề tối ưu hóa khi viết một ứng dụng React thì Immutable.js là một thư viện không thể thiếu, đấy là một thư viện tuyệt vời. Immutable.js cung cấp các collection immutable, persistent:

  • Immutable: Mỗi khi được tạo, collection không thể thay đổi vào bất cứ lúc nào.
  • Persistent: collection mới có thể được tạo từ collection trước. Collection cũ vẫn valid sau khi collection mới được tạo.
  • Structural Sharing: collection mới được tạo sử dụng các cấu trúc của các collection cũ nếu có thể, giảm việc copy đến tối thiểu hoặc dữ liệu bộ nhớ cache nhằm cải thiện performance. Các cấu trúc dữ liệu này có hiệu quả cao đối với các máy ảo JavaScript hiện đại.

1. Getting started

Cài đặt immutable bằng cách sử dụng NPM. npm install immutable Sau đó require nó vào module bất kỳ.

const { Map } = require('immutable')
const map1 = Map({ a: 1, b: 2, c: 3 })
const map2 = map1.set('b', 50)
map1.get('b') // 2
map2.get('b') // 50

2. Browser

Để sử dụng Immutable.js từ browser, download dist/immutable.min.js hoặc sử dụng một CDN như CDNJS hoặc jsDelivr. Sau đó, thêm nó như một thẻ script vào trang của bạn:

<script src="immutable.min.js"></script>
<script>
    var map1 = Immutable.Map({a:1, b:2, c:3});
    var map2 = map1.set('b', 50);
    map1.get('b'); // 2
    map2.get('b'); // 50
</script>

Hoặc sử dụng bộ nạp AMD (như RequireJS ):

require(['./immutable.min.js'], function (Immutable) {
    var map1 = Immutable.Map({a:1, b:2, c:3});
    var map2 = map1.set('b', 50);
    map1.get('b'); // 2
    map2.get('b'); // 50
});

Nếu bạn đang sử dụng webpack hoặc browserify , immutable module cũng hoạt động từ trình duyệt.

3. Flow & TypeScript

Sử dụng các Immutable collections và sequences giống như bạn sử dụng các native collections trong các chương trình Flowtype hoặc TypeScript trong khi vẫn tận dụng lợi thế của các loại generics, phát hiện lỗi và tự động complete trong IDE của bạn. Cài đặt immutable qua NPM mang theo định nghĩa cho Flow (v0.39.0 hoặc cao hơn) và TypeScript (v2.1.0 hoặc cao hơn), do đó bạn không cần phải làm gì cả!

Sử dụng TypeScript với Immutable.js v4 Định nghĩa Immutable.js bao gồm ES2015. Mặc dù Immutable.js tự hỗ trợ các trình duyệt và môi trường kế thừa, các loại định nghĩa của nó yêu cầu phải có thư viện TypeScript 2015. Bao gồm "target" : "es2015" hoặc "lib" : "es2015" trong tsconfig.json hoặc gõ lệnh tsc -- target es2015 hoặc tsc -- lib es2015 trong cmd.

import { Map } from "immutable";
const map1 = Map({ a: 1, b: 2, c: 3 });
const map2 = map1.set('b', 50);
map1.get('b'); // 2
map2.get('b'); // 50

Sử dụng TypeScript với Immutable.js v3 and trước đó Các phiên bản trước của Immutable.js bao gồm reference file mà bạn có thể include relative path vào đầu file của bạn.

///<reference path='./node_modules/immutable/dist/immutable.d.ts'/>
import Immutable = require('immutable');
var map1: Immutable.Map<string, number>;
map1 = Immutable.Map({a:1, b:2, c:3});
var map2 = map1.set('b', 50);
map1.get('b'); // 2
map2.get('b'); // 50

4. Các trường hợp cho Immutability

Immutable collections nên được xem là giá trị chứ không phải đối tượng. Trong khi các đối tượng đại diện cho một số điều có thể thay đổi theo thời gian, một giá trị đại diện cho trạng thái của điều đó trong một trường hợp cụ thể. Nguyên tắc này là quan trọng nhất để hiểu được việc sử dụng dữ liệu không thay đổi hợp lý. Để Immutable.js collections được xem như là một giá trị, điều quan trọng là phải sử dụng chức năng Immutable.is() hoặc phương thức.equals ( ) để xác định các giá trị bằng nhau không thay vì toán tử === xác định tham chiếu đến đối tượng.

const { Map } = require('immutable')
const map1 = Map( {a: 1, b: 2, c: 3 })
const map2 = map1.set('b', 2)
assert(map1.equals(map2) === true)
const map3 = map1.set('b', 50)
assert(map1.equals(map3) === false)

Nếu một đối tượng là không thay đổi, nó có thể được sao chép đơn giản bằng cách làm một tham chiếu đến nó thay vì sao chép toàn bộ đối tượng. Bởi vì một tham chiếu nhỏ hơn nhiều so với đối tượng, điều này dẫn đến việc tiết kiệm bộ nhớ và tăng tiềm năng trong tốc độ thực hiện cho các chương trình dựa vào bản sao.

const { Map } = require('immutable')
const map1 = Map({ a: 1, b: 2, c: 3 })
const clone = map1;

5. JavaScript-first API

Trong khi Immutable.js được lấy cảm hứng từ Clojure, Scala, Haskell và các môi trường lập trình chức năng khác, nó được thiết kế để đưa những khái niệm mạnh mẽ này vào JavaScript, và do đó có một API hướng đối tượng tương phản với ES2015 Array , Map và Set . Sự khác biệt cho các immutable collections là các phương pháp có thể làm biến đổi bộ sưu tập, như push , set , unshift hoặc splice thay vì trả về một bộ sưu tập mới bất biến. Các phương thức trả về mảng mới như slice hoặc concat thay vì trả về các bộ sưu tập mới bất biến.

const { List } = require('immutable')
const list1 = List([ 1, 2 ]);
const list2 = list1.push(3, 4, 5);
const list3 = list2.unshift(0);
const list4 = list1.concat(list2, list3);
assert(list1.size === 2);
assert(list2.size === 5);
assert(list3.size === 6);
assert(list4.size === 13);
assert(list4.get(0) === 1);

Hầu như tất cả các phương thức trên Array sẽ được tìm thấy ở dạng tương tự trên Immutable.List , các Map được tìm thấy trên Immutable.Map, và của Set tìm thấy trên Immutable.Set, bao gồm các thao tác như forEach()map().

const { Map } = require('immutable')
const alpha = Map({ a: 1, b: 2, c: 3, d: 4 });
alpha.map((v, k) => k.toUpperCase()).join();
// 'A,B,C,D'