Loại tham chiếu ECMAScript
- Trang trước Chuyển đổi loại ECMAScript
- Trang tiếp theo Toán tử một ngôi
Loại tham chiếu thường được gọi là lớp (class).
Giáo trình này sẽ thảo luận về rất nhiều loại tham chiếu định nghĩa sẵn của ECMAScript.
Loại tham chiếu
Loại tham chiếu thường được gọi là lớp (class), có nghĩa là khi gặp giá trị tham chiếu, điều được xử lý là đối tượng.
Giáo trình này sẽ thảo luận về rất nhiều loại tham chiếu định nghĩa sẵn của ECMAScript.
Từ bây giờ, chúng ta sẽ tập trung thảo luận về các loại tham chiếu liên quan chặt chẽ với các loại nguyên mẫu đã thảo luận.
Lưu ý:Theo nghĩa truyền thống, ECMAScript không thực sự có lớp. Thực tế, ngoài việc cho thấy không có lớp, trong ECMA-262 cũng không có từ 'lớp'. ECMAScript định nghĩa 'định nghĩa đối tượng', logic tương đương với lớp trong ngôn ngữ lập trình khác.
Lưu ý:Khóa học này sẽ sử dụng thuật ngữ "đối tượng".
Đối tượng được tạo ra bằng cách sử dụng toán tử new cộng với tên của đối tượng cần được thể hiện. Ví dụ, đoạn mã sau tạo ra instance của đối tượng Object:
var o = new Object();
Cú pháp này tương tự như ngôn ngữ Java, nhưng khi có nhiều tham số, ECMAScript yêu cầu sử dụng dấu ngoặc. Nếu không có tham số, như đoạn mã sau, dấu ngoặc có thể bỏ qua:
var o = new Object;
Lưu ý:Mặc dù dấu ngoặc không bắt buộc, nhưng để tránh sự lẫn lộn, tốt nhất là sử dụng dấu ngoặc.
Lưu ý:Chúng ta sẽ深入研究 đối tượng và hành vi của chúng trong chương cơ sở về đối tượng.
Chương này tập trung vào các loại tham chiếu có loại nguyên thủy tương đương.
Đối tượng Object
Đối tượng Object không có giá trị nhiều lắm, nhưng trước khi hiểu các lớp khác, bạn vẫn nên hiểu nó. Bởi vì đối tượng Object trong ECMAScript tương tự như java.lang.Object trong Java, tất cả các đối tượng trong ECMAScript đều kế thừa từ đối tượng này, tất cả các thuộc tính và phương thức trong đối tượng Object sẽ xuất hiện trong các đối tượng khác, vì vậy việc hiểu đối tượng Object sẽ giúp bạn hiểu các đối tượng khác tốt hơn.
Đối tượng Object có các thuộc tính sau:
- constructor
- Tham chiếu đến hàm tạo đối tượng (con trỏ). Đối với đối tượng Object, con trỏ này chỉ đến hàm Object() nguyên thủy.
- Prototype
- Tham chiếu đến nguyên mẫu của đối tượng. Đối với tất cả các đối tượng, nó mặc định trả về một instance của Object.
Đối tượng Object cũng có một số phương thức:
- hasOwnProperty(property)
- Xác định đối tượng có thuộc tính đặc định nào đó hay không. Phải chỉ định thuộc tính này bằng chuỗi. (Ví dụ, o.hasOwnProperty("name"))
- IsPrototypeOf(object)
- Xác định đối tượng này có phải là nguyên mẫu của đối tượng khác hay không.
- PropertyIsEnumerable
- Xác định thuộc tính được chỉ định có thể được liệt kê bằng câu lệnh for...in hay không.
- ToString()
- Trả về biểu diễn chuỗi nguyên thủy của đối tượng. Đối với đối tượng Object, ECMA-262 không định nghĩa giá trị này, vì vậy các thực hiện ECMAScript khác nhau có giá trị khác nhau.
- ValueOf()
- Trả về giá trị nguyên thủy phù hợp với đối tượng đó. Đối với nhiều đối tượng, giá trị mà phương thức này trả về tương tự như giá trị của phương thức ToString().
Ghi chú:Mỗi thuộc tính và phương thức được liệt kê trên sẽ bị ghi đè bởi các đối tượng khác.
Đối tượng Boolean
Đối tượng Boolean là một loại đối tượng tham chiếu của loại nguyên thủy Boolean.
Để tạo đối tượng Boolean, chỉ cần truyền giá trị Boolean làm tham số:
var oBooleanObject = new Boolean(true);
Đối tượng Boolean sẽ ghi đè phương thức ValueOf() của đối tượng Object, trả về giá trị nguyên thủy, tức là true và false. Phương thức ToString() cũng sẽ bị ghi đè, trả về chuỗi "true" hoặc "false".
Rất đáng tiếc, trong ECMAScript, đối tượng Boolean không được sử dụng nhiều, và ngay cả khi sử dụng, cũng không dễ hiểu.
Vấn đề thường xuất hiện khi sử dụng đối tượng Boolean trong biểu thức Boolean. Ví dụ:
var oFalseObject = new Boolean(false); var bResult = oFalseObject && true; // xuất true
Trong đoạn mã này, sử dụng giá trị false để tạo đối tượng Boolean. Sau đó, sử dụng giá trị này để thực hiện phép AND với giá trị nguyên thủy true. Trong phép toán Boolean, kết quả của phép AND giữa false và true là false. Tuy nhiên, trong dòng mã này, tính toán được thực hiện là cho oFalseObject,而不是 giá trị false của nó.
Như đã thảo luận trước đó, trong biểu thức Boolean, tất cả các đối tượng sẽ được tự động chuyển đổi thành true, vì vậy giá trị của oFalseObject là true. Sau đó, true sẽ thực hiện phép AND với true, kết quả là true.
Lưu ý:Mặc dù bạn nên hiểu về khả năng sử dụng của đối tượng Boolean, nhưng tốt nhất vẫn nên sử dụng giá trị nguyên thủy Boolean để tránh những vấn đề được đề cập trong phần này.
tham khảo
Nếu bạn cần thêm thông tin về đối tượng Boolean, hãy truy cập Tài liệu tham khảo đối tượng Boolean JavaScript。
Đối tượng Number
Như bạn có thể tưởng tượng, đối tượng Number là một loại đối tượng tham chiếu của loại nguyên thủy Number. Để tạo đối tượng Number, hãy sử dụng mã sau:
var oNumberObject = new Number(68);
Bạn đã nhận ra đối tượng Number mà chúng ta đã thảo luận trong phần trước của chương này về các giá trị đặc biệt (như Number.MAX_VALUE). Tất cả các giá trị đặc biệt đều là thuộc tính tĩnh của đối tượng Number.
Để lấy giá trị nguyên thủy của đối tượng số Number, chỉ cần sử dụng phương thức valueOf():
var iNumber = oNumberObject.valueOf();
Tất nhiên, lớp Number cũng có phương thức toString(), đã được thảo luận chi tiết trong phần thảo luận về việc chuyển đổi loại.
Ngoài các phương thức tiêu chuẩn được kế thừa từ đối tượng Object, đối tượng Number còn có một số phương thức chuyên dụng để xử lý số.
Phương thức toFixed()
Phương thức toFixed() trả về biểu diễn chuỗi của số có số lượng chữ số thập phân xác định. Ví dụ:
var oNumberObject = new Number(68); alert(oNumberObject.toFixed(2)); // xuất ra "68.00"
Ở đây, tham số của phương thức toFixed() là 2, có nghĩa là nên hiển thị hai chữ số thập phân. Phương thức này trả về "68.00", các vị trí trống được lấp đầy bằng số 0. Đối với các ứng dụng xử lý tiền tệ, phương thức này rất hữu ích. Phương thức toFixed() có thể biểu diễn số có từ 0 đến 20 chữ số thập phân, các giá trị vượt quá phạm vi này sẽ gây ra lỗi.
Phương thức toExponential()
Một phương thức khác liên quan đến định dạng số là toExponential(), nó trả về chuỗi biểu diễn số dưới dạng số học.
Giống như phương thức toFixed(), phương thức toExponential() cũng có một tham số xác định số lượng chữ số thập phân cần xuất ra. Ví dụ:
var oNumberObject = new Number(68); alert(oNumberObject.toExponential(1)); // xuất ra "6.8e+1"
Kết quả của đoạn mã này là "6.8e+1", đã được giải thích trước đó, nó biểu diễn 6.8x101Vấn đề là nếu không biết nên biểu diễn số dưới dạng nào (dạng định dạng hoặc dạng指数) thì sao? Có thể sử dụng phương thức toPrecision().
Phương thức toPrecision()
Phương thức toPrecision() trả về hình thức định dạng hoặc hình thức指数 của số dựa trên hình thức có ý nghĩa nhất. Nó có một tham số, đó là số lượng chữ số để biểu diễn số (không bao gồm指数). Ví dụ:
var oNumberObject = new Number(68); alert(oNumberObject.toPrecision(1)); // xuất ra "7e+1"
Nhiệm vụ của đoạn mã này là biểu diễn số 68 bằng một chữ số, kết quả là "7e+1", biểu diễn dưới dạng khác là 70. Đúng vậy, phương thức toPrecision() sẽ làm tròn số.
var oNumberObject = new Number(68); alert(oNumberObject.toPrecision(2)); // xuất ra "68"
Tất nhiên, kết quả là "68", vì đó chính là cách biểu diễn chính xác của số đó. Tuy nhiên, nếu số lượng chữ số được chỉ định nhiều hơn số lượng cần thiết thì sao?
var oNumberObject = new Number(68); alert(oNumberObject.toPrecision(3)); //xuất ra "68.0"
Trong trường hợp này, toPrecision(3) tương đương với toFixed(1), xuất ra là "68.0".
phương thức toFixed(), toExponential() và toPrecision() đều sẽ thực hiện việc làm tròn để biểu diễn số với số lượng chữ số thập phân chính xác.
Lưu ý:Tương tự như đối tượng Boolean, đối tượng Number cũng rất quan trọng, nhưng nên sử dụng ít đối tượng này để tránh các vấn đề tiềm ẩn. Khi có thể, hãy sử dụng biểu diễn nguyên thủy của số.
tham khảo
Nếu cần thêm thông tin về đối tượng Number, xin hãy truy cập Tài liệu tham khảo đối tượng Number JavaScript。
đối tượng String
Đối tượng String là biểu diễn của loại nguyên thủy String, nó được tạo ra theo cách sau:
var oStringObject = new String("hello world");
phương thức valueOf() và toString() của đối tượng String đều sẽ trả về giá trị nguyên thủy của loại String:
alert(oStringObject.valueOf() == oStringObject.toString()); //xuất ra "true"
Nếu chạy đoạn mã này, kết quả xuất ra là "true", điều này có nghĩa là các giá trị này thực sự bằng nhau.
Ghi chú:Đối tượng String là một trong những loại tham chiếu phức tạp trong ECMAScript. Similar, trọng tâm của phần này chỉ là các chức năng cơ bản của lớp String. Các chức năng cao cấp hơn, xin hãy đọc các phần liên quan của hướng dẫn này hoặc tham khảo Tài liệu tham khảo đối tượng String JavaScript。
thuộc tính length
Đối tượng String có thuộc tính length, đó là số lượng ký tự trong chuỗi:
var oStringObject = new String("hello world"); alert(oStringObject.length); //xuất ra "11"
ví dụ này sẽ xuất ra "11", tức là số lượng ký tự trong "hello world". Lưu ý, ngay cả khi chuỗi chứa các ký tự kép byte (so với ký tự ASCII chỉ chiếm một byte), mỗi ký tự cũng chỉ được tính là một ký tự.
phương thức charAt() và charCodeAt()
Đối tượng String cũng có rất nhiều phương thức.
đầu tiên, hai phương thức charAt() và charCodeAt() truy cập vào các ký tự đơn trong chuỗi. Cả hai phương thức này đều có một tham số, đó là vị trí của ký tự cần xử lý.
charAt() 方法返回的是包含指定位置处的字符的字符串:
var oStringObject = new String("hello world"); alert(oStringObject.charAt(1)); //输出 "e"
Trong chuỗi "xin chào thế giới", ký tự ở vị trí 1 là "e". Trong phần "ECMAScript loại nguyên thủy", chúng ta đã nói rằng vị trí của ký tự đầu tiên là 0, vị trí của ký tự thứ hai là 1, và cứ thế. Do đó, gọi charAt(1) trả về "e".
Nếu bạn muốn nhận được không phải là ký tự mà là mã ký tự, bạn có thể gọi phương pháp charCodeAt():
var oStringObject = new String("hello world"); alert(oStringObject.charCodeAt(1)); // xuất ra "101"
Ví dụ này xuất ra "101", là mã ký tự của chữ cái "e" in thường.
Phương pháp concat()
Tiếp theo là phương pháp concat(), được sử dụng để kết nối một hoặc nhiều chuỗi với giá trị gốc của đối tượng String. Phương pháp này trả về giá trị gốc của String, giữ nguyên đối tượng String ban đầu:
var oStringObject = new String("xin chào "); var sResult = oStringObject.concat("thế giới"); alert(sResult); // xuất ra "xin chào thế giới" alert(oStringObject); // xuất ra "xin chào "
Trong đoạn mã này, phương pháp concat() trả về "xin chào thế giới", trong khi đối tượng String lưu trữ vẫn là "xin chào ". Do lý do này, việc sử dụng dấu cộng (+) để kết nối chuỗi là phổ biến hơn, vì hình thức này từ ngữ lý ra đã thể hiện hành vi thực sự:
var oStringObject = new String("xin chào "); var sResult = oStringObject + "thế giới"; alert(sResult); // xuất ra "xin chào thế giới" alert(oStringObject); // xuất ra "xin chào "
Cả hai phương pháp indexOf() và lastIndexOf()
Đến nay, chúng ta đã thảo luận về các phương pháp kết nối chuỗi, và các phương pháp truy cập vào một ký tự duy nhất trong chuỗi. Tuy nhiên, nếu bạn không chắc chắn rằng một ký tự thực sự có trong chuỗi đó, bạn nên gọi phương pháp gì? Lúc này, bạn có thể gọi phương pháp indexOf() và lastIndexOf().
Cả hai phương pháp indexOf() và lastIndexOf() đều trả về vị trí của chuỗi con trong chuỗi khác, nếu không tìm thấy chuỗi con, thì trả về -1.
Sự khác biệt giữa hai phương pháp này là, phương pháp indexOf() bắt đầu tìm kiếm chuỗi từ đầu chuỗi (vị trí 0), trong khi phương pháp lastIndexOf() bắt đầu tìm kiếm từ cuối chuỗi. Ví dụ:
var oStringObject = new String("xin chào thế giới!"); alert(oStringObject.indexOf("o")); 输出 "4" alert(oStringObject.lastIndexOf("o")); 输出 "7"
Ở đây, chuỗi "o" đầu tiên xuất hiện ở vị trí 4, tức là "o" trong "hello"; chuỗi "o" cuối cùng xuất hiện ở vị trí 7, tức là "o" trong "world". Nếu chuỗi chỉ có một chuỗi "o", thì phương thức indexOf() và lastIndexOf() sẽ trả về vị trí tương tự.
Phương thức localeCompare()
Phương thức tiếp theo là localeCompare(), để sắp xếp chuỗi. Phương thức này có một tham số - chuỗi cần so sánh, giá trị trả về là một trong ba giá trị sau:
- Nếu đối tượng String được sắp xếp theo thứ tự字母 trước chuỗi trong tham số, sẽ trả về số âm.
- Nếu đối tượng String bằng chuỗi trong tham số, sẽ trả về 0
- Nếu đối tượng String được sắp xếp theo thứ tự字母 sau chuỗi trong tham số, sẽ trả về số dương.
Ghi chú:Nếu giá trị trả về là số âm, thì phổ biến nhất là -1, nhưng giá trị thực sự trả về là do thực hiện quyết định. Nếu giá trị trả về là số dương, thì tương tự, phổ biến nhất là 1, nhưng giá trị thực sự trả về là do thực hiện quyết định.
Dưới đây là một ví dụ:
var oStringObject = new String("yellow"); alert(oStringObject.localeCompare("brick")); //In ra "1" alert(oStringObject.localeCompare("yellow")); //In ra "0" alert(oStringObject.localeCompare("zoo")); //In ra "-1"
Trong đoạn mã này, chuỗi "yellow" được so sánh với 3 giá trị, tức là "brick", "yellow" và "zoo". Do được sắp xếp theo thứ tự字母, "yellow" nằm sau "brick", vì vậy phương thức localeCompare() trả về 1; "yellow" bằng "yellow", vì vậy phương thức localeCompare() trả về 0; "zoo" nằm sau "yellow", phương thức localeCompare() trả về -1. Lại nhấn mạnh một lần nữa, do giá trị trả về do thực hiện quyết định, vì vậy tốt nhất nên gọi phương thức localeCompare() theo cách sau:
var oStringObject1 = new String("yellow"); var oStringObject2 = new String("brick"); var iResult = oStringObject1.localeCompare(oStringObject2); if(iResult < 0) { alert(oStringObject1 + " comes before " + oStringObject2); } alert(oStringObject1 + " comes after " + oStringObject2); } alert("The two strings are equal"); }
Bằng cách này, có thể đảm bảo rằng đoạn mã này hoạt động đúng trong mọi thực hiện.
Điểm đặc biệt của phương thức localeCompare() là khu vực (locale, bao gồm cả quốc gia/địa phương và ngôn ngữ) nơi phương thức được thực hiện xác định cách phương thức này hoạt động. Ở Mỹ, ngôn ngữ tiêu chuẩn của thực hiện ECMAScript là tiếng Anh, phương thức localeCompare() phân biệt chữ hoa và chữ thường, chữ hoa đứng sau chữ thường trong thứ tự字母. Tuy nhiên, ở các khu vực khác, tình hình có thể không như vậy.
slice() và substring()
ECMAScript cung cấp hai phương thức để tạo giá trị chuỗi từ một chuỗi con, đó là slice() và substring(). Cả hai phương thức này đều trả về một chuỗi con của chuỗi cần xử lý, đều chấp nhận một hoặc hai tham số. Tham số đầu tiên là vị trí bắt đầu của chuỗi con cần lấy, tham số thứ hai (nếu có) là vị trí chấm dứt của chuỗi con cần lấy (tức là, ký tự ở vị trí chấm dứt không bao gồm trong giá trị trả về). Nếu bỏ qua tham số thứ hai, vị trí chấm dứt sẽ mặc định là độ dài của chuỗi.
Như với phương thức concat() vậy, phương thức slice() và substring() cũng không thay đổi giá trị của đối tượng String. Chúng chỉ trả về giá trị String ban đầu, giữ nguyên đối tượng String.
var oStringObject = new String("hello world"); alert(oStringObject.slice("3")); // Xuất ra "lo world" alert(oStringObject.substring("3")); // Xuất ra "lo world" alert(oStringObject.slice("3", "7")); // Xuất ra "lo w" alert(oStringObject.substring("3", "7")); // Xuất ra "lo w"
Trong ví dụ này, cách sử dụng của slice() và substring() giống nhau, và giá trị trả về cũng vậy. Khi chỉ có tham số 3, cả hai phương pháp đều trả về "lo world", vì "l" thứ hai trong "hello" nằm ở vị trí 3. Khi có hai tham số "3" và "7", cả hai phương pháp đều trả về "lo w" (ký tự "o" trong "world" nằm ở vị trí 7, vì vậy nó không được bao gồm trong kết quả).
Tại sao lại có hai phương pháp có chức năng hoàn toàn giống nhau? Thực tế, hai phương pháp này không hoàn toàn giống nhau, nhưng chỉ khi tham số là âm, cách xử lý tham số của chúng mới có sự khác biệt nhỏ.
Đối với các tham số âm, hàm slice() sẽ sử dụng độ dài của chuỗi cộng với tham số, trong khi đó hàm substring() sẽ xử lý nó như là vị trí 0 (nghĩa là sẽ bỏ qua nó). Ví dụ:
var oStringObject = new String("hello world"); alert(oStringObject.slice("-3")); // Xuất ra "rld" alert(oStringObject.substring("-3")); // Xuất ra "hello world" alert(oStringObject.slice("3, -4")); // Xuất ra "lo w" alert(oStringObject.substring("3, -4")); // Xuất ra "hel"
Như vậy có thể thấy sự khác biệt chính giữa hàm slice() và substring().
Khi chỉ có tham số -3, hàm slice() sẽ trả về "rld", hàm substring() sẽ trả về "hello world". Bởi vì đối với chuỗi "hello world", slice("-3") sẽ được chuyển đổi thành slice("8"), trong khi đó substring("-3") sẽ được chuyển đổi thành substring("0").
Tương tự, khi sử dụng tham số 3 và -4, sự khác biệt cũng rất rõ ràng. slice() sẽ được chuyển đổi thành slice(3, 7), giống như ví dụ trước, trả về "lo w". Còn phương pháp substring() sẽ giải thích hai tham số là substring(3, 0), thực chất là substring(0, 3), vì substring() luôn lấy số nhỏ hơn làm vị trí bắt đầu, số lớn hơn làm vị trí kết thúc. Do đó, substring("3, -4") trả về "hel". Dòng mã cuối cùng trong đoạn mã này được sử dụng để giải thích cách sử dụng các phương pháp này.
toLowerCase(), toLocaleLowerCase(), toUpperCase() và toLocaleUpperCase()
Mục tiêu cuối cùng của bộ phương pháp mà chúng ta sẽ thảo luận liên quan đến việc chuyển đổi chữ hoa/thường. Có 4 phương pháp được sử dụng để thực hiện việc chuyển đổi chữ hoa/thường, đó là
- toLowerCase()
- toLocaleLowerCase()
- toUpperCase()
- toLocaleUpperCase()
Từ tên có thể看出 mục đích của chúng, hai phương pháp đầu tiên được sử dụng để chuyển đổi chuỗi thành chữ thường, hai phương pháp sau được sử dụng để chuyển đổi chuỗi thành chữ hoa.
toLowerCase() và toUpperCase() là phương pháp nguyên gốc, được thực hiện dựa trên nguyên mẫu của phương pháp tương tự trong java.lang.String.
toLocaleLowerCase() và toLocaleUpperCase() phương pháp dựa trên khu vực cụ thể được thực hiện (giống như phương pháp localeCompare()). Trong nhiều khu vực, các phương pháp đặc thù của khu vực và phương pháp thông dụng hoàn toàn giống nhau. Tuy nhiên, có một số ngôn ngữ áp dụng các quy tắc đặc thù cho việc chuyển đổi chữ hoa/thường Unicode (ví dụ: tiếng Thổ Nhĩ Kỳ), vì vậy bạn phải sử dụng phương pháp đặc thù của khu vực để thực hiện việc chuyển đổi chính xác.
var oStringObject = new String("Hello World"); alert(oStringObject.toLocaleUpperCase()); // 输出 "HELLO WORLD" alert(oStringObject.toUpperCase()); // 输出 "HELLO WORLD" alert(oStringObject.toLocaleLowerCase()); // 输出 "hello world" alert(oStringObject.toLowerCase()); // Xuất ra "hello world"
Trong đoạn mã này, toUpperCase() và toLocaleUpperCase() đều xuất ra "HELLO WORLD",而下tolowerCase() và toLocaleLowerCase() đều xuất ra "hello world". Nhìn chung, nếu không biết đang chạy ngôn ngữ bằng mã hóa nào, thì sử dụng phương thức đặc trưng cho khu vực là an toàn hơn.
Lưu ý:Lưu ý, tất cả các thuộc tính và phương thức của đối tượng String đều có thể được áp dụng cho giá trị String nguyên thủy, vì chúng là pseudo-object.
Toán tử instanceof
Khi sử dụng toán tử typeof để lưu trữ giá trị bằng loại tham chiếu, sẽ xuất hiện một vấn đề, bất kể đối tượng loại nào được lưu trữ, nó đều trả về "object". ECMAScript đã giới thiệu toán tử instanceof mới để giải quyết vấn đề này.
Toán tử instanceof tương tự như toán tử typeof, được sử dụng để xác định loại đối tượng mà bạn đang xử lý. Khác với phương thức typeof, phương thức instanceof yêu cầu nhà phát triển xác định rõ ràng đối tượng là loại nào cụ thể. Ví dụ:
var oStringObject = new String("hello world"); alert(oStringObject instanceof String); // Xuất ra "true"
Mã này hỏi rằng “Biến oStringObject có phải là đối tượng String không?” oStringObject thực sự là đối tượng String, vì vậy kết quả là "true". Mặc dù không linh hoạt như phương thức typeof, nhưng phương thức instanceof vẫn rất hữu ích khi phương thức typeof trả về "object".
- Trang trước Chuyển đổi loại ECMAScript
- Trang tiếp theo Toán tử một ngôi