Học làm web (62) - JS căn bản (4)

Tiếp theo của: Học làm web (61) - JS căn bản (3)
----

2.2.11       Các hằng tạo sẵn


null

Null là một hằng, được sử dụng để gán một cách có chủ đích cho một biến, ý báo rằng biến này chưa có giá trị. Null là một giá trị nguyên thủy (primitive value). Null không là thuộc tính của đối tượng toàn cục (global object).

Giá trị nguyên thủy[1] là dữ liệu không ở dạng đối tượng (object) và không có phương thức (method). Trong JavaScript có sáu loại giá trị (hay dữ liệu) nguyên thủy là: string, number, boolean, null, undefined và symbol.

Null có giá trị giống với undefined, nhưng null không đồng nhất với undefined. Lý do là: kiểu dữ liệu của null là object, tuy nhiên kiểu dữ liệu của undefined là undefined.

Nhập các lệnh sau vào cửa sổ Console để quan sát,

null == undefined //true

nul === undefined //false

// kiểm tra kiểu dữ liệu

typeof null //object

typeof undefined //undefined

Để kiểm tra giá trị của một biến có thực sự là null hay không, cần sử dụng phép so sánh đồng nhất (===), ví dụ:

var a = null;

a === null; // true

NaN

NaN (Not a Number) là một hằng, khi một hàm toán học hay một thao tác trong JavaScript mà không thể trả về một số cụ thể, thì nó sẽ trả về giá trị là NaN.

NaN là một thuộc tính của đối tượng toàn cục. Ví dụ, có thể tham chiếu tới thuộc tính NaN bằng các đối tượng toàn cục,

Number.NaN; // NaN

window.NaN; // NaN

Hoặc,

window.hasOwnProperty('NaN'); // true

Tuy nhiên, rắc rối lại ở chỗ, kiểu dữ liệu của NaN lại là number. Có thể kiểm tra bằng lệnh typeof,

typeof NaN; // number

Để kiểm tra một giá trị có phải là NaN hay không? không nên sử dụng phép toán so sánh ==, hoặc ===, mà phải sử dụng hàm isNaN().

Ví dụ,

NaN == NaN; // false

NaN === NaN; // false

Các hàm và thao tác trả về NaN

Các phép toán thực hiện trên dữ liệu không phải kiểu số sẽ trả về NaN. Ví dụ,

‘b’ * 3; // NaN

‘abc’ – ‘a’; // NaN

[1, 2, 3] * 2; // NaN

Phép chia 0/0,

0/0; // NaN

Tuy nhiên, phép nhân giữa hai mảng gồm một phần tử sẽ là hợp lệ,

[2] * [3]; // 6

Phép cộng giữa hai chuỗi sẽ là thao tác nối chuỗi (concatenate),

‘ab’ + ‘c’; // ‘abc’

Với các hàm toán học, nếu truyền đối số cho nó không phải kiểu số, thì hàm sẽ trả về NaN. Ví dụ,

Math.floor(‘a’); // NaN

Truyền giá trị âm cho hàm căn bậc hai sẽ trả về NaN, ví dụ,

Math.sqrt(-1); // NaN

Sử dụng isNaN()

isNaN() là một hàm toàn cục, nên có thể gọi nó từ các đối tượng. Ví dụ,

window.isNaN();

Cách hoạt động của hàm window.isNaN(): đầu tiên hàm window.isNaN() sẽ kiểm tra xem đối tượng cần kiểm tra có phải là một giá trị số hay không? nếu đúng trả về giá trị false, nếu không nó sẽ chuyển đổi đối tượng cần kiểm tra sang dạng số và kiểm tra trên kết quả vừa chuyển đổi. Vì cách làm việc này, nên đôi khi hàm window.isNaN() cũng gây khó hiểu.

Quan sát một số ví dụ sau để hiểu rõ hơn về cách sử dụng hàm window.isNaN(),

isNaN(NaN);
// true, hiển nhiên, vì NaN nghĩa là không phải số
isNaN(1);
// false: vì 1 là một số
isNaN(-2e-4);
// false: vì -2e-4 là một số, có giá trị là -0.0002 (đừng nhầm dấu ‘–’ thứ hai là dấu trừ)
isNaN(Infinity);
// false: vì Infinity là một số
isNaN(true);
// false: vì true được chuyển đổi thành 1, là một số
isNaN(false);
// false: vì false được chuyển đổi thành 0, là một số
isNaN(null);
// false: vì null được chuyển đổi thành 0, là một số
isNaN("" );
// false: vì "" được chuyển đổi thành 0, là một số
isNaN(" " );
// false: vì " " được chuyển đổi thành 0, là một số
isNaN("45.3");
// false: vì "45.3" biểu diễn một số, có giá trị là 45.3
isNaN("1.2e3");
// false: vì "1.2e3" biểu diễn một số, có giá trị là 1.2e3
isNaN("Infinity");
// false: vì chuỗi "Infinity" sẽ được chuyển đổi thành Infinity
isNaN(new Date);
// false: vì đối tượng Date sẽ được chuyển đổi sang giá trị giây
isNaN("10$"); 
// true: vì chuyển đổi không thành công, dấu $ không phải là kí số 
isNaN("hello");
// true: hello là chuỗi
isNaN("undefined");
// true: undefined được chuyển thành NaN
isNaN();
// true: (ngầm hiểu là undefined) được chuyển thành NaN
isNaN(function(){});
// true: việc chuyển đổi không thành công
isNaN({});
// true: việc chuyển đổi không thành công
isNaN([1, 2]);
// true: không thể chuyển đổi thành số

Trường hợp isNaN([1, 2]) khá đặc biệt. Như đã biết isNaN([]) và isNaN([34]) đều trả về giá trị false, nhưng isNaN([true]) và isNaN([1, 2]) lại trả về giá trị true. Lý do nằm ở chỗ chuyển đổi sang dạng số trước khi kiểm tra. Cụ thể: [] được chuyển đổi thành “ ”, [34] > “34”, [true] > “true”, [1, 2] > “1, 2”. Nói chung, với hàm isNaN, một mảng sẽ được xem là NaN, trừ khi mảng chỉ gồm một phần tử, và phần tử này có thể chuyển đổi được sang dạng số.

Hàm Number.isNaN()

Từ phiên bản ECMAScript 6 trở đi, hàm Number.isNaN() được sử dụng để khắc phục vấn đề bắt buộc chuyển đổi tham số sang dạng chuỗi của hàm window.isNaN(). Hàm Number.isNaN() không chuyển đổi tham số sang dạng chuỗi trước khi kiểm tra. Kết quả là chỉ có các giá trị kiểu số và là NaN thì hàm Number.isNaN() mới trả về giá trị true, các trường hợp còn lại trả về false.

Cách làm việc của hàm Number.isNaN(), với đối số là number,

– Nếu Type(number) không là Number, trả về giá trị false

– Nếu number là NaN, trả về giá trị true

– Các trường hợp khác trả về false

Một số ví dụ,

Number.isNaN(NaN);
// true
// Numbers
Number.isNaN(1);
Number.isNaN(-2e-4);
Number.isNaN(Infinity);
// false
// giá trị không thuộc kiểu số
Number.isNaN(true);
Number.isNaN(false);
Number.isNaN(null);
Number.isNaN("" );
Number.isNaN(" " );
Number.isNaN("45.3");
Number.isNaN("1.2e3");
Number.isNaN("Infinity");
Number.isNaN(new Date);
Number.isNaN("10$"); 
Number.isNaN("hello");
Number.isNaN("undefined");
Number.isNaN();
Number.isNaN(function(){});
Number.isNaN({});
Number.isNaN([]);
Number.isNaN([1]);
Number.isNaN([1,2]);
Number.isNaN([true]);
// false

undefined và null

Undefined là một giá trị toàn cục, cho biết tình trạng (biến) chưa được gán dữ liệu.

Null là một đối tượng, được sử dụng để báo rằng, biến được thiết lập ở chế độ không có dữ liệu một cách có chủ đích, một cách tường minh.

– typeof null === ‘object’

– typeof undefined === ‘undefined’

Khi thiết lập một biến là undefined có nghĩa là biến này không còn hiệu lực. Một số xử lý (ví dụ JSON serialization) sẽ gỡ bỏ các thuộc tính có giá trị là undefined ra khỏi đối tượng. Ngược lại, thuộc tính với giá trị null, có nghĩa là thuộc tính này vẫn có hiệu lực và nó mang giá trị rỗng (empty).

Ví dụ một số thao tác dẫn tới giá trị undefined:

– Khai báo biến nhưng không gán giá trị

let foo;
console.log('is undefined?', foo === undefined);
// is undefined? true

– Truy cập tới giá trị của thuộc tính không tồn tại

let foo = {a: 'a'};
console.log('is undefined?', foo.b===undefined);
// is undefined? true

– Giá trị trả về của một hàm, mà hàm này không trả về giá trị

function foo() { return; }
console.log('is undefined?', foo() === undefined);
// is undefined? true

– Đối số của một hàm: có khai báo khi định nghĩa, nhưng khi gọi hàm thì không truyền giá trị

function foo(param) {
            console.log('is undefined?', param === undefined);
}
foo('a');
foo();
// is undefined? false
// is undefined? true

Lưu ý: undefined cũng là thuộc tính của đối tượng toàn cục window

console.log(window.undefined);
window.hasOwnProperty('undefined');
// undefined
// true

Infinity và –Infinity

Infinity (dương vô cùng) là thuộc tính của đối tượng toàn cục (global object), nó đại diện cho giá trị dương vô cùng của toán học. Trong JavaScript, cũng có thể tham chiếu tới giá trị dương vô cùng bằng thuộc tính INFINITY của đối tượng Number, cụ thể: Number.INFINITY.

Infinity có giá trị lớn hơn mọi giá trị khác. Ví dụ, lấy một số dương bất kì chia cho 0 thì sẽ được Infinity, hoặc một biểu thức toán học cho ra kết quả rất lớn, đến mức tràn số (overflow) thì cũng tạo ra một Infinity.

Ngoài Infinity, trong JavaScript còn có –Infinity. Đây là âm vô cùng, là số nhỏ hơn mọi giá trị khác. Để có –Infinity, có thể đổi dấu của Infinity hoặc tham chiều tới thuộc tính NEGATIVE_INFINITY của đối tượng Number, cụ thể: Number.NEGATIVE_INFINITY.

Ví dụ, nhập các lệnh sau vào cửa sổ Console của trình duyệt,

-(Infinity); // -Infinity

Number.NEGATIVE_INFINITY; // -Infinity

Một số ví dụ khác,

Infinity > 123192310293; // true

-Infinity < -123192310293; // true

1 / 0; // Infinity

Math.pow(123123123, 9123192391023); // Infinity

Number.MAX_VALUE * 2; // Infinity

23 / Infinity; // 0

-Infinity; // -Infinity

-Infinity === Number.NEGATIVE_INFINITY; // true

-0; // -0 , trong JavaScript có số -0

0 === -0; // true

1 / -0; // -Infinity

1 / 0 === 1 / -0; // false

Infinity + Infinity; // Infinity

var a = 0, b = -0;

a === b; // true

1 / a === 1 / b; // false

Một số hằng của đối tượng Number

Number.MAX_VALUE; // 1.7976931348623157e+308

Number.MAX_SAFE_INTEGER; // 9007199254740991

Number.MIN_VALUE; // 5e-324

Number.MIN_SAFE_INTEGER; // -9007199254740991

Number.EPSILON; // 0.0000000000000002220446049250313

Number.POSITIVE_INFINITY; // Infinity

Number.NEGATIVE_INFINITY; // -Infinity

Number.NaN; // NaN


Lưu ý: một số phép toán trong JavaScript sẽ bị ngưng thực thi, nếu giá trị tính toán vượt ra ngoài vùng giá trị an toàn (Number.MIN_SAFE_INTEGER , Number.MAX_SAFE_INTEGER).


[1] https://developer.mozilla.org/en-US/docs/Glossary/Primitive
-----------
Cập nhật [11/9/2018]
-----------
Xem thêm: Tổng hợp các bài viết về Học làm web
Xem thêm: Học làm web (63) - JS căn bản (5)