Saturday, 22 April 2017

Học JavaScript - phần 1 - number, boolean, string

(từ Python nhảy sang - kèm so sánh với Python)
JavaScript (JS) - /ˈdʒɑːvəˌskrɪpt/

Why?

- Mình thích thì mình học thôi 😚
- Syntax/Khái niệm 2 ngôn ngữ giống nhau đến 70%, bạn phải bỏ ra rất ít công để thụ được nhiều lợi.
- Dù thích hay không, JavaScript (từ đây ghi là JS) vẫn là ngôn ngữ duy nhất ở phía client khi duyệt web. Ngôn ngữ duy nhất chạy trên browser FireFox, Chrome, IE, Safari ... Đến cả Google, dù đã cố gắng lắm, nhưng vẫn không thể đưa Dart thay thế vị trí của JS

Để làm gì?

- Học JS để có thể viết code ngay trên FireFox/Chrome lúc nào mình muốn, không phải cài đặt, mọi lúc mọi nơi.
- Có thể điều khiển, tương tác với website qua code dễ dàng (bấm vào nút này, nút kia).
- Nếu bạn muốn làm Web Developer, biết JS là một điều bắt buộc.

Loạt bài viết này sẽ

- Lướt qua các khái niệm phổ biến của JS phía client (chung cho cả JS phía client lẫn server (Node.js)
- Học JS để tương tác với HTML DOM. Không học JS để xử lý phía server, khi ta đã có Python rồi, chẳng có lý do TỐT gì để dùng JS cho phía server. Nếu tốc độ là điều quan trọng? hãy dùng Golang. Học 1 syntax dùng cho cả 2 phía là một lý do YẾU. Cái giá phải trả cho việc dùng JS làm backend đủ để ta học 1 ngôn ngữ Backend khác tốt hơn (VD Golang/Erlang). (Đây là ý kiến cá nhân, tranh cãi đầy trên mạng: http://lmgtfy.com/?q=why+not+node+js )

Bài viết sử dụng FireFox 52.

Bắt đầu!

Bật Web console (FireFox) lên để gõ code. (Chrome cũng làm được tương tự).

Web Console trên FireFox

Web Console trên FireFox

Hello World!

Gõ:
console.log("Hello FAMILUG!");
rồi enter để xem kết quả trên Web console, nhớ bật "Logging" để xem log.
Mỗi dòng code NÊN kết thúc bằng dấu ; (đôi khi không có cũng không sao).



Vậy là ta đã thành công, done! 😎
Giờ cùng đá qua một chút lý thuyết để nắm được một số từ khoá, đỡ bị lạc hậu khi nói chuyện về JS! rồi sẽ quay lại code sau.

Lý thuyết về ngôn ngữ

ECMAScript là gì?

Giống như mọi ngôn ngữ lập trình khác, JavaScript được thực hiện tuân theo một bộ mô tả cú pháp. Các bên sẽ lấy bộ mô tả đó và viết nên các "JavaScript engine" (hay JavaScript interpreter) để nhận đầu vào là code JS, và thực hiện chạy code đó. Trên các web browser: có SpiderMonkey chạy trên FireFox, V8 chạy trên Google Chrome, JavaScriptCore chạy trên Safari, Chakra chạy trên IE/Edge... Node.js cũng dùng V8 nhưng chạy code cho phía server. Các Engine này hầu hết được viết bằng C++. Tương tự như Python, cũng là một bộ mô tả, mà khi dùng C để viết ra interpreter, ta có CPython.

Bộ mô tả (specification) JS nói trên, được thống nhất và chuẩn hoá dưới cái tên ECMAScript hay ES (ECMA - European Computer Manufacturers Association).
Phiên bản ES mới nhất là ES6, các trình duyệt phổ biến, tại thời điểm hiện tại, đều hỗ trợ ES5. Điều này nói rằng, ES vẫn tiếp tục phát triển không ngừng, và vì thế, JS cũng vậy.

Các kiểu dữ liệu cơ bản

Như học Python, ta bắt đầu bằng học kiểu số.

Kiểu number

Code sau đây copy trực tiếp từ FireFox web console, theo sau mỗi dòng input là output tương ứng, hãy bỏ qua phần thời gian trước mỗi câu lệnh.
10:16:07.131 1 + 1
10:16:07.135 2

10:16:12.990 1 - 1000000000000
10:16:12.994 -999999999999

10:16:19.632 2 * 131279861872674891263
10:16:19.637 262559723745349800000

10:16:25.376 5/2
10:16:25.381 2.5

10:16:34.984 typeof 2
10:16:34.989 "number"

10:16:39.072 typeof 5/2
10:16:39.077 NaN

10:16:47.247 typeof (5/2)
10:16:47.253 "number"

10:17:24.583 1/0
10:17:24.589 Infinity

10:19:14.372 typeof (1/0)
10:19:14.380 "number"

+ - * / khá giống với Python, điểm khác biệt đáng chú ý:
- Chỉ có 1 kiểu dữ liệu là "number", không phân biệt Integer hay Float.
- 1/0 nhận được kết quả là Infinity, giá trị đó được xem như 1 số, chứ không có Exception xảy ra như Python.

Thử kiểm tra 0.1 + 0.1 + 0.1 == 0.3
10:20:33.395 0.1 + .1 + .1
10:20:33.402 0.30000000000000004

10:27:28.021 .1 + .1 + .1 == .3
10:27:28.034 false
Vậy kiểu "number" của JS tương tự như Float của Python. JS chỉ có một kiểu number duy nhất, nghe có vé giới hạn, nhưng cũng chẳng sao, vì không ai tính toán khoa học hay làm gì cần tính toán nhiều trên JS cả, float là đủ.

Các phép tính cao cấp hơn
10:28:57.787 5 % 2
10:28:57.795 1

10:29:01.075 2 ** 1000
10:29:01.083 1.0715086071862673e+301

10:29:07.707 1e3
10:29:07.719 1000

1e3 là viết tắt của 1 * 10**3
Ta thấy khi tính 2 mũ 1000, kết quả không trả về đầy đủ như kiểu int trong Python mà giống kết quả của kiểu float:
In [6]: 2.0 ** 1000
Out[6]: 1.0715086071862673e+301

In [7]: 2 ** 1000
Out[7]: 10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376

Kết luận: muốn tính toán thì dùng Python, JS chỉ dùng tính toán đơn giản thôi.

Kiểu boolean

10:37:40.400 2 > 4
10:37:40.407 false

10:37:43.297 2 < 4
10:37:43.307 true

10:37:47.569 2 == 2
10:37:47.576 true

10:37:52.072 2 === 2.0
10:37:52.081 true

10:38:18.846 typeof (2<4)
10:38:18.852 "boolean"

10:38:21.598 typeof true
10:38:21.604 "boolean"

10:38:26.047 typeof false
10:38:26.053 "boolean"

10:39:01.253 true || blah
10:39:01.261 true

10:39:07.069 true && blah
10:39:07.081 ReferenceError: blah is not defined [Learn More]

10:39:25.861 false && blah
10:39:25.873 false

10:39:30.557 false || blah
10:39:30.565 ReferenceError: blah is not defined [Learn More]

2 giá trị kiểu boolean của JS là "true" và "false" (chữ t và f viết thường, trong Python phải viết hoa).
Phép and sử dụng (&&) và or (||) đều có tính "short circuit" giống Python:

    false && anything is short-circuit evaluated to false.
    true || anything is short-circuit evaluated to true.

Trong JS, === (strict equal) kiểm tra 2 vế == và cùng kiểu, == giống như == trong Python.

Kiểu string

Sử dụng single quote 'JS' hay double quote "JS" để biểu diễn string.
Single quote và double quote là tương đương nhau, giống trong Python.
10:44:17.113 'JS' === "JS"
10:44:17.120 true
10:44:25.023 typeof "JS"
10:44:25.028 "string"
Trong JS mặc định nó hỗ trợ Unicode (như Python3), sử dụng encoding UTF-16

String trong JS là Unicode


Xử lý string

Tương tự bài viết xử lý string trên Golang
10:47:19.396 "Python".length
10:47:19.402 6
Ok, thử những từ khác:

15:35:44.922 "Hưng".length
15:35:44.935 4
15:35:53.889 "😚".length
15:35:53.900 2 // WTF!!!

Tại sao 1 "ký tự" emoticon lại có length là 2? Lý do lằng nhằng có thể giải thích được, nhưng đó không phải là điều chúng ta mong đợi. Python làm điều này tốt hơn với UTF-8:
In [12]: x = "😙"
In [13]: ord(x)
Out[13]: 128537
In [14]: len(x)
Out[14]: 1 


Lấy độ dài của string bằng cách truy cập property "length".
10:48:29.930 s = "JavaScript"
10:48:29.942 "JavaScript"
10:48:31.698 s[0]
10:48:31.702 "J"
Indexing hoạt động như mọi ngôn ngữ lập trình Python, Java, Golang...
10:48:36.594 s[-1]
10:48:36.599 undefined
Không index âm như Python được 🙄.
10:48:48.482 s[0] = 'P'
10:48:48.492 "P"
10:48:51.065 s
10:48:51.086 "JavaScript"
Không thể thay đổi string. string là immutable - giống Python.

10:50:48.399 'The answer is ' + 42
10:50:48.403 "The answer is 42"
Tự động convert số thành string khi cộng với string. Trong Python, ta sẽ bị TypeError khi làm vậy, hư lắm:
In [8]: 'The answer is ' + 42
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-defa453cb41a> in <module>()
----> 1 'The answer is ' + 42

TypeError: Can't convert 'int' object to str implicitly

Không thể nhân string với số - một phép toán rất tiện lợi trong Python.
10:51:05.998 'Anh xin loi\n' * 5
10:51:06.002 NaN
10:54:35.476 5 + '2'
10:54:35.484 "52"
10:54:47.243 5 + parseInt(2.5)
10:54:47.249 7
10:54:52.810 5 + parseFloat(2.5)
10:54:52.816 7.5

dùng built-in function parseInt/parseFloat để convert từ string thành số.

Template string : sử dụng ``, có thể thay thế các giá trị bằng ${varname}, gần tương tự cách format string trong Python, cách xuống dòng như dùng triple quote trên Python '''
10:56:32.912 thing = "foo"
10:56:32.919 "foo"

10:57:11.428 poem = `Roses are red,
Violets are blue.
Sugar is sweet,
and so is ${thing}`

10:57:11.440 "Roses are red,
Violets are blue.
Sugar is sweet,
and so is foo"
Sử dụng các method của String object để xử lý string:

1. includes - kiểm tra chứa một string hay không
11:07:39.468 "JavaScript".includes("Java")
11:07:39.480 true
11:07:48.555 "JavaScript".includes("java")
11:07:48.560 false

2. split - biến string thành array chứa các string sau khi cắt
11:09:05.763 "Nơi   này có anh".split()
11:09:05.768 Array [ "Nơi   này có anh" ]
11:09:17.434 "Nơi   này có anh".split(" ") # cắt tại dấu space
11:09:17.441 Array [ "Nơi", "", "", "này", "có", "anh" ]
Trong JS, khái niệm Array tương ứng với list của Python.

3. startsWith
11:11:05.290 "JavaScript".startsWith("Java")
11:11:05.297 true
Kiểm tra string bắt đầu bằng một string - tương tự Python.

4. endsWith
11:12:08.677 "taiLieuMat.mp4".endsWith(".mp4")
11:12:08.684 true
Kiểm tra xem string có kết thúc bằng một string không - tương tự Python.

PS: Với Python ta có thể kiểm tra nhiều giá trị trong startswith hay endswith
In [9]: 'taiLieuMat.mp4'.endswith(('.mp4', '.mkv'))
Out[9]: True
5. indexOf, lastIndexOf

11:13:50.116 "JavaScript".indexOf('H')
11:13:50.123 -1 // không tìm thấy sẽ trả về -1
11:14:02.612 "JavaScript".indexOf('a')
11:14:02.618 1
11:14:14.653 "JavaScript".lastIndexOf('a')
11:14:14.668 3
6. Array.join
11:16:56.299 Array.join("Nơi này có anh".split(" "), "-")
11:16:56.311 "Nơi-này-có-anh"
Nối các phần tử của 1 array bằng một ký tự - tương tự Python.

7. trim
11:18:07.673 "   Học Python ở PyMi   ".trim()
11:18:07.688 "Học Python ở PyMi"
Tương tự strip trong Python.

8. concat
Nối 2 string, như +
11:18:52.129 "abc".concat("xyz")
11:18:52.145 "abcxyz"
11:18:58.024 "abc" + "xyz"
11:18:58.033 "abcxyz"
9. replace
11:19:53.390 "JavaScript".replace("Java", "Python")
11:19:53.396 "PythonScript"
Như Python

10. toLowerCase, toUpperCase
11:20:54.428 "PYMI".toLowerCase()
11:20:54.439 "pymi"

11:21:04.963 "familug".toUpperCase()
11:21:04.969 "FAMILUG"
11. repeat
11:21:29.419 "Anh xin lỗi\n".repeat(5)
11:21:29.429 "Anh xin lỗi
Anh xin lỗi
Anh xin lỗi
Anh xin lỗi
Anh xin lỗi
"
Như đem string nhân int trong Python.

12. slice
11:22:57.529 "JavaScript".slice(0,4)
11:22:57.535 "Java"

11:23:27.906 "JavaScript".slice(7) # từ index 7 đến hết
11:23:27.918 "ipt"
Như phép slicing trong Python "JavaScript"[0:4]


Tài liệu ngắn gọn, chính xác, thích hợp cho người đọc đã thành thạo một ngôn ngữ lập trình https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript

Tham khảo


https://developer.mozilla.org/en-US/docs/Web/JavaScript, mặc dù đọc hơi chán, nhưng mà lỡ rồi :p
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Text_formatting
https://en.wikipedia.org/wiki/JavaScript_engine

Hết phần 1.
HVN at http://www.familug.org/ and http://pymi.vn

Đăng ký học #Python 3 từ con số 0 tại https://pymi.vn/ - trung tâm đào tạo lập trình viên Python số 1 Việt Nam.

Nhập email vào http://invite.pymi.vn/ để nhận thư mời tham gia forum hỏi đáp Python, Django, Golang, Linux ...