“Var FOO = FOO || {} ”(Gán một biến hoặc một đối tượng trống cho biến đó) nghĩa là gì trong Javascript?


99

Nhìn vào một mã nguồn trực tuyến, tôi bắt gặp điều này ở đầu một số tệp nguồn.

var FOO = FOO || {};
FOO.Bar = …;

Nhưng tôi không biết || {}phải làm gì .

Tôi biết {}là bằng new Object()và tôi nghĩ ||là cho một cái gì đó như "nếu nó đã tồn tại, hãy sử dụng giá trị của nó, khác sử dụng đối tượng mới.

Tại sao tôi lại thấy phần này ở đầu tệp nguồn?


Lưu ý: Câu hỏi đã được chỉnh sửa để phản ánh rằng đây là mẫu mã thường thấy ở đầu các tệp nguồn Javascript.
Robert Harvey

Câu trả lời:


153

Dự đoán của bạn về mục đích || {}là khá gần.

Mẫu cụ thể này khi nhìn thấy ở đầu tệp được sử dụng để tạo không gian tên , tức là một đối tượng được đặt tên theo đó các hàm và biến có thể được tạo mà không làm ô nhiễm quá mức đối tượng chung.

Lý do tại sao nó được sử dụng là vì nếu bạn có hai (hoặc nhiều) tệp:

var MY_NAMESPACE = MY_NAMESPACE || {};
MY_NAMESPACE.func1 = {
}

var MY_NAMESPACE = MY_NAMESPACE || {};
MY_NAMESPACE.func2 = {
}

cả hai đều chia sẻ cùng một không gian tên nên không quan trọng thứ tự hai tệp được tải, bạn vẫn nhận được func1func2xác định chính xác bên trong MY_NAMESPACEđối tượng một cách chính xác.

Tệp đầu tiên được tải sẽ tạo raMY_NAMESPACE đối tượng ban đầu và bất kỳ tệp nào được tải sau đó sẽ tăng thêm đối tượng.

Một cách hữu ích, điều này cũng cho phép tải không đồng bộ các tập lệnh chia sẻ cùng một không gian tên có thể cải thiện thời gian tải trang. Nếu các <script>thẻ có bộ deferthuộc tính, bạn không thể biết chúng sẽ được diễn giải theo thứ tự nào, vì vậy, như được mô tả ở trên, cách này cũng khắc phục sự cố đó.


2
Chính xác là như vậy, có một số file js có khai báo giống hệt nhau lúc đầu, cảm ơn nhiều!
Ricardo Sanchez

41
+1 để đọc giữa các dòng và giải thích lý do làm điều đó. Sẽ luôn tốt khi ai đó đưa ra câu trả lời mà người dùng thực sự muốn hơn là chỉ câu mà anh ta yêu cầu. :)
Spudley

1
tôi muốn nói đó là # ifndef / # define cho javascript :)
Darren Kopp

1
||cũng là thực sự hữu ích khi bạn muốn cung cấp đối số tùy chọn và khởi tạo chúng để mặc định nếu không được cung cấp:function foo(arg1, optarg1, optarg2) { optarg1 = optarg1 || 'default value 1'; optarg2 = optart2 || 'defalt value 2';}
crazy2be

1
@ crazy2be mà không hoạt động nếu mặc định là truthy, nhưng giá trị falsey cũng là hợp pháp, kể từ khi ||nhà điều hành không thể nói undefinedtừ falsey.
Alnitak

23
var AEROTWIST = AEROTWIST || {};

Về cơ bản, dòng này nói rằng hãy đặt AEROTWISTbiến thành giá trị của AEROTWISTbiến hoặc đặt nó thành một đối tượng trống.

Dấu ngoặc kép ||là một câu lệnh OR và phần thứ hai của OR chỉ được thực thi nếu phần đầu tiên trả về false.

Do đó, nếu AEROTWISTđã có một giá trị, nó sẽ được giữ như giá trị đó, nhưng nếu nó chưa được đặt trước đó, thì nó sẽ được đặt là một đối tượng rỗng.

về cơ bản nó giống như nói điều này:

if(!AEROTWIST) {var AEROTWIST={};}

Hy vọng rằng sẽ giúp.


1
thực sự là phạm vi sẽ là tốt trong ví dụ cuối cùng của bạn vì JS không có phạm vi khối
Alnitak

@Alnitak - meh, bạn nói đúng; Gần đây, tôi đã làm việc với việc đóng cửa quá nhiều và tôi đã quên những điều cơ bản. Tôi sẽ chỉnh sửa câu trả lời.
Spudley

6

Một cách sử dụng phổ biến khác cho || cũng là đặt giá trị mặc định cho một tham số hàm không xác định:

function display(a) {
  a = a || 'default'; // here we set the default value of a to be 'default'
  console.log(a);
}

// we call display without providing a parameter
display(); // this will log 'default'
display('test'); // this will log 'test' to the console

Tương tự trong các chương trình khác thường là:

function display(a = 'default') {
  // ...
}

Bạn không cần phải varở phía trước a, ađi vào bối cảnh thực hiện của chức năng như một tham số chính thức , do đó nó đã được công bố.
Fabrício Matté

6

Có hai phần chính var FOO = FOO || {};bao gồm.

# 1 Ngăn chặn ghi đè

Hãy tưởng tượng bạn có mã của mình được chia thành nhiều tệp và đồng nghiệp của bạn cũng đang làm việc trên một Đối tượng được gọi FOO. Sau đó, nó có thể dẫn đến trường hợp ai đó đã xác định FOOvà gán chức năng cho nó (như một skateboardhàm). Sau đó, bạn sẽ ghi đè nó, nếu bạn không kiểm tra xem nó đã tồn tại chưa.

Trường hợp có vấn đề:

// Definition of co-worker "Bart" in "bart.js"
var FOO = {};

FOO.skateboard = function() {
  alert('I like skateboarding!');
};

// Definition of co-worker "Homer" in "homer.js"
var FOO = {};

FOO.donut = function() {
  alert('I like donuts!');
};

Trong trường hợp này, skateboardhàm sẽ biến mất nếu bạn tải tệp JavaScript homer.jssau bart.jstrong HTML của mình vì Homer định nghĩa một FOOđối tượng mới (và do đó ghi đè đối tượng hiện có từ Bart) để nó chỉ biết về donuthàm.

Vì vậy, bạn cần sử dụng var FOO = FOO || {};có nghĩa là “FOO sẽ được gán cho FOO (nếu nó đã tồn tại) hoặc một đối tượng trống mới (nếu FOO chưa tồn tại).

Giải pháp:

var FOO = FOO || {};

// Definition of co-worker Bart in bart.js
FOO.skateboard = function() {
  alert('I like skateboarding!');
};

// Definition of co-worker Homer in homer.js
var FOO = FOO || {};

FOO.donut = function() {
  alert('I like donuts!');
};

Bởi vì Bart và Homer tại đang kiểm tra sự tồn tại của FOOtrước khi họ xác định phương pháp của họ, bạn có thể tải bart.jshomer.jstrong bất kỳ thứ tự mà không trọng phương pháp của nhau (nếu họ có tên gọi khác nhau). Vì vậy, bạn sẽ luôn nhận được một FOOđối tượng có các phương thức skateboarddonut(Yay!).

# 2 Xác định một đối tượng mới

Nếu bạn đã đọc qua ví dụ đầu tiên thì bây giờ bạn đã biết mục đích của nó là gì || {}.

Bởi vì nếu không có FOOđối tượng hiện có thì trường hợp OR sẽ hoạt động và tạo ra một đối tượng mới, vì vậy bạn có thể gán các chức năng cho nó. Giống:

var FOO = {};

FOO.skateboard = function() {
  alert('I like skateboarding!');
};

3

Nếu không có giá trị nào trong AEROTWIST hoặc là giá trị rỗng hoặc không được xác định, giá trị được gán cho AEROTWIST mới sẽ là {} (một đối tượng trống)


1

Các ||nhà điều hành có hai giá trị:

a || b

Nếu a là true , nó sẽ trả về a. Nếu không, nó sẽ trở lại b.

Các giá trị falsy là null, undefined, 0, "", NaNfalse. Các giá trị trung thực là mọi thứ khác.

Vì vậy, nếu achưa được thiết lập (là nó undefined) nó sẽ trở lại b.


Tôi không chắc sự thậtgiả dối nên được duy trì như những lời nói thực tế. Vui, nhưng không chính xác tiêu chuẩn. :-)
Đánh bạc

4
@Orbling chúng khá thường được sử dụng để nói về các giá trị như vậy trong JS.
Alnitak

+1 để mô tả toán tử chính xác, vì nó không phải là toán tử logic. Đôi khi nó được gọi là "toán tử mặc định".
Tim Büthe

@Tim Sự khác biệt duy nhất giữa ||trong JS (và Perl) và phiên bản trong C, C ++ và Java là JS không truyền kết quả thành boolean. Nó vẫn là một toán tử logic.
Alnitak

@Alnitak: Có thể là do nền tảng không chuyên nghiệp của các nhà phát triển JS trong quá khứ.
Chơi bạc

-1

Lưu ý rằng trong một số phiên bản IE, mã này sẽ không hoạt động như mong đợi. Bởi vì var, biến được định nghĩa lại gán như vậy - nếu tôi nhớ chính xác vấn đề - thì cuối cùng bạn sẽ luôn có một đối tượng mới. Điều đó sẽ khắc phục sự cố:

var AEROTWIST;
AEROTWIST = AEROTWIST || {};
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.