JavaScript (3) - Lập trình JS căn bản (2)

 

1.1       Lập trình JS căn bản (2)

1.1.1       Phạm vi

Ở phần trước, bạn đã biết cách khai báo một biến bằng từ khóa const, hoặc let. Bạn cũng biết là chương trình JavaScript được tạo thành từ các lệnh và các khối lệnh (block code). Vậy nếu một biến được khai báo ở trong khối lệnh thì khi ra ngoài khối lệnh nó có tồn tại không? Hoặc một biến khai báo ở bên ngoài thì trong khối lệnh bạn có dùng được nó không? Hoặc bên ngoài khối lệnh đã khai báo biến, bên trong khối lệnh cũng khai báo một biến trùng tên, thì chuyện gì xảy ra? Phần này sẽ tìm hiểu để trả lời một số câu hỏi như vậy.

Phạm vi (scope) trong ngôn ngữ lập trình là một khái niệm dùng để xác định một vùng của chương trình máy tính, mà trong đó, biến có tồn tại và có thể tham chiếu tới nó để thực hiện các thao tác.

Trong JavaScript, phạm vi của biến được xác định dựa trên mã nguồn (lexical scope).

Từ JavaScript phiên bản ES6 trở đi, một vùng mã, hay khối lệnh (code block) được xác định bằng các cặp dấu ngoặc nhọn ({}).

JavaScript có hai loại phạm vi là: toàn cục (global scope) và cục bộ (local scope).

Phạm vi toàn cục

Biến được khai báo bên ngoài khối lệnh sẽ có phạm vi toàn cục. Ngoài ra, nếu khai báo biến ở bất cứ đâu, nếu không dùng từ khóa const và let thì nó cũng sẽ có phạm vi toàn cục.

Với biến toàn cục, bạn có thể sử dụng, truy cập tới biến này ở mọi nơi trong chương trình.

Mới nghe qua, sẽ thấy ý tưởng biến toàn cục này có vẻ hay. Tuy nhiên, trong thực tế nó không không phải như vậy. Các lập trình viên kinh nghiệm thường hạn chế sử dụng các biến toàn cục, lý do là nó dễ gây ra tình trạng khó kiểm soát tên biến, và có nguy cơ bị ghi đè giá trị.

Phạm vi cục bộ

Các biến được khai báo ở trong khối lệnh, bằng từ khóa const và let sẽ có phạm vi cục bộ trong chính khối lệnh đó. Nghĩa là, biến sẽ được sử dụng ở bên trong khối lệnh, và không thể truy cập nó ở bên ngoài khối lệnh.

Một số ví dụ minh họa về phạm vi của biến

– Khi bạn khai báo một biến toàn cục, thì bạn có thể sử dụng nó ở mọi nơi

    const a = 5;

    {

        console.log(a);// 5

    }

    console.log(a); // 5

– Nếu bạn khai báo một biến là cục bộ thì bạn không thể sử dụng nó ở bên ngoài khối lệnh

    {

        const a = 5;

        console.log(a);// 5

    }

    console.log(a); // error

– Nếu bạn đã định nghĩa một biến toàn cục và một biến cục bộ trùng tên, thì sẽ tồn tại 2 biến khác nhau (mặc dù trùng tên)

    const a = 6;

    {

        const a = 5;

        console.log(a); // 5

    }

    console.log(a); // 6

– Khi khai báo một biến mà không dùng từ khóa const hoặc let, biến đó sẽ là toàn cục, cho dù bạn khai báo ở trong hay ngoài khối lệnh

    c = 7;

    {

        console.log(c); // 7

        d = 8;

    }

    console.log(d); // 8

1.1.2       Kiểu dữ liệu string

Ở phần trước, bạn đã biết trong JavaScript có các kiểu dữ liệu căn bản (string, symbol, number, boolean, undefined, null) và kiểu object. Phần này sẽ tìm hiểu chi tiết về kiểu dữ liệu string.

String (chuỗi) là một dãy các kí tự. Người ta sử dụng kiểu dữ liệu string để lưu trữ các dữ liệu dạng văn bản. Xem hình ví dụ (nguồn wikipedia).


Để tạo ra dữ liệu kiểu string, bạn chỉ cần bao một chuỗi bằng dấu nháy đơn (') hoặc dấu nháy kép ("). Trong JavaScript, người ta gọi chuỗi này là string literal (chuỗi thuần). Ví dụ:

    const str1 = "Chao bac Teo";

    console.log(str1);

    const str2 = 'Chao cu Ti';

    console.log(str2);

Nếu trong chuỗi có chứa dấu nháy đơn, hoặc nháy kép thì khi tạo chuỗi bạn cần đảo dấu nháy ở bên ngoài, ví dụ:

    const str1 = "Chao bac's Teo";

    console.log(str1);

    const str2 = 'Chao "cu" Ti';

    console.log(str2);

    const str3 = 'chao bac's Teo'; // lỗi

Bạn cũng có thể sử dụng dấu xuyệt ngược (backslash) để xuất các dấu nháy đơn và nháy kép ở trong một chuỗi. Ví dụ:

    const str1 = 'Chao bac\'s Teo';

Bạn cũng có thể tạo ra một chuỗi bằng cách tạo ra một đối tượng kiểu String, tuy nhiên cách này ít dùng vì phải gõ phím nhiều. Ví dụ:

    const str4 = new String('Chao bac Teo');

    // String {'Chao bac Teo'}

Khi bạn tạo ra một biến kiểu string, JavaScript sẽ dùng lớp String để bọc lại biến, vì vậy bạn có thể xử lý biến như một đối tượng. Nghĩa là bạn có thể gọi các thuộc tính và phương thức đi kèm với đối tượng String. Sử dụng dấu chấm (.) để truy cập tới các thuộc tính và phương thức.

Chúng ta sẽ cùng tìm hiểu một số thuộc tính và phương thức.

Để biết chiều dài của chuỗi (chuỗi đang chứa bao nhiêu kí tự), sử dụng thuộc tính length.

    const str = 'hello';

    console.log(str.length);// 5

Cũng có thể sử dụng dấu ngoặc vuông ([]) để truy cập tới thuộc tính.

    console.log(str['length']);

Với kiểu dữ liệu căn bản, JavaScript không cho phép bạn thay đổi giá trị trong các thuộc tính. Ví dụ, giá trị thuộc tính length của chuỗi str đang là 5, bạn sẽ không thể thay đổi được giá trị này.

    const str = 'hello';

    console.log(str['length']);// 5

    str.length = 7; // thay đổi giá trị của thuộc tính

    console.log(str.length) // 5

Để chuyển chuỗi sang dạng chữ hoa, sử dụng phương thức toUpperCase(). Để ý sẽ thấy, khi gọi phương thức sẽ khác với khi tham chiếu tới thuộc tính; phương thức luôn có dấu ngoặc đơn ().

    console.log(str.toUpperCase()); // HELLO

Chuyển chuỗi sang dạng chữ thường, dùng phương thức toLowerCase().

    const str = 'Hello';

    console.log(str.toLowerCase()); // hello

Dùng phương thức charAt() để xem kí tự tại một ví trí trong chuỗi là gì? Lưu ý: vị trí trong chuỗi được đánh số từ 0.

    console.log(str.charAt(1));// e

Nếu muốn biết một kí tự hoặc một chuỗi con có trong chuỗi không, sử dụng phương thức indexOf(). Nếu có: trả về vị trí bắt đầu, nếu không: trả về giá trị -1.

    console.log(str.indexOf('o')); // 4

    console.log(str.indexOf('z')); // -1

Nếu muốn trả về vị trí của kí tự hoặc chuỗi con xuất hiện sau cùng (nếu có), sử dụng phương thức lastIndexOf().

    const str = 'Hello every one';

    console.log(str.lastIndexOf('e')); // 14

Để kiểm tra một chuỗi có chứa một kí tự bất kì, sử dụng phương thức includes().

    const str = 'hello';

    console.log(str.includes('e')); // true

    console.log(str.includes('z')); // false

Để kiểm tra một chuỗi có bắt đầu bằng một kí tự cụ thể nào đó, sử dụng phương thức startsWith(). Phương thức này có phân biệt chữ hoa, chữ thường (case-sensitive).

    const str = 'hello';

    console.log(str.startsWith('h')); // true

    console.log(str.startsWith('H')); // false

Để kiểm tra một chuỗi có kết thúc bằng một kí tự cụ thể nào đó, sử dụng phương thức endsWith(). Phương thức này có phân biệt chữ hoa, chữ thường (case-sensitive).

    const str = 'hello';

    console.log(str.endsWith('o')); // true

    console.log(str.endsWith('H')); // false

Để nối hai chuỗi, sử dụng phương thức concat() (viết tắt của concatenate). Hoặc đơn giản hơn là dùng toán tử cộng (+).

    const str = 'hello';

    console.log(str.concat(' bac Teo')); // hello bac Teo

    // đơn giản hơn

    console.log(str + ' bac Teo');

Nếu bạn muốn xóa các khoảng trắng ở đầu và cuối chuỗi, sử dụng phương thức trim().

    const str = '   nguyen van teo   ';

    console.log(str); // '   nguyen van teo   '

    console.log(str.trim()); // 'nguyen van teo'

Nếu bạn muốn lặp lại một chuỗi nhiều lần, sử dụng phương thức repeat().

    const str = 'hi';

    console.log(str.repeat(3)); // hihihi

Để trích một chuỗi con từ chuỗi gốc, sử dụng phương thức slice(viTriBatDau, viTriKetThuc). Phương thức slice sẽ lấy kí tự từ chỉ mục viTriBatDau tới kí tự tại (viTriKetThuc – 1).

    const str = 'Nguyen Thi Van Teo';

    console.log(str.slice(0, 6)); // Nguyen

Để tách một chuỗi thành nhiều chuỗi con, sử dụng phương thức split(kiTuTach).

    const str = 'teonv@gmail.com';

    const result = str.split('@');

    console.log(result[0]); // teovn

    console.log(result[1]); // gmail.com

1.1.3       Mẫu xuất chuỗi

Trong tiếng Anh, ba từ này là tương đương: template strings, template literals và string templates tạm gọi là mẫu dùng để xuất chuỗi.

Thông thường, bạn hay sử dụng dấu cộng (+) để nối chuỗi với giá trị của biến, ví dụ:

    const ho = 'Nguyen', ten = 'Teo';

    console.log('Ho ten la: ' + ho + ' ' + ten);

Ngoài cách trên, bạn có thể sử dụng mẫu (template) để xuất chuỗi cùng với giá trị của biến, sử dụng cú pháp ${}.

Ví dụ:

    const ho = 'Nguyen', ten = 'Teo';

    console.log(`Ho ten la: ${ ho } ${ ten }`);

Để ý ở đoạn mã trên, đừng nhầm dấu nháy đơn (‘’) với dấu (``).

Khi hiển thị template, các khoảng trắng và dấu xuống dòng vẫn được duy trì so với mã nguồn, vì vậy rất tiện cho việc thiết kế các mẫu dữ liệu xuất ra màn hình, như một email hoặc một đoạn mã nguồn.

Ví dụ:

          const ten = 'Teo';

          const qty = 4;

          const email = `

          Xin chao ban ${ ten },

 

          Chung toi ra vui khi nhan duoc ${ qty } don hang tu ban.

          

          Cam on ban.`;

          console.log(email);

Hoặc bạn có thể sử dụng template để xuất trực tiếp trên trang HTML như ví dụ sau:

          const article = {

               title: 'Xuat template',

               body: 'Su dung template de xuat truc tiep len trang web'

          };

          document.body.innerHTML = `

          <section>

               <header>

                    <h1>Hoc React</h1>

               </header>

               <article>

                    <h2>${article.title}</h2>

                    ${article.body}

               </article>

               <footer>

                    <p>copyright ${new Date().getFullYear()} | Hoc React</p>

               </footer>

          </section>

          `;

1.1.4       Xem và đọc thêm

– Darren Jones, JavaScript Novice To Ninja, second edition, SitePoint, 2017,  p31 > p59

– Alex Banks, Eve Porcello, Learning React – Mordern Patterns for Developing React Apps, O’Reilly Media, 2020, p7 – p11

1.1.5       Bài tập và thực hành

Bài tập 1. Viết và chạy các đoạn mã trong phần lý thuyết.

Bài tập 2. Cho một chuỗi là họ tên của người dùng, hãy viết đoạn mã để tách thành họ, tên lót và tên.

Ví dụ:

– Họ tên: Nguyen Van Teo

– Kết quả: ho = 'Nguyen'; tenLot = 'Van' ; ten = 'Teo'.

Bài tập 3. Write a JavaScript function to hide email addresses to protect from unauthorized user.

Input: "robin_singh@example.com"

Output: "robin...@example.com"

[Gợi ý]

Bài tập 2.

    const str = '     Nguyen Thi Van Teo     ';

 

    // bỏ khoảng trắng dư ở đầu và đuôi

    const temp = str.trim();

    // tìm khoảng trắng đầu tiên

    const firstSpace = temp.indexOf(' ');

    // tim khoảng trắng sau cùng

    const lastSpace = temp.lastIndexOf(' ');

 

    const ho = temp.slice(0, firstSpace);

    const tenLot = temp.slice(firstSpace + 1, lastSpace);

    const ten = temp.slice(lastSpace + 1, temp.length + 1);

    console.log(ho, tenLot, ten);

Bạn có thể viết thêm các đoạn mã kiểm tra cho trường hợp:

– Họ tên không hợp lệ, ví dụ: chuỗi rỗng, chỉ có một chữ

– Có nhiều khoảng trắng giữa các chữ, ví dụ: '      Nguyen          Van         Teo      '

Bài tập 3.

    const email = 'teonv@gmail.com';

    let avg = 0, splitted = '', part1 = '', part2 = '';

    splitted = email.split("@");

    part1 = splitted[0];

    avg = part1.length / 2;

    part1 = part1.slice(0, (part1.length - avg));

    part2 = splitted[1];

    console.log(part1 + "...@" + part2);

1.1.6       Câu hỏi ôn tập

Câu 1. Đoạn mã này xuất gì ra màn hình:  const a = 6; { const a = 5; console.log(a); }

A. 6

B. 5

C. Error

D. null

Câu 2. Đoạn mã này xuất gì ra màn hình:  const a = 6; { const a = 5; } console.log(a);

A. Error

B. undefined

C. 5

D. 6

Câu 3. Đoạn mã này xuất gì ra màn hình? const str = 'Nguyen Van Teo'; console.log(str.slice(3, 6));  

A. Nguyen

B. Van

C. Teo

D. yen

Câu 4. Đoạn mã này xuất gì ra màn hình? const str = 'teonv@gmail.com'; const result = str.split('@'); console.log(result[0]);

A. t

B. teonv

C. null

D. @

Đáp án: 1 (B), 2 (D), 3 (D), 4 (B)

-----

Cập nhật: 9/10/2022