Tôi có thể đặt các biến thành không xác định hoặc chuyển không xác định làm đối số không?


304

Tôi hơi bối rối về các giá trị undefinedvà JavaScript null.

Những gì if (!testvar)thực sự làm? Nó kiểm tra cho undefinednullchỉ undefined?

Khi một biến được định nghĩa, tôi có thể xóa nó trở lại undefined(do đó xóa biến) không?

Tôi có thể vượt qua undefinednhư một tham số không? Ví dụ:

function test(var1, var2, var3) {

}

test("value1", undefined, "value2");

Câu trả lời:


514

Tôi hơi bối rối về Javascript không xác định & null.

Đừng nhầm lẫn về null. Nó thường có ý nghĩa và hành xử tương tự như các khái niệm ngôn ngữ kịch bản khác về các đối tượng ngoài luồng 'null', 'nil' hoặc 'Không'.

undefined, mặt khác, là một trò chơi JavaScript kỳ quặc. Đó là một đối tượng đơn lẻ đại diện cho các giá trị ngoài băng, về cơ bản là một thứ hai tương tự nhưng khác biệt null. Nó đi lên:

  1. Khi bạn gọi một hàm có ít đối số hơn danh sách đối số trong danh sách functioncâu lệnh, các đối số không được bỏ qua được đặt thành undefined. Bạn có thể kiểm tra điều đó với ví dụ:

    function dosomething(arg1, arg2) {
        if (arg2===undefined)
        arg2= DEFAULT_VALUE_FOR_ARG2;
        ...
    }

    Với phương pháp này, bạn không thể biết sự khác biệt giữa dosomething(1)dosomething(1, undefined); arg2sẽ có cùng giá trị trong cả hai. Nếu bạn cần nói sự khác biệt mà bạn có thể nhìn vào arguments.length, nhưng thực hiện các đối số tùy chọn như thế thường không dễ đọc.

  2. Khi một chức năng không có return value;, nó trả về undefined. Nói chung không cần sử dụng kết quả trả lại như vậy.

  3. Khi bạn khai báo một biến bằng cách có một var acâu lệnh trong một khối, nhưng chưa gán giá trị cho nó, thì đó là undefined. Một lần nữa, bạn không thực sự cần phải dựa vào điều đó.

  4. typeofToán tử ma quái trả về 'undefined'khi toán hạng của nó là một biến đơn giản không tồn tại, thay vì đưa ra một lỗi như thường xảy ra nếu bạn cố gắng tham chiếu đến nó. (Bạn cũng có thể cung cấp cho nó một biến đơn giản được gói trong ngoặc đơn, nhưng không phải là biểu thức đầy đủ liên quan đến biến không tồn tại.) Cũng không sử dụng nhiều cho điều đó.

  5. Đây là một trong những tranh cãi. Khi bạn truy cập vào một thuộc tính của một đối tượng không tồn tại, bạn sẽ không gặp lỗi ngay lập tức như mọi ngôn ngữ khác. Thay vào đó bạn có được một undefinedđối tượng. (Và sau đó khi bạn cố gắng sử dụng undefinedđối tượng đó sau này trong tập lệnh, nó sẽ sai theo một cách kỳ lạ, khó theo dõi hơn nhiều so với việc JavaScript vừa ném lỗi ngay lập tức.)

    Điều này thường được sử dụng để kiểm tra sự tồn tại của các thuộc tính:

    if (o.prop!==undefined) // or often as truthiness test, if (o.prop)
       ...do something...

    Tuy nhiên, vì bạn có thể gán undefinednhư bất kỳ giá trị nào khác:

    o.prop= undefined;

    điều đó không thực sự phát hiện liệu tài sản có ở đó một cách đáng tin cậy hay không. Tốt hơn là sử dụng intoán tử, không có trong phiên bản JavaScript gốc của Netscape, nhưng hiện có sẵn ở mọi nơi:

    if ('prop' in o)
        ...

Tóm lại, undefinedlà một mớ hỗn độn dành riêng cho JavaScript, khiến mọi người bối rối. Ngoài các đối số chức năng tùy chọn, trong đó JS không có cơ chế thanh lịch nào khác, undefinednên tránh. Nó không bao giờ nên là một phần của ngôn ngữ; nullsẽ chỉ hoạt động tốt đối với (2) và (3) và (4) là một hành vi sai trái chỉ tồn tại vì lúc đầu JavaScript không có ngoại lệ.

những gì if (!testvar)thực sự làm gì? Nó kiểm tra cho không xác định và null hoặc chỉ không xác định?

Như một 'truthiness' kiểm tra thử nghiệm chống lại false, undefined, null, 0, NaNvà chuỗi rỗng. Nhưng trong trường hợp này, vâng, nó thực sự undefinedđược quan tâm. IMO, cần nói rõ hơn về điều đó và nói if (testvar!==undefined).

một khi một biến được định nghĩa, tôi có thể xóa nó trở lại không xác định (do đó xóa biến).

Bạn chắc chắn có thể gán undefinedcho nó, nhưng điều đó sẽ không xóa biến. Chỉ có các delete object.propertynhà điều hành thực sự loại bỏ mọi thứ.

deletelà thực sự có nghĩa cho các thuộc tính chứ không phải là các biến như vậy. Các trình duyệt sẽ cho phép bạn thoát ra một cách thẳng thắn delete variable, nhưng đó không phải là một ý tưởng hay và sẽ không hoạt động trong chế độ nghiêm ngặt của ECMAScript Fifth Edition. Nếu bạn muốn giải phóng một tài liệu tham khảo đến một cái gì đó để nó có thể được thu gom rác, thì sẽ là bình thường hơn để nói variable= null.

Tôi có thể vượt qua không xác định như là một tham số?

Đúng.


10
Thật là một câu trả lời tuyệt vời. Tôi vừa thất bại trong bài kiểm tra JavaScript: perfectionkills.com/javascript-quiz Sau này tôi sẽ đọc lại câu trả lời của bạn và thử lại bài kiểm tra!
Skilldrick

1
cố định, ta. (Tôi có xu hướng không lo lắng quá nhiều về việc tái chỉ định, vì có rất nhiều điều mà một kịch bản có thể định nghĩa lại để làm rối tung mọi thứ mà trường hợp chung là không thể giải quyết.)
bobince

2
@bobince undefinedlà một đối tượng đơn lẻ? Ý anh là gì? Đó là một giá trị nguyên thủy, và không phải là một đối tượng.
Vidime Vidas

2
@ Độ cao: Đó là điểm (4). Tôi thường sẽ không typeof foo=='undefined'; nó có xu hướng được sử dụng cho (4a) đánh hơi toàn cầu, trong trường hợp đó tôi muốn nói rõ hơn và nói 'foo' in window, hoặc (4b) thử nghiệm đối với chính giá undefinedtrị, trong trường hợp tôi muốn đọc và nói foo===undefined. Trong thử nghiệm lý thuyết typeofchống lại 'undefined'có thể có một trường hợp sử dụng mà cấu trúc khác không thể cung cấp: đánh hơi cho sự tồn tại của các biến địa phương. Tuy nhiên, trong thực tế, bạn luôn biết những biến nào được khai báo cục bộ.
bobince

4
Một cảnh báo với # 2, thường là một hàm không có returncâu lệnh trả về undefined, nhưng nếu hàm đó là hàm tạo (được gọi với newtoán tử), nó sẽ trả về đối tượng mới (giá trị thisbên trong hàm tạo) mặc dù không có returncâu lệnh. console.log((function (){}()));trả lại undefined. console.log((new function (){}()));trả về một đối tượng
Mã vô dụng

18

Bạn không thể (không nên?) Định nghĩa bất cứ điều gì là không xác định, vì biến sẽ không còn được xác định nữa - bạn chỉ định nghĩa nó với một cái gì đó.

Bạn không thể (không nên?) Truyền undefinedđến một chức năng. Nếu bạn muốn vượt qua một giá trị trống, nullthay vào đó hãy sử dụng .

Câu lệnh if(!testvar)kiểm tra các giá trị boolean true / false, đặc biệt này kiểm tra xem có testvarđánh giá được không false. Theo định nghĩa nullundefinedkhông nên được đánh giá là truehoặc false, nhưng JavaScript đánh giá nullfalsevà đưa ra lỗi nếu bạn cố gắng đánh giá một biến không xác định.

Để kiểm tra đúng undefinedhoặc nullsử dụng:

if(typeof(testvar) === "undefined") { ... }

if(testvar === null) { ... }

1
Kiểm tra ba bằng cũng cho loại, vì vậy không có ép buộc loại được thực hiện. Douglas Crockford khuyên không nên sử dụng các toán tử ép buộc kiểu ( ==!=).
Skilldrick

3
Bạn có thể định nghĩa một cái gì đó là không xác định. var a= undefined. Bạn có thể vượt qua fn(undefined). Nếu bạn muốn tìm sự khác biệt giữa một pthuộc tính không xác định của một đối tượng ovà một thuộc tính pđã được xác định và đặt thành undefined, bạn phải sử dụng 'p' in otoán tử.
bobince

1
Có một lý do tại sao người ta không nên kiểm tra testvar === undefinedthay vì phức tạp hơn typeof(testvar) === "undefined"?
ddaa

4
Có một lý do chính đáng khác để sử dụng typeofthử nghiệm cho các biến không xác định: không giống như null, undefinedchỉ đơn giản là một thuộc tính của đối tượng toàn cầu và chính nó có thể được xác định lại. Nó chỉ có một kiểu mã hóa cụ thể và một dấu bằng bị thiếu và undefinedđược thay đổi âm thầm:if (undefined = someVar) {...}
Tim Down

1
@IanGrainger: ECMAScript 5 (được triển khai trong các phiên bản hiện tại của tất cả các trình duyệt) chủ yếu khắc phục điều này bằng cách tạo undefinedmột thuộc tính bất biến của đối tượng toàn cầu, vì vậy nó an toàn hơn trước đây. Tuy nhiên, vẫn có thể định nghĩa một biến có thể thay đổi được gọi undefinedtrong hàm, vì vậy vấn đề chưa hoàn toàn biến mất.
Tim Down

13

Sự khác biệt cơ bản là undefinednullđại diện cho các khái niệm khác nhau.

Nếu chỉ nullcó sẵn, bạn sẽ không thể xác định liệu nullđược đặt có chủ ý làm giá trị hay chưa giá trị chưa được đặt trừ khi bạn sử dụng bắt lỗi rườm rà: vd

var a;

a == null; // This is true
a == undefined; // This is true;
a === undefined; // This is true;

Tuy nhiên, nếu bạn cố tình đặt giá trị thành null, bình đẳng nghiêm ngặt với undefinedthất bại, do đó cho phép bạn phân biệt giữa nullundefinedgiá trị:

var b = null;
b == null; // This is true
b == undefined; // This is true;
b === undefined; // This is false;

Kiểm tra tài liệu tham khảo ở đây thay vì dựa vào những người bỏ qua những câu nói linh tinh như "Tóm lại, không xác định là một mớ hỗn độn dành riêng cho JavaScript, khiến mọi người bối rối". Chỉ vì bạn bối rối, điều đó không có nghĩa là nó là một mớ hỗn độn.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/und xác định

Hành vi này cũng không cụ thể cho JavaScript và nó hoàn thành các khái niệm tổng quát rằng một kết quả boolean có thể true, false, chưa biết ( null), không có giá trị ( undefined), hoặc một cái gì đó đã đi sai ( error).

http://en.wikipedia.org/wiki/Und xác_value


Và vẫn nullsẽ làm việc tốt. a == nulltruebởi vì kiểu ép buộc Javascript.
mộng du

11

Cách tốt nhất để kiểm tra giá trị null là

if ( testVar !== null )
{
    // do action here
}

và không xác định

if ( testVar !== undefined )
{
    // do action here
}

Bạn có thể chỉ định một avaritable với không xác định.

testVar = undefined;
//typeof(testVar) will be equal to undefined.

1
Cách tốt nhất để kiểm tra giá trị null là sử dụng !==, không phải!=
MBO

6

CÓ, bạn có thể, bởi vì không xác định được xác định là không xác định.

console.log(
   /*global.*/undefined === window['undefined'] &&
   /*global.*/undefined === (function(){})() &&
   window['undefined']  === (function(){})()
) //true

trường hợp của bạn:

test("value1", undefined, "value2")

bạn cũng có thể tạo biến không xác định của riêng mình:

Object.defineProperty(this, 'u', {value : undefined});
console.log(u); //undefined

5

Để trả lời câu hỏi đầu tiên của bạn, toán tử không ( !) sẽ ép buộc bất cứ điều gì nó được đưa vào một giá trị boolean. Vì vậy null, 0, false, NaN""(trống string) sẽ xuất hiện tất cả các sai.


Và cả chuỗi rỗng và NaN (Không phải là số)
MBO

undefinedsẽ không xuất hiện dưới dạng false, nó sẽ đưa ra lỗi 'không được xác định'.
Tatu Ulmanen

Tatu Ulmanen: không đúng sự thật. if (undefined) {/* Do stuff*/}sẽ không đưa ra lỗi, vì undefinedtồn tại như một thuộc tính của đối tượng toàn cầu. Điều gì sẽ gây ra lỗi là một cái gì đó nhưif (someUndeclaredVariable) {/* Do stuff*/}
Tim Down

2

JavaScript, cách đặt biến thành không xác định trên dòng lệnh:

Đặt một biến thành không xác định trong jsthiết bị đầu cuối dòng lệnh javascript đi kèm với Java trên Ubuntu 12.10.

el@defiant ~ $ js

js> typeof boo
"undefined"

js> boo
typein:2: ReferenceError: boo is not defined

js> boo=5
5

js> typeof boo
"number"

js> delete(boo)
true

js> typeof boo
"undefined"

js> boo
typein:7: ReferenceError: boo is not defined

Nếu bạn đặt một biến thành không xác định trong javascript:

Đặt cái này trong myjs.html:

<html>
<body>
    <script type="text/JavaScript">
        document.write("aliens: " + aliens);
        document.write("typeof aliens: " + (typeof aliens));
        var aliens = "scramble the nimitz";
        document.write("found some aliens: " + (typeof aliens));
        document.write("not sayings its aliens but... " + aliens);
        aliens = undefined;
        document.write("aliens deleted");
        document.write("typeof aliens: " + (typeof aliens));
        document.write("you sure they are gone? " + aliens);
    </script>
</body>
</html>

Nó in cái này:

aliens: undefined
typeof aliens: undefined
found some aliens: string
not sayings its aliens but... scramble the nimitz
aliens deleted
typeof aliens: undefined
you sure they are gone? undefined

CẢNH BÁO! Khi đặt biến của bạn thành không xác định, bạn đang đặt biến của mình thành một biến khác. Nếu một số người lén lút chạy undefined = 'rm -rf /';thì bất cứ khi nào bạn đặt biến của mình thành không xác định, bạn sẽ nhận được giá trị đó.

Bạn có thể tự hỏi làm thế nào tôi có thể xuất ra người ngoài hành tinh giá trị không xác định khi bắt đầu và nó vẫn chạy. Đó là do cẩu javascript: http://www.adequTHERgood.com/JavaScript-Scoping-and-Ho hiện.html


2

Thử cái này:

// found on UglifyJS
variable = void 0;

0

Các for if (something)if (!something)thường được sử dụng để kiểm tra nếu một cái gì đó được xác định hoặc không được xác định. Ví dụ:

if (document.getElementById)

Mã định danh được chuyển đổi thành giá trị boolean, do đó undefinedđược hiểu là false. Tất nhiên có các giá trị khác (như 0 và '') cũng được hiểu là false, nhưng định danh không nên có giá trị như vậy một cách hợp lý hoặc bạn hài lòng với việc xử lý giá trị đó giống như không xác định.

Javascript có một deletetoán tử có thể được sử dụng để xóa một thành viên của một đối tượng. Tùy thuộc vào phạm vi của một biến (tức là nó có toàn cầu hay không), bạn có thể xóa nó để làm cho nó không xác định.

Không có undefinedtừ khóa mà bạn có thể sử dụng như một nghĩa đen không xác định. Bạn có thể bỏ qua các tham số trong lệnh gọi hàm để làm cho chúng không được xác định, nhưng điều đó chỉ có thể được sử dụng bằng cách gửi ít tham số đến hàm, bạn không thể bỏ qua một tham số ở giữa.


0

Để cho vui, đây là một cách khá an toàn để gán "chưa gán" cho một biến. Để điều này xảy ra xung đột sẽ yêu cầu ai đó đã thêm vào nguyên mẫu cho Object có cùng tên với chuỗi được tạo ngẫu nhiên. Tôi chắc rằng trình tạo chuỗi ngẫu nhiên có thể được cải thiện, nhưng tôi chỉ lấy một từ câu hỏi này: Tạo chuỗi / ký tự ngẫu nhiên trong JavaScript

Điều này hoạt động bằng cách tạo một đối tượng mới và cố gắng truy cập một thuộc tính trên nó với một tên được tạo ngẫu nhiên, mà chúng tôi giả sử sẽ không tồn tại và do đó sẽ có giá trị không xác định.

function GenerateRandomString() {
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for (var i = 0; i < 50; i++)
        text += possible.charAt(Math.floor(Math.random() * possible.length));

    return text;
}

var myVar = {}[GenerateRandomString()];
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.