Sách đang đọc · The principle of OOP in JavaScript

Chương 1 – Kiểu tham trị và tham chiếu trong JavaScript

What are Types?

Mặc dầu JavaScript không có khái niệm class, nó vẫn sử dụng 2 kiểu dữ liệu:
tham trịtham chiếu. Kiểu tham trị được lưu trữ như kiểu dữ liệu cơ bản. Kiểu tham chiếu được lưu trữ như objects, nơi mà nó chỉ tham chiếu đến vị trí trong bộ nhớ.

Trong khi các ngôn ngữ lập trình khác phân biệt tham trị và tham chiếu bởi việc lưu trữ giá trị trên stack và tham chiếu trong bộ nhớ heap, JS thì không như vậy: Nó theo dõi các biến cho một phạm vi cụ thể với một variable object. Kiểu tham trị được lưu trữ trực tiếp trên variable object, trong khi kiểu tham chiếu được đặt như một con trỏ trong variable object, như một tham chiếu đến 1 vị trí trong bộ nhớ nơi object được lưu trữ. Tuy nhiên, bạn sẽ nhìn thấy trong các phần sau của chương này, tham trị và tham chiếu sẽ có những hành vi khác nhau mặc dù chúng có thể khởi tạo theo cùng một cách.

Dĩ nhiên, đây là một sự khác biệt khác giữa kiểu tham trị và tham chiếu.

Kiểu tham trị

Kiểu tham trị được giới thiệu như phần đơn giản của data được lưu trữ như true và 25. Trong JS có 5 kiểu tham trị chính:

  • Boolean: true và false
  • Number: Bất kỳ số nguyên hoặc số thập phân
  • String: Một ký tự hoặc một chuỗi các ký tự được bọc bởi dấu nháy đơn hoặc dấu nháy kép (JS không phân biệt kiểu ký tự)
  • Null: Một kiểu tham trị chỉ có một giá trị Null
  • Undefined: Một kiểu tham trị chỉ có một giá trị undefined (undefined là một giá trị được gán đến một biến mà không được khởi tạo)

 

Ba kiểu giá trị đầu tiên (Boolean, Number và String) có hành vi giống nhau trong khi 2 kiểu còn lại (null và undefined) có một chút khác biệt. Tất cả các kiểu tham trị có giá trị thể hiện.Đây là một vài ví dụ của mỗi kiểu sử dụng với hình thức của chúng:

//strings
var name = "Nicholas";
var selection = "a";

// numbers
var count = 25;
var cost = 1.51;

// Boolean
var found = true;

// null
var object = null;

// undefined
var flag = undefined;
var ref; // asigned undefined automatically

Trong JS, giống như các ngôn ngữ khác, một biến giữ tham trị tực triếp chứa giá trị của chúng ( hơn là một con trỏ đến một object). Khi bạn gán một kiểu tham trị đến một biến, giá trị được sao chép đến biến đó. Điều này có nghĩa rằng nếu bạn set một biến bằng một biến khác, mỗi biến sẽ có bản sao data riêng của chúng. Ví dụ:

var color1 = "red";
var color2 = color1;

Ở đây, color1 được gán đến giá trị “red”. Biến color2 sau đó được gán đến giá trị của color1 là giá trị “red”. Mặc dù color1 và color2 chứa cùng giá trị, chúng vẫn hoàn toàn tách biệt nhau, và bạn có thể thay đổi giá trị trong color1 mà không ảnh hướng đến giá trị của color2 và ngược lại. Đó là bởi vì ở đây có 2 vùng lưu trữ giá trị khác nhau cho mỗi biến. Hình 1-1 mô tả mỗi biến lưu trữ giá trị trong code:

Variable Object
color1 “red”
color2 “red”

Bởi vì mỗi biến chứa một tham trị sử dụng các vùng nhớ riêng biệt, nên thay đổi một biến không ảnh hưởng đến biến khác.
Ví dụ:

var color1 = "red";
var color2 = color1;

console.log(color1); // "red"
console.log(color2); // "red"

color1 = "blue";

console.log(color1); // "blue"
console.log(color2); // "red"

Trong code trên, color1 thay đổi đến “blue”color2 vẫn giữa nguyên giá trị ban đầu “red”

Xác định kiểu tham trị

Cách tốt nhất để xác định một biến có phải là một kiểu tham trị hay không với toán tử typeof, trên bất kỳ biến nào và trả về một chuỗi string cho biết kiểu dữ liệu. Toán tử typeoflàm việc trên string, numbers, Booleanundefined. Ví dụ theo sau cho thấy giá trị trả về khi sử dụng typeoftrên các kiểu dữ liệu tham trị khác nhau:

console.log(typeof "Nicholas"); //"string"
console.log(typeof 10); // "number"
console.log(typeof 5.1); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"

Như bạn có thể mong đợi, typeof trả về string khi giá trị là một chuỗi; number khi giá trị là 1 số (cả số nguyên và số thập phân); boolean khi giá trị là kiểu Boolean; và undefined khi giá trị không được định nghĩa.

Phần khó hơn liên quan đến null.

Bạn không phải là người đầu tiên nhầm lẫn bởi kết quả của dòng code sau:

console.log(typeof null); // "object"

Khi bạn chạy typeof null; kết quả là một object. Nhưng tại sao lại là một object khi kiểu là null? (Trong thực tế, đây được thừa nhận như một lỗi bởi TC39, của ban thiết kế và bảo trì JS. Bạn có thể cho rằng null là một con trỏ đến object rỗng, trả về một object là hợp lý, nhưng đó vẫn còn rất mơ hồ).

Các tốt nhất để xác định nếu một giá trị là null là so sánh nó trực tiếp với null, như sau:

console.log(value === null); // true or false

SO SÁNH MÀ KHÔNG CÓ SỰ ÉP BUỘC

Chú ý đoạn code trên sử dụng toán tử `===` thay cho toán tử `==`. 
Lý do là toán tử `===` so sánh 2 giá trị mà không có sự ép buộc biến 
(vừa so sánh giá trị và kiểu dữ liệu). Để hiểu rằng tại sao điều này 
là quan trọng, xem ví dụ sau:

---
console.log("5" == 5); // true
console.log("5" === 5); // false

console.log(undefined == null); // true
console.log(undefined === null); // false
---

Khi bạn sử dụng toán tử `==`, chuỗi "5" and số 5 bằng nhau bởi vì `==` 
tự động convert chuỗi đến một số trước khi thực hiện việc so sánh. 
Toán tử `===` không làm điều đó bởi vì chúng là 2 kiểu khác nhau. 
Tương tự như vậy, khi bạn so sánh `undefined` và `null`, 
toán tử `==` nói rằng chúng giống nhau nhưng `===` thì không. 
Khi bạn cố gắng xác định `null`, sử dụng `===` để bạn có thể 
xác định đúng kiểu của chúng.

Các phương thức của Kiểu Tham trị

Mặc dù chúng là các kiểu dữ liệu nguyên thủy, strings, numbersBooleans thật sự có một vài phương thức (methods). (Các kiểu nullundefined không có phương thức). Cụ thể Strings có một vài phương thức giúp cho bạn có thể thao tác trên chúng. Ví dụ:

var name = "Nicholas";
var lowercaseName = name.toLowerCase(); // convert to lowercase
var firstLetter = name.charAt(0); // get first character
var middleOfName = name.substring(2, 5); // get characters 2-4

var count = 10;
var fixedCount = count.toFixed(2); // convert to "10.00"
var hexCount = count.toString(16); // convert to "a"

var flag = true;
var stringFlag = flag.toString(); // convert to "true"

Kiểu Tham chiếu

Kiểu tham chiếu đại diện cho một objects trong JS và là những thứ gần gũi với class trong các ngôn ngữ. Giá trị tham chiếu là một thể hiện (instance) của kiểu tham chiếu và đồng nghĩa với các đối tượng (objects). Một object là một danh sách có thứ tự các thuộc tính (properties) chứa tên (name) và một giá trị (value). Khi value của một property là một function, nó được gọi là một method. Function bản thân chúng là một giá trị tham chiếu trong JS, vì vậy ở đây có một chút khác biệt giữa một property chứa một mảng các giá trị và một property chứa một function ngoại trừ một số function có thể thực thi.

Dĩ nhiên, bạn phải tạo object trước khi cạn có thể bắt đầu làm việc với chúng.

Tạo Objects

Nó dường như giúp bạn nghĩ về object của JS không gì nhiều hơn một bảng băm như hình sau:

Object
name value
name value

Ở đây có 2 cách để tạo hoặc thể hiện một object. Đầu tiên là sử dụng toán tử new với một constructor. (Một constructor đơn giản là một function sử dụng new để tạo một object- bất kỳ function nào cũng có thể là một constructor).

Theo quy ước, các constructor trong JS bắt đầu với một ký tự HOA để phân biệt chúng với các function nonconstructor. Ví dụ, code sau khởi tạo một object chung chung và lưu trữ một tham chiếu đến nó trong object:

var object = new Object();

Kiểu tham chiếu không lưu trữ object trực tiếp đến biến mà nó được gán, vì vậy biến object trong ví dụ này không thật sự chứa object thể hiện. Thay vì đó, nó giữ một con trỏ (hoặc một tham chiếu) đến vị trí trong bộ nhớ nơi object tồn tại. Đây là sự khác biệt chính giữa object và kiểu giá trị nguyên thủy, như giá trị nguyên thủy được lưu trữ trực tiếp trong biến.

Khi bạn gán một object đến một biến, bạn thực sự gán một con trỏ. Điều này có nghĩa rằng nếu bạn gán một biến đến một biến khác, mỗi biến sẽ nhận một bản sao chép của con trỏ, và cả hai đều cùng trỏ đến cùng một object trong bộ nhớ. Ví dụ:

var object1 = new Object();
var object2 = object1;

Đoạn code đầu tiên tạo một object (với từ khóa new) và lưu trữ một tham chiếu trong object1. Tiếp theo object2được gán giá trị của object1. Đây vẫn chỉ là một thể hiện của object đã được tạo trong dòng đầu tiên, nhưng cả hai biến bây giờ đều trỏ đến 1 object, như mô tả trong hình sau:

Dereferencing Objects

JS là một ngôn ngữ thu gom rác (garbage-collected), vì vậy bạn không thật sự cần phải lo lắng về việc cấp phát bộ nhớ khi bạn sử dụng kiểu tham chiếu. Tuy nhiên, tốt nhất là để các object tham chiếu mà bạn không cần cho bộ dọn rác có thể giải phóng bộ nhớ. Cách tốt nhất để làm điều này là set biến object đến null.

var object1 = new Object();

//do something

object1 = null; //dereference

Ở đây, object1 được tạo và sử dụng trước khi cuối cùng được set đến null. Khi ở đây có nhiều tham chiếu đến một object trong bộ nhớ, bộ thu gom rác (garbage-collector) có thể sử dụng bộ nhớ cho 1 vài thứ khác.

Thêm và xóa các properties

Một khía cạnh thú vị khác của các object trong JS là bạn có thể thêm và xoá các properties tại bất kỳ thời điểm nào. Lấy ví dụ:

var object1 = new Object();
var object2 = object1;

object1.myCustomProperty ="Awesome!";
console.log(object2.myCustomProperty); // "Awesome!"

Ở đây, myCustomProperty được thêm vào object1 với giá trị là “Awesome!”. Thuộc tính đó cũng được truy cập trên object2 bởi vì cả hai object1object2 đều trỏ đến cùng một object.

Ngoài các kiểu tham chiếu chung của object, JS có một vài kiểu được xây dựng sẵn cho bạn.

Instantiating Built-in Types

Bạn đã nhìn thấy làm thế nào để tạo và tương tác với một object được tạo với new Object(). Kiểu Object chỉ là một trong nhiều thứ tham chiếu được JS cung cấp. Các kiểu xây dựng sẵn khác có nhiều đặc biệt trong cách sử dụng của chúng và có thể được khởi tạo vào bất kỳ lúc nào.
Các kiểu xây dựng sẵn đó là:

Array: một danh sách có thứ tự các giá trị được lập chỉ mục
Date: Ngày và giờ
Error: Lỗi runtime( đây cũng có nhiều lỗi con đặc biệt)
Function: Một function
Object: Một object chung chung
RegExp: Biểu thức chính quy

Bạn có thể tạo thể hiện của mỗi loại bằng cách sử dụng từ khóa new như sau:

var items = new Array();
var now = new Date();
var error = new Error("Something bad happened.");
var func = new Function("console.log('Hi');");
var object = new Object();
var re = new RegExp("\\d+");

Object and Array Literals

Để tạo một object với cú pháp object literal, bạn có thể định nghĩa các properties của một object mới bên trong cặp dấu ngoặc {}. Các properties được tạo thành một định danh hoặc một chuỗi, theo sau bởi dấu : và giá trị, với nhiều properties được chia cách bởi dấu ,. Ví dụ:

var book = {
name: "The principles of Object-Oriented JavaScript",
year: 2014
},

Bạn cũng có thể sử dụng string như tên của properties, sẽ hữu ích trong trường hợp bạn muốn tên của property có space hoặc một vài ký tự đặc biệt:

var book = {
"name": "The principles of Object-Oriented JavaScript",
"year": 2014
};

Ví dụ này là tương đương với ví dụ trước đó, mặc dù chúng được khai báo khác nhau. Cả hai ví dụ đều hợp lý tương đương như ví dụ sau:

var book = new Object();
book.name = "The Principles of Object-Oriented JavaScript";
book.year = 2014;

Kết quả trả về cùng với 2 ví dụ trước là như nhau: một object với 2 properties. Sự lựa chọn mô hình nào tùy thuộc vào bạn bởi vì kết quả của function là giống nhau.

Bạn có thể định nghĩa một array literal theo cùng cách được bao bọc bởi bất kỳ số lượng value được chia tách bởi dấu , bên trong 2 dấu ngoặc vuông. Ví dụ:

var colors = ["red", "blue", "green"];
console.log(color[0]); // "red"

Code trên tương đương với code theo sau:

var colors = new Array("red", "blue", "green");
console.log(colors[0]); // "red"

Function Literals

Hầu hết bạn luôn định nghĩa function sử dụng các literal form của chúng. Trong thực tế, việc sử dụng Function constructor là kiểu không khuyến khích cho việc bảo trì, đọc và debug một chuỗi string code hơn là các đoạn code thực sự, vì vậy bạn sẽ hiếm khi nhìn thấy chúng trong code.

Tạo function thì nhiều dễ dàng hơn và ít lỗi hơn khi bạn sử dụng các literal form. Ví dụ:

function reflect(value) {
return value;
}

// is the same as

var reflect = new Function("value", "return value;");

Đoạn code trên định nghĩa một function reflect() sẽ trả về kết kỳ value nào được passed đến nó. Thậm chí trong trường hợp của function đơn giản này, kiểu literal form là dễ dàng hơn để viết và hiểu hơn là constructor form. Thêm nữa đây không phải là cách tốt để debug function khi tạo với constructor form: Các function này không được nhận dạng bởi các trình Debugger của JS và do đó thực tế nó như hộp đen trong ứng dụng của bạn.

Regular Expression Literals

JS cũng có regular expression literals cho phép bạn định nghĩa biểu thức chính quy mà không sử dụng RegExp constructor. Regular expression literals trông rất giống với biểu thức chính quy trong Perl: Mẫu chứa giữa hai \ và bất kỳ điều kiện tùy chọn nào là ký tự theo sau \ thứ 2. Ví dụ:

var numbers = /\d+/g;

// is the same as

var numbers= new RegExp("\\d+", "g");

The literal form của biểu thức chính quy trong JS thì dễ hiểu hơn với constructor form bởi vì bạn không cần lo lắng về các ký tự bọc chuỗi như nháy đơn hoặc nháy kép. Khi sử dụng RegExp constructor, bạn pass mẫu như một string, vì vậy bạn phải thêm phần quan tâm về các dấu nháy ngược. Regular Expression literal thường được dùng nhiều hơn các hình thức của constructor form trong JS ngược trừ khi các biểu thức chính quy constructor xử lý động từ một hoặc nhiều chuỗi string.

Truy cập Thuộc tính (Property Access)

Properties là cặp name/value để lưu trữ trong một object. Dấu . là cách hầu hết được dùng để truy cập các properties trong JS (cũng như trong nhiều ngôn ngữ OOP khác), nhưng bạn cũng có thể truy cập các properties trong các object JS bằng cách sử dụng dấu ngoặc [] với chuỗi string bên trong.

Ví dụ, bạn có thể viết đoạn code sau, sử dụng dấu chấm .:

var array = [];
array.push(12345);

Với dấu ngoặc [], tên của method bây giờ được bao gồm trong một chuỗi bên trong ngoặc vuông, như ví sau sau:

var array = [];
array["push"](12345);

Cú pháp này rất hữu ích khi bạn muốn cập nhật động cho các thuộc tính truy cập. Ví dụ, đây là dấu ngoặc vuông cho phép bạn sử dụng một biến thay vì xác định property để truy cập:

var array = [];
var method = "push";
array[method](12345);

Trong danh sách trên, biến method có giá trị push, vì thế push() có giá trị trên mảng. Một điểm cần lưu ý rằng, điều này chỉ khác cú pháp, bằng cách này hay cách khác, sự khác biệt giữa dấu chấm và cặp ngoặc vuông là ở chỗ cặp ngoặc vuông cho phép bạn sử dụng các ký tự đặc biệt trong tên của các property. Các nhà phát triển có xu hướng sử dụng dấu chấm để dễ dàng cho việc đọc, vì thế bạn sẽ nhìn thấy nó thường xuyên hơn dấu ngoặc vuông.

Xác định Kiểu tham chiếu

Một function là kiểu tham chiếu dễ nhất để xác định bởi vì khi bạn sử dụng toán tử typeof trên một function, toán tử nên trả về function:

function reflect(value) {
return value;
}

console.log(typeof reflect); // "function"

Kiểu tham chiếu khác là phức tạp hơn để xác định bởi vì tất cả các kiểu tham chiếu khác function typeof trả về object. Điều đó không hữu ích khi bạn đang làm việc với nhiều kiểu khác nhau. Để xác định kiểu tham chiếu nhiều dễ dàng hơn, bạn có thể sử dụng toán tử instanceof trong JS.

Toán tử instanceof nhận một object và một constructor như các đối số. Khi value là một thể hiện của kiểu constructor đặc biệt, instanceof trả về true, ngược lại nó trả về false, như bạn có thể xem ví dụ dưới đây:

var items = [];
var object = {};

function reflect(value) {
return value;
}

console.log(items instanceof Array); // true
console.log(object instanceof Object); // true
console.log(reflect instanceof Function); // true

Trong ví dụ này, nhiều value được test đang sử dụng instanceof và một constructor. Mỗi kiểu tham chiếu được xác định đúng bằng cách sử dụng instanceof và constructor đại diện cho kiểu true.

Toán tử instanceof có thể xác định các kiểu kế thừa. Điều này có nghĩa rằng mỗi object thực sự là một thể hiện của Object bởi vì mỗi kiểu tham chiếu đều kế thừa từ Object.
Theo sau là danh sách ba kiểu tham chiếu được tạo trước đó với instanceof:

var items = [];
var object = {};

function reflect(value) {
return value;
}

console.log(items instanceof Array); // true
console.log(items instanceof Object); // true
console.log(object instanceof Object); // true
console.log(object instanceof Array); // false
console.log(reflect instanceof Function); // true
console.log(reflect instanceof Object); // true

Mỗi kiểu tham chiếu được xác định như một thể hiện của Object, vì tất cả đều kế thừa từ Object.

Xác định Mảng (Arrays)

Mặc dù instanceof có thể xác định một mảng, đây còn có một ngoại lệ ảnh hưởng đến các nhà phát triển: value của JS có thể chuyển qua lại những các frame trong cùng một trang web. Điều này trả thành vấn đề chỉ khi bạn cố xác định kiểu của một giá trị tham chiếu, bởi vì mỗi trang web đều có context global là phiên bản riêng của Object, Array và tất cả các kiểu build-in khác. Khi bạn đặt một array từ một frame đến một frame khác, instanceof không làm việc bởi vì array thật sự là một thể hiện của Array.

Để giải quyết vấn đề này, ECMAScript 5 giới thiệu Array.isArray() được dùng để xác định value như một thể hiện của Array bất kể nguồn gốc của giá trị. Method này trả về true khi nó nhận một value là một native array từ bất kỳ context. Nếu môi trường của bạn tuân thủ chuẩn ECMAScript 5, Array.isArray() là cách tốt nhất để xác định mảng.

var items = [];

console.log(Array.isArray(items)); // true

Method `Array.isArray() được hỗ trợ trong hầu hết các môi trường của trên trình duyệt lẫn trong Node.js. Method này không hỗ trợ trên IE 8 và các phiên bản IE trước đó.

Primitive Wrapper Types

Có lẽ một trong những phần nhầm lẫn của JS là khái niệm của primitive wrapper types. Đây là 3 kiểu primitive wraper types (String, Number và Boolean). Các kiểu tham chiếu đặc biệt này tồn tại để làm việc với các giá trị nguyên thủy dễ dàng như với các objects.

Các kiểu primitive wrapper là kiểu tham chiếu được tự động tạo đằng sau bất cứ khi nào strings, numbers hoặc Booleans được đọc. Ví dụ, trong dòng đầu tiên của danh sách này, một giá trị của chuỗi nguyên thủy được gán đến name. Dòng thứ 2 xử lý name như một object và gọi charAt(0)sử dụng dấu chấm:

var name = "Nicholas";
var firstChar = name.charAt(0);
console.log(firstChar); // "N";

Đây là những gì xảy ra đằng sau chúng:

// what the JS engine does
var name = "Nicholas";
var temp = new String(name);
var firstChar = temp.charAt(0);
temp = null;
console.log(firstChar); // "N"

Bởi vì dòng thứ 2 sử dụng một string (kiểu nguyên thủy) như một object, JS engine tạo một thể hiện của String vì vậy method charAt(0) sẽ làm việc. Object String tồn tại chỉ cho một câu lệnh trước khi bị hủy (một quy trình gọi là autoboxing). Để kiểm tra điều này, thử thêm một property đến một string:

var name = "Nicholas";
name.last = "Zakas";

console.log(name.last) // undefined

Đoạn code trên cố gắng thêm một property last đến một chuỗi name. Code này hoạt động tốt ngoại trừ rằng property không tìm thấy. Chuyện gì xảy ra với nó? Khi làm việc với các regular object, bạn có thể thêm properties tại bất kỳ thời điểm nào và chúng vẫn còn đó cho đến khi bạn remove chúng đi. Với kiểu primitive wrapper, các properties dường như không tìm thấy bởi vì object trên property được gán bị hủy nguy lập tức sau đó.

Đây là những gì thực sự xảy ra trong JS engine:

// what the JS engine does
var name = "Nicholas";
var temp = new String(name);
temp.last = "Zakas";
temp = null; // temporary object destroyed

var temp = new String(name);
console.log(temp.last); // undefined
temp = null;

Thay vì gán một property mới đến một string, code thật sự tạo một property mới trên một object temp và bị hủy sau đó. Khi bạn cố gắng truy cập đến property sau đó một object khác là temp được tạo ra và property mới không tồn tại ở đây. Mặc dù giá trị tham chiếu đã được tạo một cách tự động cho giá trị nguyên thủy, khi đó instanceof kiểm tra cho các kiểu của giá trị cho kết quả là false:

var name = "Nicholas";
var count = 10;
var found = false;

console.log(name instanceof String); //false
console.log(count instanceof Number); // false
console.log(found instanceof Boolean); // false

Toán tử instanceof trả về false bởi vì một object temp được tạo chỉ khi một value được đọc. Bởi vì instanceofkhông thực sự đọc bất kỳ thứ gì, không có object temp được tạo, và nó nói với chúng ta rằng value không thể hiện cho kiểu primitive wrapper. Bạn có thể tạo kiểu primitive wrapper bằng tay, nhưng cũng có những tác dụng phụ nhất định:

var name = new String("Nicholas");
var count = new Number(10);
var found = new Boolean(false);

console.log(typeof name); // "object"
console.log(typeof count); // "object"
console.log(typeof found); // "object"

Như bạn có thể nhìn thấy, tạo một thể hiện của kiểu primitive wrapper chỉ là tạo một object khác, điều đó có nghĩa typeof không thể xác định kiểu của data mà bạn có ý định lưu trữ.

Hơn nữa, bạn không thể sử dụng các object String, Number, và Boolean như bạn sử dụng với các value nguyên thủy. Ví dụ, code sau sử dụng một object Boolean. Object Booleanfalse, câu lệnh console.log("Found") vẫn thực hiện bởi vì một object luôn dường như true trong một câu lệnh điều kiện. Không vấn đề về giá trị đại diện của object là false, nó là một object, vì thế nó là true.

var found = new Boolean(false);

if (found) {
console.log("Found"); // this executes
}

Tạo đối tượng primitive wrappers cũng có thể nhầm lẫn trong một số trường hợp, vì thế cho đến khi bạn tìm một trường hợp đặc biệt để sử dụng, còn không bạn nên tránh sử dụng nó. Hầu hết, sử dụng object primitive wrapper thay vì chỉ chỉ primitives dẫn đến lỗi.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s