Điều quan trọng cần lưu ý ở đây là, vì Javascript là một ngôn ngữ động , về cơ bản, mọi đối tượng chỉ là một bản đồ băm được tôn vinh ( với một vài ngoại lệ ). Và mọi thứ trong một đối tượng Javascript có thể được truy cập theo hai cách - ký hiệu dấu ngoặc và ký hiệu dấu chấm.
Tôi sẽ nhanh chóng đi qua hai ký hiệu trả lời phần đầu tiên của câu hỏi của bạn, và sau đó tôi sẽ đến phần thứ hai.
Ký hiệu khung
Chế độ này tương tự như truy cập hashmap và mảng trong các ngôn ngữ lập trình khác. Bạn có thể truy cập bất kỳ thành phần (dữ liệu (bao gồm các đối tượng khác) hoặc hàm) bằng cú pháp này.
Đây chính xác là những gì bạn đang làm trong ví dụ của bạn. Bạn có 'a'
, đó là một chuỗi (và không là một ký tự theo nghĩa đen, giống như nó sẽ có trong một ngôn ngữ như C ++).
Sử dụng ký hiệu ngoặc, bạn truy cập toUpperCase
phương thức của nó . Nhưng truy cập nó vẫn chưa đủ; alert
chẳng hạn như chỉ cần gõ , trong Javascript, không gọi phương thức. Đó chỉ là một tuyên bố đơn giản. Để gọi hàm, bạn cần thêm dấu ngoặc đơn: alert()
hiển thị hộp thoại đơn giản chứa undefined
, vì nó không nhận được tham số. Bây giờ chúng ta có thể sử dụng kiến thức này để giải mã mã của bạn, trở thành:
alert('a'.toUpperCase());
Mà dễ đọc hơn nhiều.
Trên thực tế, một cách tốt để hiểu điều này tốt hơn một chút là thực thi Javascript sau:
alert(alert)
Điều này gọi alert
bằng cách chuyển cho nó một đối tượng chức năng, đồng thời alert
, mà không thực hiện cảnh báo thứ hai. Những gì được hiển thị (trong Chrome 26, ít nhất) là như sau:
function alert() { [native code] }
Gọi điện thoại:
alert(alert())
hiển thị hai hộp thông báo liên tiếp chứa undefined
. Điều này rất dễ giải thích: phần bên trong alert()
được thực thi trước, hiển thị undefined
(vì nó không có bất kỳ tham số nào) và không trả về gì cả. Cảnh báo bên ngoài nhận giá trị trả về của cảnh báo bên trong - không có gì và cũng hiển thị undefined
trong hộp thông báo.
Hãy thử tất cả các trường hợp trên jsFiddle!
Ký hiệu chấm
Đây là cách tiếp cận chuẩn hơn, cho phép các thành viên của một đối tượng được truy cập bằng .
toán tử dot ( ). Đây là những gì mã của bạn sẽ trông giống như trong ký hiệu chấm:
alert('a'.toUpperCase())
Dễ đọc hơn nhiều. Vậy khi nào chúng ta nên sử dụng ký hiệu chấm và khi nào nên sử dụng ký hiệu dấu ngoặc?
So sánh
Sự khác biệt chính giữa hai phương pháp là ngữ nghĩa. Ngoài ra còn có một số chi tiết khác, nhưng tôi sẽ đến với những người trong một giây. Điều quan trọng nhất là những gì bạn thực sự muốn làm - một nguyên tắc nhỏ là bạn sử dụng ký hiệu chấm cho các trường và phương thức được thiết lập tốt, và ký hiệu dấu ngoặc khi bạn thực sự sử dụng đối tượng của mình làm bản đồ băm .
Một ví dụ tuyệt vời về lý do tại sao quy tắc này rất quan trọng có thể được hiển thị trong ví dụ của bạn - vì mã đang sử dụng ký hiệu dấu ngoặc ở nơi ký hiệu dấu chấm sẽ hợp lý hơn nhiều, nó làm cho mã khó đọc hơn. Và đó là một điều xấu, bởi vì mã được đọc nhiều lần hơn so với nó được viết .
Trong một số trường hợp, bạn phải sử dụng ký hiệu dấu ngoặc ngay cả khi sử dụng ký hiệu dấu chấm hợp lý hơn:
nếu một thành viên của một đối tượng có một tên chứa một hoặc nhiều khoảng trắng hoặc bất kỳ ký tự đặc biệt nào khác, bạn không thể sử dụng ký hiệu dấu chấm: foo.some method()
không hoạt động, nhưng foo["some method"]()
không;
nếu bạn cần truy cập động các thành viên của đối tượng, bạn cũng bị kẹt khi sử dụng ký hiệu dấu ngoặc;
Thí dụ:
for(var i = 0; i < 10; ++i) {
foo["method" + i]();
}
Điểm mấu chốt là bạn nên sử dụng cú pháp ngoặc khi sử dụng đối tượng làm bản đồ băm ( foods["burger"].eat()
) và cú pháp dấu chấm khi làm việc với các trường và phương thức "thực tế" ( enemy.kill()
). Với Javascript là một ngôn ngữ động, ranh giới giữa các trường "thực tế" và phương thức của một đối tượng và dữ liệu "khác" được lưu trữ bên trong có thể trở nên khá mờ. Nhưng miễn là bạn không trộn chúng theo những cách khó hiểu, bạn sẽ ổn thôi.
Bây giờ, vào phần còn lại của câu hỏi của bạn (cuối cùng !: P).
Làm thế nào tôi có thể chắc chắn phương pháp sẽ luôn là thành viên của obj
Bạn không thể. Thử nó. Cố gắng gọi derp
trên một chuỗi. Bạn sẽ gặp lỗi trong các dòng:
Uncaught TypeError: Object a has no method 'derp'
Đây là một hàm chung để gọi bất kỳ phương thức nào trên đối tượng BẤT K .. Nhưng điều đó có nghĩa là phương thức đã chỉ định sẽ là một thành viên ngầm định của đối tượng được chỉ định?
Vâng, trong trường hợp của bạn nó sẽ phải được. Nếu không, bạn kết thúc với lỗi tôi đã đề cập ở trên. Tuy nhiên, bạn không phải để sử dụng return obj[method]();
trong các callMethod()
chức năng. Bạn có thể thêm chức năng của riêng mình sau đó được sử dụng bởi chức năng bản đồ. Đây là một phương pháp được mã hóa cứng để biến tất cả các chữ cái thành một chữ cái viết hoa:
function makeCap()
{
return function(obj) {
return obj.toUpperCase();
}
}
var caps2 = map(['a', 'b', 'c'], makeCap()); // ['A','B','C']
console.log(caps2)
Mã trong hướng dẫn bạn liên kết để sử dụng các chức năng một phần . Bản thân chúng là một khái niệm khó khăn. Đọc thêm về chủ đề đó sẽ giúp làm cho mọi thứ rõ ràng hơn tôi có thể làm cho chúng.
Lưu ý: đây là mã của chức năng bản đồ được sử dụng bởi mã trong câu hỏi, nguồn ở đây .
function map(arr, iterator) {
var narr = [];
for (var i = 0; i < arr.length; i++) narr.push(iterator(arr[i], i));
return narr;
}
arr[5]
. Nếu số có tên định danh hợp lệ, bạn có thể sử dụng ký hiệu dấu chấm :arr.5
.