Up and Going – Hiểu về lập trình (Phần 1)
August 8, 2018Code
Một chương trình, thường được gọi là source code hoặc code, là một tập hợp các hướng dẫn để yêu cầu máy tính cần xử lý một nhiệm vụ nào đó. Thông thường, code được lưu dưới dạng file văn bản, với js bạn có thể gõ code trực tiếp lên console của trình duyệt.
Các nguyên tắc của một định dạng hợp lệ cùng sự kết hợp của các hướng dẫn được gọi là ngôn ngữ máy tính, hay còn gọi là cú pháp, tương tự như ngôn ngữ giao tiếp chỉ cho bạn cách đọc từ và các tạo ra câu đúng bằng cách sử dụng từ và dấu câu.
Các câu lệnh (Statements)
Trong ngôn ngữ máy tính, một nhóm từ, số, cách thức thực thi từng nhiệm vụ cụ thể được gọi là câu lệnh. Trong JS, câu lệnh có thể như sau:
a = b * 2;
Ký tự a và b là các biến (variable), giống như những cái hộp, bạn có thể lưu trữ đồ vật trong đó. Trong lập trình, biến giữ giá trị (ví dụ số 42) được chương trình sử dụng.
Về mặt tương phản, số 2 bản thân nó chỉ là một giá trị, được gọi là giá trị ký tự (literal value), vì nó độc lập và không lưu trữ trong một biến nào cả.
Dấu = và * là toán tử (operators) (xem “Toán tử”) — nó thực thi các hành động với giá trị và biến như sự phân công và phép toán nhân.
Hầu hết câu lệnh trong JS kết thúc bằng dấu chấm phẩy (;) ở cuối câu.
Lệnh a = b * 2; báo cho máy tính giá trị được lưu trữ trong biến b, nhân giá trị đó với 2, sau đó lưu kết quả lại vào một biến khác gọi là a.
Lập trình tương tự như bộ sưu tập của nhiều câu lệnh cùng nhau mô tả tất cả các bước để thực thi mục đích lập trình.
Biểu thức (Expressions)
Các câu lệnh được tạo thành từ một hay nhiều biểu thức. Một biểu thức là bất kỳ tham chiếu trên một biến hoặc một giá trị, hoặc tập hợp các giá trị và các biến kết hợp thành toán tử.
Ví dụ:
a = b * 2;
Câu lệnh này có 4 biểu thức bên trong nó:
● 2 là giá trị biểu thức trực kiện.
● b là giá trị biểu thức, có nghĩa là sẽ lấy giá trị hiện tại của nó
● b * 2 là biểu thức toán học, nghĩa là sẽ làm phép nhân
● a = b * 2 là một biểu thức gán, nghĩa là sẽ gán kết quả của biểu thức b * 2 cho biến a (còn tìm hiểu thêm sau)
Một biểu thức chung đứng một mình còn được gọi là lệnh biểu thức(expression statement), như ví dụ sau:
b * 2;
Kiểu biểu thức này thường không hữu dụng, bởi nó chẳng có tác dụng nào đối với chương trình đang chạy—nó sẽ lấy giá trị của b và nhân nó với 2, nhưng sau đó không làm gì với kết quả đó.
Một loại câu lệnh biểu thức nữa là biểu thức lệnh gọi (call expression) (Xem “Functions”), khi toàn câu lệnh là một hàm tự gọi biểu thức:
alert( a );
Thực thi chương trình
Làm cách nào mà tập hợp các câu lệnh lập trình có thể yêu cầu máy tính phải làm gì? Chương trình cần được thực thi, hay còn được biết đến với tên chạy chương trình.
Các lệnh giống như a = b * 2 rất hữu dụng cho lập trình viên đọc và viết, nhưng nó không hoàn toàn ở dạng để máy tính hiểu trực tiếp. Vì vậy, một trình tiện ích đặc biệt trong máy tính (hoặc là thông dịch-interpreter hoặc là biên dịch-compiler) được sử dụng để dịch code bạn viết thành các lệnh mà máy tính có thể hiểu.
Đối với một số ngôn ngữ máy tính, mỗi khi chương trình chạy thì bản dịch của các câu lệnh thường được hoàn thành từ trên xuống dưới, từng dòng một, nó thường được gọi là thông dịch mã.
Một số ngôn ngữ khác, bản dịch được hoàn thiện trước, gọi là biên dịch mã, rồi sau đó chương trình mới chạy, những gì đang chạy đã được biên dịch xong để cho máy sẵn sàng chạy.
JavaScript thường được khẳng định nó là ngôn ngữ được thông dịch, bởi vì mã nguồn JavaScript được xử lý mỗi lần chạy. Nhưng điều đó không hoàn toàn chính xác, thực ra là
JavaScript engine biên dịch chương trình và sau đó chạy ngay mã đã được biên dịch.
Các biểu thức
Toán tử là những gì chúng ta thực thi hành động trên các biến và các giá trị. Chúng ta đã thấy hai kiểu toán tử của JavaScript ở ví dụ trên là = và *
Toán tử * để thực hiện phép toán nhân. Dễ heng. Dấu = được sử dụng để gán — đầu tiên là ta tính toán giá trị ở phía bên phải(giá trị nguồn) dấu = và sau nó đặt nó vào biến(variable) mà chúng ta xác định ở phía bên trái (variable mục tiêu).
Chú ý: Có thể cảm giác hơi bị ngược bằng cách đảo trình tự gán. Thay vì a = 42, một số người thích lật ngược trình tự giá trị nguồn ở bên trái và biến mục tiêu ở bên phải, kiểu như 42 -> a (nó không phải JavaScript!). Không may,a = 42là định dạng được sắp xếp, và tương tự các biến, nó khá phổ biến trong các ngôn ngữ lập trình hiện đại. Nếu có cảm giác không tự nhiên, hãy bỏ chút thời gian để làm quen và tâm trí bạn sẽ tự sắp xếp nó.
Hãy xem:
a = 2;
b = a + 1;
Tại đây, chúng ta gán giá trị2 cho biến a. Sau đó chúng ta có giá trị của biến a (vẫn là 2), thêm 1 vào nó sẽ có kết quả giá trị 3, sau đó lưu giá trị đó vào biến b.
Trong khi biểu thức kỹ thuật, bạn cũng cần từ khoá var trong mọi thể loại lập trình, như cách đầu tiên bạn khai báo(khởi tạo) các biến (Xem “Variables”)
Bạn có thể luôn khai báo biến bằng tên trước khi sử dụng nó. Nhưng bạn cũng chỉ khai báo một biến một lần trong mỗi scope (xem “Scope”): nó có thể được sử dụng nhiều lần khi cần. Ví dụ:
var a = 20; a = a + 1; a = a * 2; console.log( a ); // 42
Sau đây là một số biểu thức trong JavaScript:
● Gán: = như a = 2.
● Toán: + (cộng), – (trừ), * (nhân), và / (chia), a * 3.
● Tổ hợp gán: +=, -=, *=, và /= là các biểu thức tổ hợp mà nó kết hợp giữa toán với các giá trị gán, ví dụ như a += 2 (tương tự a = a + 2).
● Tăng/Giảm: ++ (tăng), — (giảm), như a++ (tương tự a = a + 1).
● Tiếp cận object: . như console.log(). Object là các giá trị chứa các giá trị khác tại các vị trí có tên cụ thể gọi là thuộc tính. obj.a nghĩa là một giá trị object gọi obj với một đặc tính có tên a. Các thuộc tính có thể chuyển đổi cách tiếp cận ví dụ obj[“a”]. Xem “Values & Types”.
● Tương đương: == (bằng tương đối), === (bằng tuyệt đối), != (khác tương đối), !== (khác tuyệt đối), ví dụ a == b. Xem “Values & Types”.
● So sánh: < (nhỏ hơn), > (lớn hơn), <= (nhỏ hơn hoặc bằng tương đối), >= (lớn hơn hoặc bằng tương đối), như a <= b. Xem “Values & Types”.
● Tính logic: && (và), || (hoặc), ví dụ a || b chọn luôn a hoặc b.
Các biểu thức này được sử dụng để diễn tả các điều kiện phức tạp (xem “Điều kiện”), ví như cả a hoặc b đều đúng.
Giá trị (Values) & loại (types)
Nếu bạn hỏi nhân viên tại một cửa hàng điện thoại giá của một cái điện thoại gì đó, và họ trả lời “chín chín, chín chín” (ví dụ $99.99), tức họ đã cho bạn một hình dung giá trị tiền mà bạn cần phải trả (bao gồm thuế) để mua nó. Nếu bạn muốn mua 2 cái điện thoại, bạn có thể dễ dàng làm phép toán để gấp đôi giá trị thành $199.98 từ giá gốc.
Nếu người nhân viên đó lấy hai cái điện thoại tương tự và nói “miễn phí”, tức là họ không cho bạn một con số nào, nhưng nó cũng là một dạng đại diện cho mức giá ($0.00)—cho từ “miễn phí”.
Sau đó bạn lại hỏi điện thoại có đồ sạc hay không, câu trả lời có thể là “có” hoặc “không”.
Bằng cách tương tự, khi bạn diễn tả những giá trị trong một chương trình, bạn chọn các kiểu đại diện khác nhau cho các giá trị đó dựa trên những gì bạn kế hoạch với chúng. Những kiểu đại diện khác nhau cho các giá trị được gọi là types trong thuật ngữ lập trình. JavaScript có sẵn các type được gọi là giá trị nguyên thuỷ :
● Khi bạn muốn làm toán, bạn muốn number.
● Khi bạn muốn in giá trị trên màn hình, bạn cần string (một hay nhiều ký tự, từ, câu).
● Khi bạn muốn tạo một quyết định trên chương trình, bạn cần boolean(true hoặc false).
Các giá trị được thêm trực tiếp vào trong source code được gọi là literals. string literals được bao bằng dấu ngoặc kép “…” hoặc dấu ngoặc đơn (‘…’) — chỉ là phong cách khác nhau. number và boolean literals được đại diện như là ví dụ ( 42, true, etc.).
Hãy xem:
"I am a string"; 'I am also a string'; 42; true; false;
Ngoài kiểu giá trị string/number/boolean, các ngôn ngữ lập trình còn thường cung cấp kiểu arrays, objects, functions, và hơn nữa.
Chuyển đổi giữa các kiểu
Nếu bạn có một number nhưng muốn hiển thị trên màn hình, bạn cần chuyển giá trị thành string, và trong JavaScript gọi việc chuyển đổi này là “cưỡng bức”. Tương tự, nếu ai đó cho một loạt ký tự số vào trong form của trang thương mại điện tử, đó là string, nhưng nếu bạn muốn sử dụng giá trị để thực hiện phép toán, bạn cần ép nó thành number
JavaScript cung cấp một vài cơ sở khác nhau để ép buộc chuyển đổi các kiểu. Ví dụ:
var a = "42"; var b = Number( a ); console.log( a ); // "42" console.log( b ); // 42
Sử dụng Number(..) (một function có sẵn) như đã thấy là một sự cưỡng bức minh bạch từ bất kỳ kiểu nào sang number. Nó hơi rõ ràng. Nhưng có một chủ đề gây tranh cãi rằng những gì xảy ra khi bạn muốn so sánh hai giá trị của cùng một kiểu, nó cần một cưỡng bức ngầm.
Khi so sánh chuỗi “99.99” với số 99.99, hầu hết mọi người đồng ý rằng nó bằng nhau. Nhưng nó không chính xác, đúng không? Nó có chung giá trị trong hai kiểu đại diện khác nhau, hai kiểu khác nhau. Bạn có thể nói là “bằng tương đối” , đúng không?
Để giúp bạn thoát khỏi hoàn cảnh như vậy, JavaScript đôi khi đưa vào một sự cưỡng bức giá trị ngầm đến kiểu phù hợp.
Vì vậy nếu bạn sử dụng dấu bằng tương đối == để so sánh “99.99” == 99.99, JavaScript sẽ chuyển phía bên trái “99.99” thành number tương đương 99.99. Sự so sánh trở thành 99.99 == 99.99, nghĩa là đương nhiên true.
Khi được thiết kế để giúp bạn, cưỡng bức ngầm có thể mang đến sự hoang mang nếu bạn không có thời gian để học luật quản lý hành vi của nó. Hầu hết JS dev chưa bao giờ tìm hiểu, vì vậy cảm giác thường tình là sự cưỡng bức ngầm này gây hoang mang và tạo ra bug ngoài ý muốn, vậy nên phải tránh.
Nó đôi khi được gọi là lỗ hổng trong thiết kế ngôn ngữ. Tuy nhiên, cưỡng bức ngầm là một cơ chế có thể học được, và hơn thế nữa là cần được học bởi bất kỳ ai muốn học lập trình
JavaScript một cách nghiêm túc. Nó không chỉ làm bạn hết hoang mang khi bạn học luật này, nó còn làm cho bạn lập trình tốt hơn. Hiệu quả xứng đáng.
— Còn tiếp —