Có một toán tử lồng ghép null null trong JavaScript không?


1381

Có một toán tử hợp nhất null trong Javascript không?

Ví dụ: trong C #, tôi có thể làm điều này:

String someString = null;
var whatIWant = someString ?? "Cookies!";

Phép tính gần đúng nhất mà tôi có thể tìm ra cho Javascript là sử dụng toán tử có điều kiện:

var someString = null;
var whatIWant = someString ? someString : 'Cookies!';

Đó là IMHO sắp xếp. Tôi có thể làm tốt hơn không?


31
lưu ý từ 2018: x ?? yCú pháp hiện đang ở giai đoạn tình trạng 1 đề nghị - coalescing nullish
Aprillion

2
Hiện tại có một plugin Babel kết hợp cú pháp chính xác này.
Jonathan Sudiaman

10
Lưu ý từ năm 2019: bây giờ là trạng thái giai đoạn 3!
Daniel Schaffer

3
Lưu ý từ tháng 1 năm 2020: Toán tử kết hợp Nullish có sẵn trong Firefox 72 nhưng toán tử chuỗi tùy chọn vẫn không có.
Kir Kanos

4
Toán tử kết hợp nullish ( x ?? y) và toán tử chuỗi tùy chọn ( user.address?.street) hiện đều là Giai đoạn 4. Đây là một mô tả hay về điều đó có nghĩa là gì: 2ality.com/2015/11/tc39- process.html#stage-4%3A-finished .
Mass Dot Net

Câu trả lời:


2135

Cập nhật

JavaScript hiện hỗ trợ toán tử kết hợp nullish (??) . Nó trả về toán hạng bên phải của nó khi toán hạng bên trái của nó là nullhoặc undefined, và nếu không thì trả về toán hạng bên trái của nó.

Vui lòng kiểm tra tính tương thích trước khi sử dụng nó.


Tương đương JavaScript của toán tử hợp nhất C # null ( ??) đang sử dụng logic OR ( ||):

var whatIWant = someString || "Cookies!";

Có những trường hợp (được làm rõ bên dưới) rằng hành vi sẽ không khớp với C #, nhưng đây là cách chung chung, ngắn gọn để gán các giá trị mặc định / thay thế trong JavaScript.


Làm rõ

Bất kể loại toán hạng thứ nhất, nếu chuyển nó thành kết quả Boolean false, phép gán sẽ sử dụng toán hạng thứ hai. Cảnh giác với tất cả các trường hợp dưới đây:

alert(Boolean(null)); // false
alert(Boolean(undefined)); // false
alert(Boolean(0)); // false
alert(Boolean("")); // false
alert(Boolean("false")); // true -- gotcha! :)

Điều này có nghĩa là:

var whatIWant = null || new ShinyObject(); // is a new shiny object
var whatIWant = undefined || "well defined"; // is "well defined"
var whatIWant = 0 || 42; // is 42
var whatIWant = "" || "a million bucks"; // is "a million bucks"
var whatIWant = "false" || "no way"; // is "false"

48
Các chuỗi như "false", "không xác định", "null", "0", "trống", "đã xóa" đều đúng vì chúng là các chuỗi không trống.
một số

4
Điều này cần được làm rõ. "" không phải là null nhưng được xem là falsey. Vì vậy, nếu bạn đang kiểm tra một giá trị cho null và nó thực sự là "" thì nó sẽ không vượt qua bài kiểm tra này một cách chính xác.
ScottKoon

99
Đáng chú ý là ||trả về giá trị "thật" đầu tiên hoặc giá trị "falsey" cuối cùng (nếu không thể đánh giá là đúng) và &&hoạt động theo cách ngược lại: trả về giá trị trung thực cuối cùng hoặc giá trị falsey đầu tiên.
Justin Johnson

19
FYI cho bất kỳ ai vẫn quan tâm, chuỗi 0 và chuỗi rỗng được đánh giá giống như null nếu bạn sử dụng hàm tạo của kiểu để khai báo. var whatIWant = new Number(0) || 42; // is Number {[[PrimitiveValue]]: 0} var whatIWant = new String("") || "a million bucks"; // is String {length: 0, [[PrimitiveValue]]: ""}
Kevin Heidt

5
@LuisAntonioPestana var value = myObj && myObj.property || ''sẽ quay trở lại ''nếu myObj hoặc myObj.property là giả mạo.
Ates Goral

77
function coalesce() {
    var len = arguments.length;
    for (var i=0; i<len; i++) {
        if (arguments[i] !== null && arguments[i] !== undefined) {
            return arguments[i];
        }
    }
    return null;
}

var xyz = {};
xyz.val = coalesce(null, undefined, xyz.val, 5);

// xyz.val now contains 5

giải pháp này hoạt động giống như hàm hợp nhất SQL, nó chấp nhận bất kỳ số lượng đối số nào và trả về null nếu không có giá trị nào trong số chúng có giá trị. Nó hoạt động như C # ?? toán tử theo nghĩa "", false và 0 được coi là KHÔNG NULL và do đó được tính là giá trị thực. Nếu bạn đến từ một nền .net, đây sẽ là giải pháp cảm giác tự nhiên nhất.



13
Xin lỗi vì sự bổ sung muộn như vậy, nhưng tôi chỉ muốn lưu ý cho đầy đủ rằng giải pháp này có cảnh báo rằng nó không có đánh giá ngắn mạch; nếu các đối số của bạn là các lệnh gọi hàm thì tất cả chúng sẽ được đánh giá bất kể giá trị của chúng có được trả về hay không, khác với hành vi của toán tử OR logic, do đó, đáng chú ý.
Harastak

63

Vâng, nó sẽ đến sớm. Xem đề xuất ở đâytình trạng thực hiện ở đây .

Nó trông như thế này:

x ?? y

Thí dụ

const response = {
  settings: {
    nullValue: null,
    height: 400,
    animationDuration: 0,
    headerText: '',
    showSplashScreen: false
  }
};

const undefinedValue = response.settings?.undefinedValue ?? 'some other default'; // result: 'some other default'
const nullValue = response.settings?.nullValue ?? 'some other default'; // result: 'some other default'
const headerText = response.settings?.headerText ?? 'Hello, world!'; // result: ''
const animationDuration = response.settings?.animationDuration ?? 300; // result: 0
const showSplashScreen = response.settings?.showSplashScreen ?? true; // result: false

2
Bây giờ đang ở giai đoạn 3 và lên kế hoạch cho phiên bản TypeScript tiếp theo! github.com/microsoft/TypeScript/issues/26578
lautaro.dragan

1
Toán tử kết hợp nullish ( x ?? y) và toán tử chuỗi tùy chọn ( user.address?.street) hiện đều là Giai đoạn 4. Đây là một mô tả hay về điều đó có nghĩa là gì: 2ality.com/2015/11/tc39- process.html#stage-4%3A-finished .
Mass Dot Net

45

Nếu ||như một sự thay thế của C # ??không đủ tốt trong trường hợp của bạn, bởi vì nó nuốt các chuỗi và số 0 trống, bạn luôn có thể viết hàm của riêng mình:

 function $N(value, ifnull) {
    if (value === null || value === undefined)
      return ifnull;
    return value;
 }

 var whatIWant = $N(someString, 'Cookies!');

1
alert (null || '') vẫn cảnh báo một chuỗi trống và tôi nghĩ rằng tôi thực sự thích cảnh báo đó ('' || 'blah') cảnh báo blah chứ không phải là một chuỗi trống - mặc dù vậy cũng nên biết! (+1)
Daniel Schaffer

1
Tôi nghĩ rằng tôi thực sự có thể thích xác định một hàm trả về falsenếu (đúng) null / không xác định và mặt truekhác - sử dụng hàm đó với logic hoặc; nó có thể dễ đọc hơn nhiều lệnh gọi hàm lồng nhau. ví dụ như $N(a) || $N(b) || $N(c) || ddễ đọc hơn $N($N($N(a, b), c), d).
Bob

Giải pháp của Brent Larsen chung chung hơn
Assimilater

if .. return .. else ... returnlà trường hợp hoàn hảo cho một con chim nhạn. return (value === null || value === void 0) ? ifnull : value;
Alex McMillan

15

Không ai đã đề cập ở đây tiềm năng NaN, mà - đối với tôi - cũng là một giá trị null-ish. Vì vậy, tôi nghĩ rằng tôi sẽ thêm hai xu của mình.

Đối với mã đã cho:

var a,
    b = null,
    c = parseInt('Not a number'),
    d = 0,
    e = '',
    f = 1
;

Nếu bạn sử dụng ||toán tử, bạn sẽ nhận được giá trị không sai đầu tiên:

var result = a || b || c || d || e || f; // result === 1

Nếu bạn sử dụng phương thức hợp nhất điển hình, như được đăng ở đây , bạn sẽ nhận được c, có giá trị:NaN

var result = coalesce(a,b,c,d,e,f); // result.toString() === 'NaN'

Cả hai điều này có vẻ đúng với tôi. Trong thế giới logic hợp nhất nhỏ bé của riêng tôi, có thể khác với thế giới của bạn, tôi coi không xác định, null và NaN là tất cả đều là "null-ish". Vì vậy, tôi mong đợi sẽ lấy lại d(không) từ phương thức hợp nhất.

Nếu bộ não của bất cứ ai hoạt động như của tôi và bạn muốn loại trừ NaN, thì phương pháp này sẽ thực hiện điều đó:

function coalesce() {
    var i, undefined, arg;

    for( i=0; i < arguments.length; i++ ) {
        arg = arguments[i];
        if( arg !== null && arg !== undefined
            && (typeof arg !== 'number' || arg.toString() !== 'NaN') ) {
            return arg;
        }
    }
    return null;
}

Đối với những người muốn mã càng ngắn càng tốt và đừng ngại một chút thiếu rõ ràng, bạn cũng có thể sử dụng mã này theo đề xuất của @impinball. Điều này lợi dụng thực tế là NaN không bao giờ bằng NaN. Bạn có thể đọc thêm về điều đó ở đây: Tại sao NaN không bằng NaN?

function coalesce() {
    var i, arg;

    for( i=0; i < arguments.length; i++ ) {
        arg = arguments[i];
        if( arg != null && arg === arg ) { //arg === arg is false for NaN
            return arg;
        }
    }
    return null;
}

Thực tiễn tốt nhất - coi các đối số là giống như mảng, tận dụng NaN! == NaN ( typeof+ num.toString() === 'NaN'là dự phòng), lưu trữ đối số hiện tại trong biến thay vì arguments[i].
Isiah Meadows

@impinball, chỉnh sửa được đề xuất của bạn không hoạt động, nó trả về NaN thay vì 0 (không) từ trường hợp thử nghiệm của tôi. Về mặt kỹ thuật tôi có thể xóa !== 'number'séc vì tôi đã đánh giá rằng nó không nullhoặc undefined, nhưng điều này có lợi thế là rất rõ ràng cho bất kỳ ai đọc mã này và điều kiện sẽ hoạt động bất kể thứ tự. Các đề xuất khác của bạn làm rút ngắn mã một chút, vì vậy tôi sẽ sử dụng chúng.
Kevin Nelson

2
@impinball, tôi đã tìm thấy lỗi của bạn trong chỉnh sửa được đề xuất của bạn, bạn đã để nó như vậy arg !== arg, nhưng bạn cần nó là arg === arg... sau đó nó hoạt động. Tuy nhiên, điều đó có nhược điểm là không rõ ràng về những gì bạn đang làm ... yêu cầu nhận xét bằng mã để tránh bị xóa bởi người tiếp theo đi qua mã và nghĩ arg === arglà dư thừa ... nhưng tôi sẽ đưa nó lên dù sao.
Kevin Nelson

Nắm bắt tốt. Và nhân tiện, đó là một cách nhanh chóng để kiểm tra NaN lợi dụng thực tế NaN! == NaN. Nếu bạn muốn, bạn có thể giải thích điều đó.
Isiah Meadows

1
kiểm tra "không phải là số" có thể được thay thế bằng chức năng tích hợp: isNaN ()
Yury Kozlov

5

hãy cẩn thận với định nghĩa cụ thể của JavaScript về null. có hai định nghĩa cho "không có giá trị" trong javascript. 1. Null: khi một biến là null, có nghĩa là nó không chứa dữ liệu trong đó, nhưng biến đã được xác định trong mã. như thế này:

var myEmptyValue = 1;
myEmptyValue = null;
if ( myEmptyValue === null ) { window.alert('it is null'); }
// alerts

trong trường hợp như vậy, loại biến của bạn thực sự là Object. kiểm tra nó

window.alert(typeof myEmptyValue); // prints Object
  1. Không xác định: khi một biến chưa được xác định trước trong mã và như mong đợi, nó không chứa bất kỳ giá trị nào. như thế này:

    if ( myUndefinedValue === undefined ) { window.alert('it is undefined'); }
    // alerts

nếu trường hợp đó, loại biến của bạn là 'không xác định'.

lưu ý rằng nếu bạn sử dụng toán tử so sánh chuyển đổi loại (==), JavaScript sẽ hoạt động như nhau cho cả hai giá trị trống này. để phân biệt giữa chúng, luôn luôn sử dụng toán tử so sánh nghiêm ngặt loại (===).


1
Trên thực tế, null là một giá trị. Đó là một giá trị đặc biệt của loại Object. Một biến được đặt thành null có nghĩa là nó chứa dữ liệu, dữ liệu là tham chiếu đến đối tượng null. Một biến có thể được xác định với giá trị không xác định trong mã của bạn. Đây không giống như biến không được khai báo.
Ates Goral

Sự khác biệt thực tế giữa một biến được khai báo hay không: alert (window.test) / * không xác định * /; cảnh báo ("kiểm tra" trong cửa sổ) / * false * /; window.test = không xác định; cảnh báo (window.test) / * không xác định * /; cảnh báo ("kiểm tra" trong cửa sổ) / * true * /; for (var p in window) {/ * p có thể là "test" * /}
Ates Goral

1
tuy nhiên (một chút nghịch lý) bạn có thể xác định một biến có giá trị không xác địnhvar u = undefined;
Serge

@AtesGoral lại null. Mặc dù những gì bạn nói là đúng, theo quy ước , "null" đại diện cho "sự thiếu vắng dữ liệu (hữu ích)" . Do đó, nó được coi là "không có dữ liệu". Và đừng quên rằng đây là câu trả lời cho câu hỏi về "toán tử liên kết null"; trong bối cảnh này, null chắc chắn được coi là "không có dữ liệu" - bất kể nó được thể hiện như thế nào trong nội bộ.
ToolmakerSteve

4

Sau khi đọc phần làm rõ của bạn, câu trả lời của @Ates Goral cung cấp cách thực hiện cùng một thao tác bạn đang thực hiện trong C # trong JavaScript.

Câu trả lời của @ Gumbo cung cấp cách tốt nhất để kiểm tra null; tuy nhiên, điều quan trọng cần lưu ý là sự khác biệt ==so với ===JavaScript, đặc biệt là khi liên quan đến các vấn đề kiểm tra undefinedvà / hoặc null.

Có một bài viết thực sự hay về sự khác biệt trong hai thuật ngữ ở đây . Về cơ bản, hãy hiểu rằng nếu bạn sử dụng ==thay vì ===, JavaScript sẽ cố gắng kết hợp các giá trị bạn đang so sánh và trả về kết quả của việc so sánh sau khi kết hợp này.


Một điều khiến tôi bận tâm về bài viết đó (và Jash) là, một thuộc tính window.hello không xác định được đánh giá là null vì một số lý do. Nó nên được xác định thay thế. Hãy dùng thử bảng điều khiển lỗi Firefox và tự mình xem.
Ates Goral

3

Lưu ý rằng create-react-appchuỗi công cụ của React hỗ trợ quá trình kết hợp null kể từ phiên bản 3.3.0 (phát hành 5.12.2019) . Từ ghi chú phát hành:

Các nhà khai thác liên kết chuỗi và Nullish tùy chọn

Bây giờ chúng tôi hỗ trợ các toán tử kết hợp chuỗi và nullish tùy chọn!

// Optional chaining
a?.(); // undefined if `a` is null/undefined
b?.c; // undefined if `b` is null/undefined

// Nullish coalescing
undefined ?? 'some other default'; // result: 'some other default'
null ?? 'some other default'; // result: 'some other default'
'' ?? 'some other default'; // result: ''
0 ?? 300; // result: 0
false ?? true; // result: false

Điều này cho biết, trong trường hợp bạn sử dụng create-react-app3.3.0+, bạn có thể bắt đầu sử dụng toán tử hợp nhất null ngay hôm nay trong các ứng dụng React của mình.


3

Vâng, và đề xuất của nó là Giai đoạn 4 bây giờ. Điều này có nghĩa là đề xuất đã sẵn sàng để đưa vào tiêu chuẩn ECMAScript chính thức. Bạn đã có thể sử dụng nó trong các phiên bản Chrome, Edge và Firefox gần đây, nhưng chúng tôi sẽ phải chờ thêm một thời gian nữa cho đến khi tính năng này đạt được sự ổn định của trình duyệt chéo.

Hãy xem ví dụ sau để chứng minh hành vi của nó:

// note: this will work only if you're running latest versions of aforementioned browsers
const var1 = undefined;
const var2 = "fallback value";

const result = var1 ?? var2;
console.log(`Nullish coalescing results in: ${result}`);

Ví dụ trước tương đương với:

const var1 = undefined;
const var2 = "fallback value";

const result = (var1 !== null && var1 !== undefined) ?
    var1 :
    var2;
console.log(`Nullish coalescing results in: ${result}`);

Lưu ý rằng coalescing nullish sẽ không đe dọa falsy giá trị cách ||điều hành đã làm (nó chỉ kiểm tra cho undefinedhay nullgiá trị), vì thế mà đoạn sau sẽ hoạt động như sau:

// note: this will work only if you're running latest versions of aforementioned browsers
const var1 = ""; // empty string
const var2 = "fallback value";

const result = var1 ?? var2;
console.log(`Nullish coalescing results in: ${result}`);


Đối với người dùng TypeScript, bắt đầu từ TypeScript 3.7 , tính năng này hiện cũng có sẵn.


2

Hy vọng nó sẽ sớm xuất hiện trong Javascript, vì nó đang trong giai đoạn đề xuất kể từ tháng 4 năm 2020. Bạn có thể theo dõi trạng thái ở đây để tương thích và hỗ trợ - https://developer.mozilla.org/en-US/docs/Web/ JavaScript / Tham khảo / Toán tử / Nullish_coalescing_operator

Đối với những người sử dụng Bản mô tả, bạn có thể sử dụng toán tử kết hợp nullish từ Bản mô tả 3.7

Từ các tài liệu -

Bạn có thể nghĩ về tính năng này - ??nhà điều hành - như một cách để đưa rơi trở lại giá trị mặc định khi giao dịch với nullhoặc undefined. Khi chúng ta viết mã như

let x = foo ?? bar();

Đây là một cách mới để nói rằng giá trị foosẽ được sử dụng khi nó hiện tại ra; nhưng khi nó nullhoặc undefined, tính toán bar()ở vị trí của nó.


0

Ok một câu trả lời thích hợp

Nó có tồn tại trong JavaScript không? Vâng, nó làm. NHƯNG. Hiện tại, nó là vào năm 2020 / 02-06 tại Giai đoạn 3 và chưa được hỗ trợ ở mọi nơi. Theo liên kết trong URL bên dưới và đi đến tiêu đề "Thông số kỹ thuật" và "Tương thích trình duyệt" để biết thêm thông tin về vị trí của nó.

Trích dẫn từ: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator

Toán tử hợp nhất nullish (??) là toán tử logic trả về toán hạng bên phải của nó khi toán hạng bên trái của nó là null hoặc không xác định, và nếu không thì trả về toán hạng bên trái của nó.

Trái với toán tử OR (||) logic, toán hạng bên trái được trả về nếu đó là giá trị giả không phải là null hoặc không xác định. Nói cách khác, nếu bạn sử dụng | | để cung cấp một số giá trị mặc định cho một biến foo khác, bạn có thể gặp các hành vi không mong muốn nếu bạn coi một số giá trị giả là có thể sử dụng được (ví dụ: '' hoặc 0). Xem bên dưới để biết thêm ví dụ.

Muốn có ví dụ? Theo liên kết tôi đã đăng, nó có tất cả mọi thứ.



Liên kết MDN rất hữu ích nhưng đây là một câu trả lời trùng lặp. Thay vào đó, bạn nên bình luận dưới câu trả lời của vaughan.
Chris

@Chris Câu trả lời của anh ấy không đủ, vì vậy câu trả lời của tôi.
Karl Morrison

0

Giờ đây, nó đã hỗ trợ đầy đủ trong phiên bản mới nhất của các trình duyệt chính như Chrome, Edge, Firefox, Safari, v.v ... Đây là so sánh giữa toán tử null và Toán tử hợp nhất Nullish

const response = {
        settings: {
            nullValue: null,
            height: 400,
            animationDuration: 0,
            headerText: '',
            showSplashScreen: false
        }
    };
    /* OR Operator */
    const undefinedValue = response.settings.undefinedValue || 'Default Value'; // 'Default Value'
    const nullValue = response.settings.nullValue || 'Default Value'; // 'Default Value'
    const headerText = response.settings.headerText || 'Hello, world!'; //  'Hello, world!'
    const animationDuration = response.settings.animationDuration || 300; //  300
    const showSplashScreen = response.settings.showSplashScreen || true; //  true
    /* Nullish Coalescing Operator */
    const undefinedValue = response.settings.undefinedValue ?? 'Default Value'; // 'Default Value'
    const nullValue = response.settings.nullValue ?? ''Default Value'; // 'Default Value'
    const headerText = response.settings.headerText ?? 'Hello, world!'; // ''
    const animationDuration = response.settings.animationDuration ?? 300; // 0
    const showSplashScreen = response.settings.showSplashScreen ?? true; //  false
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.