Cách tạo cửa hàng bằng các hàm thuần túy

Khám phá JavaScript chức năng được BookAuthority đặt tên là một trong những cuốn sách Lập trình chức năng mới tốt nhất!

Ảnh của Ugur Akdemir trên Bapt

Các hàm thuần tạo ra cùng một giá trị đầu ra, cho cùng một đầu vào. Chúng không có tác dụng phụ, và dễ đọc, hiểu và kiểm tra hơn.

Với tất cả điều này, tôi muốn tạo ra một cửa hàng che giấu trạng thái nhưng đồng thời sử dụng các hàm thuần túy.

Bất biến

Các hàm thuần túy don lồng sửa đổi đầu vào của chúng. Họ coi các giá trị đầu vào là bất biến.

Một giá trị bất biến là một giá trị mà một khi được tạo ra không thể thay đổi.

Immutable.js cung cấp các cấu trúc dữ liệu bất biến như Danh sách. Một cấu trúc dữ liệu bất biến sẽ tạo ra một cấu trúc dữ liệu mới tại mỗi hành động.

Hãy xem xét mã tiếp theo:

nhập {Danh sách} từ "bất biến";
danh sách const = Danh sách ();
const newList = list.push (1);

push () tạo một danh sách mới có thành phần mới. Nó không sửa đổi danh sách hiện có.

xóa () trả về một Danh sách mới trong đó phần tử tại chỉ mục đã chỉ định đã bị xóa.

Cấu trúc dữ liệu Danh sách cung cấp một giao diện đẹp để làm việc với các danh sách theo cách không thay đổi, vì vậy tôi sẽ sử dụng nó làm giá trị trạng thái.

Cửa hàng

Cửa hàng quản lý nhà nước.

Nhà nước là dữ liệu có thể thay đổi. Cửa hàng che giấu dữ liệu trạng thái đó và cung cấp một bộ phương thức công khai để làm việc với nó.

Tôi muốn tạo một cửa hàng sách với các phương thức add (), remove () và getBy ().

Tôi muốn tất cả các chức năng này là chức năng thuần túy.

Sẽ có hai loại chức năng thuần túy được sử dụng bởi cửa hàng:

  • các chức năng sẽ đọc và lọc trạng thái. Tôi sẽ gọi họ là getters.
  • chức năng sẽ sửa đổi trạng thái. Tôi sẽ gọi họ là setters.

Cả hai loại hàm này sẽ lấy trạng thái làm tham số đầu tiên của chúng.

Hãy để viết thư cho cửa hàng bằng cách sử dụng các hàm thuần túy.

nhập {Danh sách} từ "bất biến";
nhập một phần từ "lodash / một phần";
nhập MatchProperty từ "lodash / MatchProperty";
// setters
thêm chức năng (sách, sách) {
  return Books.push (cuốn sách);
}
chức năng loại bỏ (sách, sách) {
  const index = Books.find Index (MatchProperty ("id", book.id));
  trả lại sách.delete (chỉ mục);
}
// getters
chức năng queryContainsBook (truy vấn, sách) {
  if (truy vấn && query.text) {
    return book.title.includes (query.text);
  }
  trả lại đúng sự thật;
}
hàm getBy (sách, truy vấn) {
  return Books.filter (một phần (queryContainsBook, query)). toArray ();
}

Thư viện

Nhà nước nên được ẩn bên trong các đối tượng cửa hàng. Tôi không muốn gửi nhà nước từ bên ngoài đến đối tượng cửa hàng. Đồng thời, tôi muốn nhận được tất cả các lợi ích của các hàm thuần túy và sử dụng chúng để xác định các phương thức lưu trữ.

Làm thế nào điều này có thể đạt được?

Chúng tôi đã thấy câu trả lời trong Redux. Chúng tôi viết các hàm thuần túy và để thư viện tạo cửa hàng và áp dụng các hàm thuần túy.

Đây là cách tôi muốn sử dụng thư viện để xác định cửa hàng:

nhập {Danh sách} từ "bất biến";
nhập Cửa hàng từ "./Store-toolbox";
// setters
thêm chức năng (sách, sách) {}
chức năng loại bỏ (sách, sách) {}
// getters
hàm getBy (sách, truy vấn) {}
xuất mặc định Store ({
  trạng thái: Danh sách (),
  setters: {thêm, xóa},
  getters: {getBy}
});

Hãy để xây dựng thư viện vi mô này tạo ra cửa hàng dựa trên các getters và setters thuần túy.

Tất cả các getters và setters công cộng sẽ được trang trí và sẽ nhận trạng thái là tham số đầu tiên của họ.

  • Giá trị trả về từ getters sẽ được trả về các hàm người gọi.
  • Giá trị trả về từ stetters sẽ được sử dụng để thay đổi trạng thái. Các chức năng người gọi sẽ không nhận được trạng thái mới.
chức năng trang tríMethods (obj, trang trí) {
  hãy để newObject = {... obj};
  Object.keys (newObject) .forEach (chức năng trang tríMethod (fnName) {
    if (typeof newObject [fnName] === "function") {
      newObject [fnName] = decorator (newObject [fnName]);
    }
  });
  trả về newObject;
}
Hàm lưu trữ (storeConfig) {
  Hàm trả về () {
    let state = storeConfig.state;
    hàm setter (fn) {
      Hàm trả về (... args) {
        state = fn (bang, ... args);
      };
    }
    hàm getter (fn) {
      Hàm trả về (... args) {
        trả về fn (trạng thái, ... args);
      };
    }
    trả về Object.freeze ({
      ... trang tríMethods (storeConfig.getters, getter),
      ... trang tríMethods (storeConfig.setters, setter)
    });
  };
}
xuất mặc định Store;

Store () tạo một hàm trả về một đối tượng đóng gói trạng thái.

Hãy để cùng nhau tạo và sử dụng đối tượng bookStore:

nhập BookStore từ "./BookStore";
const bookStore = BookStore ();
bookStore.add ({id: 1, tiêu đề: "Cách JavaScript hoạt động"});

Khi gọi bookStore.add ({}), trình trang trí setter sẽ gọi hàm setter thuần add () với trạng thái hiện tại là tham số đầu tiên và sách mới là tham số thứ hai. Sau đó, trình trang trí setter sẽ sử dụng kết quả để thay đổi giá trị của trạng thái.

Đối tượng

Hãy để phân tích đối tượng bookStore.

Nó chỉ hiển thị ba phương thức, tất cả các hàm thuần túy khác là riêng tư.

Giao diện chung của đối tượng có thể được sửa đổi từ bên ngoài.

Nhà nước bị ẩn. Các máy khách sử dụng đối tượng bookStore chỉ có thể truy cập trạng thái thông qua các phương thức công khai.

Phần kết luận

Các chức năng thuần túy dễ dàng hơn để lý do về.

Chúng ta có thể tạo một cửa hàng ẩn trạng thái và sử dụng các hàm thuần túy với sự trợ giúp của thư viện.

Chúng ta chỉ có thể viết các hàm thuần túy và để thư viện áp dụng chúng và thực hiện đột biến.

Bạn có thể kiểm tra mã mẫu trên Codeandbox.io.

Khám phá JavaScript chức năng được BookAuthority đặt tên là một trong những cuốn sách Lập trình chức năng mới tốt nhất!

Để biết thêm về việc áp dụng các kỹ thuật chức năng cho React, hãy xem React Functional.

Tìm hiểu làm thế nào để áp dụng các nguyên tắc của các mẫu thiết kế.

Bạn có thể tìm thấy tôi trên Twitter.