Lập trình khai báo JavaScript

mã khai báo. đó là một thuật ngữ nóng trong tất cả các loại lập trình. Nhưng những gì nó thực sự có nghĩa gì?

Đây có thể là một sự thay đổi tinh thần đầy thách thức để thực hiện. May mắn thay, các phiên bản JavaScript hiện đại giúp việc bắt đầu với mã khai báo trở nên dễ dàng hơn bao giờ hết

Tuyên bố vs. ngôn ngữ bắt buộc

Ngoài sự phổ biến của nó với các lập trình viên, khai báo so với. ngôn ngữ bắt buộc có nhiều liên quan đến các ngành khác. Xét câu sau

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
0

Câu trên là bắt buộc. nó mô tả làm thế nào để làm một cái gì đó. Giống như một cuốn tiểu thuyết của JRR Tolkien, nó chứa đầy chi tiết. Tuy nhiên, nó thiếu những gì tất cả các bước này cộng lại. Đây là nơi ngôn ngữ khai báo xuất hiện

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
1

Câu trên là câu khẳng định. Nó mô tả những gì bạn đã làm mà không nói rõ bạn đã làm như thế nào. Đó là phiên bản mua đồ tạp phẩm của Hemingway

Ngôn ngữ khai báo thường được sử dụng để tắt thông tin đã rõ ràng cho người đọc. Hầu hết mọi người đều biết các bước liên quan đến việc đi đến cửa hàng, không cần phải lo lắng về các chi tiết.  

Mã có thể được viết theo cách tương tự, sử dụng kiểu khai báo để nhanh chóng truyền đạt mục đích mà không bị sa lầy trong quá trình triển khai.  

Không bao giờ sử dụng vòng lặp “For” để lặp lại mảng

Tôi không lặp mảng với vòng lặp

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
2 nữa. Và với lý do chính đáng. Tôi phải đọc từng dòng của vòng lặp for để hiểu nó đang làm gì. Vòng lặp không phải là vấn đề, mà là do thiếu ngữ cảnh mà một vòng lặp 
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
2 đơn giản cung cấp. Đây là lỗ hổng mà mã khai báo có thể lấp đầy và JavaScript cung cấp các hàm tích hợp để giúp chúng tôi giải quyết

Mảng. bản đồ[]

Hãy xem ví dụ dưới đây, cố gắng tìm ra những gì nó đang làm

const numbers = [1, 2, 3, 4];
const numbersDoubled = [];
for [let i = 0; i < numbers.length; i++] {
    numbersDoubled.push[numbers[i] * 2];
}

Đoạn mã trên sử dụng vòng lặp for để lặp qua mảng 

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
4. Trong mỗi lần lặp, số hiện tại được nhân với hai và được đẩy lên
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
5. Khi vòng lặp kết thúc, mọi giá trị trong
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
5 sẽ gấp đôi giá trị tương ứng của nó trong
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
4

Giải pháp ở trên có chức năng, nhưng bạn phải phân tích cú pháp từng dòng và sau đó thực hiện một bước nhảy vọt trực quan để hiểu mã đang làm gì. Thao tác khá đơn giản này có thể được truyền đạt theo cách dễ hiểu hơn không?

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];

Giải pháp này mang tính khai báo hơn. Mảng. map[] trả về một mảng mới bắt nguồn từ giá trị của mảng mà nó được gọi. Mỗi giá trị trong mảng nguồn được chuyển đến một hàm gọi lại, nơi nó có thể được chuyển đổi trước khi được chuyển sang mảng mới

Giống như đi đến cửa hàng tạp hóa, các bước lặp qua một mảng và tạo một biến mới là giống nhau mọi lúc. Không cần phải liên tục viết lại chúng

Điều này có vẻ như là một sự khác biệt nhỏ, nhưng Array. map[] truyền đạt rất nhiều thông tin mà tôi cần phải tự ghép lại với nhau. Với Mảng. map[], tôi biết rằng

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
5 sẽ là một mảng mới bắt nguồn từ
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
4 và nó sẽ có cùng độ dài với các số. Trừ khi quá trình truyền diễn ra trong cuộc gọi lại, tôi có thể giả định một cách hợp lý rằng các giá trị của nó sẽ cùng loại với
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
4. Điều duy nhất tôi phải phân tích cú pháp là chức năng gọi lại

NHƯNG HÃY ĐỢI, giải pháp này còn cung cấp nhiều thông tin mới hơn. Mảng. map[] là bất biến, nghĩa là nó trả về một mảng mới thay vì sửa đổi mảng nguồn. Bằng cách sử dụng Mảng này. map[], tôi chỉ ra rằng

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
4 sẽ không bị sửa đổi khi dẫn xuất
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
5

Nhìn vào tất cả các thông tin đó. Tôi đã trao đổi nhiều hơn về mã của mình đồng thời quản lý để viết ít hơn về mã đó

Mảng. lọc[]

Xem xét một kịch bản khác. Thay vì nhân đôi mỗi giá trị trong

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
4, tôi muốn tạo một bản sao chỉ chứa các số chẵn. Một giải pháp cấp bách có thể trông như thế này

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
6

 

Vòng lặp

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
2 ở trên lặp qua mảng và sử dụng toán tử phần dư để xác định xem mỗi số có chia hết cho 0 không. Nếu biểu thức này là trung thực , thì số được đẩy lên
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
65. Giống như ví dụ đầu tiên, giải pháp này
hoạt động nhưng nó phải được phân tích cú pháp để hiểu được.

 

May mắn thay, có Array. lọc[]. Tương tự như map, Array. filter[] tạo một mảng mới bằng cách chuyển từng giá trị trong mảng nguồn tới hàm gọi lại. Tuy nhiên, cuộc gọi lại này chỉ cần trả lại

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
66 hoặc
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
67. Nếu giá trị trả về là
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
66, giá trị được bao gồm trong mảng mới. Nếu
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
67, nó bị bỏ đi

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
3

Giải pháp trên vẫn sử dụng toán tử phần dư để xác định xem số đó có phải là số chẵn hay không, nhưng các bước lặp qua nguồn và điền vào một mảng mới được xử lý chính xác bởi hàm bộ lọc

Đây là một cải tiến lớn, nhưng thao tác này có thể mang tính khai báo hơn nữa. Một mục tiêu dễ dàng để viết mã khai báo là chuẩn hóa các hoạt động. những hoạt động nào trong ví dụ này có thể được chuyển thành một chức năng có thể tái sử dụng?

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
4

 

Đoạn mã trên triển khai hàm trợ giúp để xác định xem một số có chia hết cho 0 không. Giống như đi đến cửa hàng tạp hóa, thực sự chỉ có một cách để thực hiện thao tác này. Không cần phải trình bày lại cách nó được thực hiện mỗi lần

 

Trong một dòng mã, tôi đã thông báo rằng

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
65 là một giá trị không đổi bắt nguồn từ
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
4 và bộ lọc chỉ bao gồm các số chẵn. Đó là rất nhiều thông tin trong rất ít dòng

 

Khi các hoạt động trở nên phức tạp hơn, thông tin được truyền đạt bằng mã khai báo càng trở nên có giá trị hơn. Hãy xem một ví dụ khác

Mảng. giảm[]

Khoảng thời gian này, tôi muốn tính tổng tất cả các giá trị trong

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
4. Một cách tiếp cận bắt buộc có thể trông như thế này

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
8

Đoạn mã trên tính tổng mảng số, nhưng nó vẫn không cho chúng ta biết bất cứ điều gì về chính nó. Tôi có thể thực hiện bất kỳ hành động nào bên trong vòng lặp này, cách duy nhất để tìm hiểu là đọc nó

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
9

Mảng. reduce[] cung cấp bối cảnh quan trọng. nó cho biết các giá trị mới đang được lấy từ nội dung của bất kỳ mảng nào. Giá trị mới này có thể thuộc bất kỳ loại nào, nhưng cách sử dụng phổ biến bao gồm các phép toán như tính tổng ở trên.  

Cú pháp giống như bản đồ và bộ lọc, nhưng thêm một đối số khác.

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
33 ở cuối được gọi là “accumulator”. Mỗi lần lặp chuyển bộ tích lũy vào hàm gọi lại làm đối số đầu tiên, nơi nó có thể được cập nhật trước khi cuối cùng được trả về làm đầu ra của hàm rút gọn. Trong trường hợp này, tôi đang thêm từng số từ mảng vào bộ tích lũy. Khi hoàn thành, kết quả là tổng của mọi số trong
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
4

Giải pháp này có thêm lợi ích là cập nhật

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
35 thành const. Vì biến này không bao giờ thay đổi nên từ khóa const chính xác hơn từ khóa let của nó [cho phép gán lại giá trị]

Giống như ví dụ về bộ lọc, quá trình cộng hai số có thể được khai báo nhiều hơn. Đây là một ví dụ

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
3


Bức tranh lớn

Hãy xem xét cả ba hoạt động này được thực hiện một cách bắt buộc

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
4

 

Và một lần nữa, với bộ tái cấu trúc khai báo

 

const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map[[number] => number * 2];
5

 

Các bước bắt buộc yêu cầu 15 dòng mã [không bao gồm ngắt dòng]. Giải pháp khai báo? .  

 

Cách tiếp cận bắt buộc kéo dài và thiết lập thủ công một số vòng lặp gần như giống hệt nhau. Ngoài độ dài của nó, bạn vẫn phải đọc từng dòng để hiểu các vòng lặp đang làm gì. Bạn gặp khó khăn khi giữ tất cả các vòng lặp và biến này trong đầu?

 

Bộ tái cấu trúc khai báo hoàn thành các tác vụ tương tự với lượng mã ít hơn một nửa. Mỗi hoạt động được triển khai bằng hàm mảng tích hợp và các chức năng mà chúng triển khai được đặt tên rõ ràng, có thể tái sử dụng và có thể kiểm tra độc lập

Một ví dụ về lập trình khai báo là gì?

Nhiều ngôn ngữ thuộc nhóm lập trình khai báo, nhưng một số ngôn ngữ được sử dụng rộng rãi nhất bao gồm HTML, SQL, CSS và XML . Các ví dụ khác bao gồm sự kết hợp giữa các ngôn ngữ lập trình chức năng và logic, chẳng hạn như Prolog, Haskell, Miranda, XQuery và Lisp.

Lập trình khai báo và mệnh lệnh trong JavaScript là gì?

Cách dễ nhất để giải thích sự khác biệt giữa mã khai báo và mã mệnh lệnh là mã mệnh lệnh tập trung vào việc viết một chuỗi lệnh rõ ràng để mô tả cách bạn muốn máy tính thực hiện mọi việc . .

Lập trình khai báo là gì?

Lập trình khai báo là một phương pháp trừu tượng hóa luồng điều khiển đối với logic cần thiết để phần mềm thực hiện một hành động và thay vào đó liên quan đến việc nêu nhiệm vụ hoặc kết quả mong muốn là gì. Declarative programming is a high-level programming concept, which is the opposite of imperative programming.

TypeScript là bắt buộc hay khai báo?

Hàm Bản mô tả sau đây thuộc Kiểu mệnh lệnh . Nó nhận một chuỗi tham số truy vấn và xuất ra một mảng các cặp giá trị khóa tham số. Chức năng có một vài vấn đề. Quá nhiều Trường tạm thời ảnh hưởng đến khả năng đọc và gây khó khăn cho việc cấu trúc lại.

Chủ Đề