JavaScript에 "널 병합"연산자가 있습니까?


1381

Javascript에 null 통합 연산자가 있습니까?

예를 들어 C #에서는 다음과 같이 할 수 있습니다.

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

Javascript에 대해 알아낼 수있는 가장 좋은 근사는 조건부 연산자를 사용하는 것입니다.

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

어느 정도 icky IMHO입니다. 더 잘할 수 있습니까?


31
2018 년 노트 : x ?? y구문은 이제 1 단계 제안 상태- 무효 병합
— Aprillion

2
이 정확한 구문을 통합 한 Babel 플러그인 이 있습니다.
— Jonathan Sudiaman

10
2019 년 참고 사항 : 이제 3 단계 상태입니다!
— Daniel Schaffer

3
2020 년 1 월부터 참고 : Nullish 통합 연산자는 Firefox 72에서 기본적으로 제공되지만 옵션 체인 연산자는 여전히 사용할 수 없습니다.
— Kir Kanos

4
Nullish 통합 연산자 ( x ?? y) 및 선택적인 연결 연산자 ( user.address?.street)는 이제 4 단계입니다. 그 의미에 대한 자세한 설명은 다음과 같습니다. 2ality.com/2015/11/tc39-process.html#stage-4%3A-finished .
— Mass Dot Net

답변:


2133

최신 정보

JavaScript는 이제 nullish 통합 연산자 (??)를 지원합니다 . 왼쪽 피연산자가 null또는 undefined일 때 오른쪽 피연산자를 반환하고, 그렇지 않으면 왼쪽 피연산자를 반환합니다.

사용하기 전에 호환성을 확인하십시오.


C # Null 병합 연산자와 동등한 JavaScript?? ) 가 논리 OR ( ||)을 사용하고 있습니다 .

var whatIWant = someString || "Cookies!";

동작이 C #의 동작과 일치하지 않는 경우가 있지만 (아래에 명시되어 있음) JavaScript에서 기본 / 대체 값을 할당하는 일반적이고 간결한 방법입니다.


설명

첫 번째 피연산자의 유형에 관계없이 부울로 캐스팅하면 결과 false는 두 번째 피연산자를 사용합니다. 아래의 모든 경우에주의하십시오.

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

이것은 다음을 의미합니다.

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
"false", "undefined", "null", "0", "empty", "deleted"와 같은 문자열은 비어 있지 않은 문자열이므로 모두 참입니다.
— 약

4
이를 명확히해야합니다. ""는 null이 아니지만 허위로 간주됩니다. 따라서 null 값을 확인하고 ""인 경우이 테스트를 제대로 통과하지 못합니다.
— ScottKoon

99
주목할 점은 ||첫 번째 "truey"값 또는 마지막 "falsey"값 (아무것도 true로 평가할 수없는 경우)을 &&반환하고 반대의 방식으로 작동합니다 : 마지막 truey 값 또는 첫 번째 false 값 반환.
— Justin Johnson

19
참고로 여전히 관심이있는 사람에게는 유형의 생성자를 사용하여 선언하면 0과 빈 문자열이 null과 동일하게 평가됩니다. 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 || ''다시 떨어질 것이다 ''myObj로 또는 myObj.property 중 하나가 falsy 경우.
— 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

이 솔루션은 SQL 병합 기능과 같이 작동하며 여러 인수를 허용하며 값이없는 경우 널을 리턴합니다. C #처럼 동작합니다 ?? "", false 및 0은 NOT NULL로 간주되므로 실제 값으로 계산됩니다. 당신이 .net 배경에서 온다면, 이것이 가장 자연스러운 느낌의 해결책이 될 것입니다.


8
가 for(var i in arguments)에 따라, 반복 순서를 보장하지 않습니다 MDN . 배열에 JavaScript의 For… In 루프가 권장되지 않는 이유는 무엇입니까?를 참조하십시오 . 그리고 왜 배열 반복이 나쁜 아이디어 "에 대한 ..."사용? .
— MvG

13
이러한 늦은 추가에 대한 사과이지만,이 솔루션에는 단락 평가가 없다는 경고가 있습니다. 인수가 함수 호출이면 논리 OR 연산자의 동작과 다른 값이 리턴되는지 여부에 관계없이 모두 평가되므로 주목할 가치가 있습니다.
— 하라 빅

63

예, 곧옵니다. 참조 여기에 제안 하고 여기에 구현 상태를 .

다음과 같이 보입니다 :

x ?? y

예

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
이제 3 단계에 있으며 다음 TypeScript 릴리스를 계획했습니다! github.com/microsoft/TypeScript/issues/26578
— lautaro.dragan

1
Nullish 통합 연산자 ( x ?? y) 및 선택적인 연결 연산자 ( user.address?.street)는 이제 4 단계입니다. 그 의미에 대한 자세한 설명은 다음과 같습니다. 2ality.com/2015/11/tc39-process.html#stage-4%3A-finished .
— 매스 닷넷

45

만약 || 이야 'C 번호의 교체로 ??좋지 귀하의 경우 충분한, 그것은 빈 문자열과 0을 삼켜 때문에, 당신은 항상 당신의 자신의 기능을 쓸 수있다 :

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

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

1
alert (null || '')은 여전히 ​​빈 문자열을 경고하며 실제로 빈 문자열이 아닌 alert ( ''|| 'blah') 경고를 좋아한다고 생각합니다. (+1)
— Daniel Schaffer

1
필자는 실제로 falsenull / undefined를 true반환 하고 그렇지 않으면 논리 또는 많은 중첩 함수 호출보다 더 읽기 쉽습니다. 예를 들어 $N(a) || $N(b) || $N(c) || d보다 읽기 쉽다 $N($N($N(a, b), c), d).
— 밥

브렌트 라슨의 솔루션이 더 일반적입니다
— Assimilater

if .. return .. else ... return삼항에 대한 완벽한 경우입니다. return (value === null || value === void 0) ? ifnull : value;
— Alex McMillan

15

아무도 여기에 대한 잠재력을 언급하지 NaN않았습니다. 그래서 저는 2 센트를 더할 것이라고 생각했습니다.

주어진 코드의 경우 :

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

||연산자 를 사용하는 경우 첫 번째 거짓이 아닌 값을 얻습니다.

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

here 게시 된 일반적인 병합 방법을 사용하면 다음과 같은c 값을 얻습니다 .NaN

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

이것들 중 어느 것도 나에게 옳지 않은 것 같습니다. 당신의 세계와 다를 수있는 나의 작은 합체 논리 세계에서, 나는 정의되지 않은, null, NaN을 모두 "무시한"것으로 간주합니다. 그래서 다시 돌아올 것으로 기대합니다d 통합 방법에서 0 .

누군가의 뇌가 내 것과 같이 작동하고을 제외하고 싶다면 NaN이 방법으로 다음을 수행하십시오.

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;
}

코드를 최대한 짧게하고 명확성이 부족하지 않은 사람들을 위해 @impinball에서 제안한대로 사용할 수도 있습니다. 이것은 NaN이 NaN과 같지 않다는 사실을 이용합니다. 당신은 더 많은 것을 여기에서 읽을 수 있습니다 이유가 NaN 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;
}

모범 사례-인수를 배열과 같이 취급하고 NaN! == NaN ( typeof+ num.toString() === 'NaN'는 중복 임)을 활용하고 현재 인수를 대신 변수에 저장하십시오 arguments[i].
— Isiah Meadows

@impinball, 제안 된 편집이 작동하지 않으면 테스트 사례에서 0 대신 NaN을 반환합니다. 나는 기술적으로 제거 할 수 !== 'number'나는 이미 아니라고 평가 한 이후 검사를 null하거나 undefined,하지만이 코드 순서에 관계없이 작동 상태를 읽는 사람에게 매우 명확하다는 장점이있다. 다른 제안은 코드를 약간 단축하므로이를 사용하겠습니다.
— 케빈 넬슨

2
@impinball, 나는 당신이 그것을 왼쪽, 당신의 제안 편집에서 버그를 발견 arg !== arg,하지만 당신은 그것을 할 필요가 arg === arg다음 작동 .... 그러나 그것은 당신이하는 일에 대해 매우 명확하지 않다는 단점이 있습니다 ... 코드를 통과하고 arg === arg중복되는 것으로 생각되는 다음 사람에 의해 제거되지 않도록 코드에 주석이 필요합니다 ...하지만 그것을 넣을 것입니다 어쨌든.
— 케빈 넬슨

잘 잡았습니다. 그건 그렇고, NaN! == NaN 사실을 활용하여 NaN을 확인하는 빠른 방법입니다. 원하는 경우 설명 할 수 있습니다.
— Isiah Meadows

1
때는 isNaN () : "숫자가 아닌"확인 내장 기능을 대체 할 수
— Yury 코즐

5

JavaScript 고유의 null 정의에주의하십시오. 자바 스크립트에는 "값 없음"에 대한 두 가지 정의가 있습니다. 1. Null : 변수가 null이면 변수에 데이터가 포함되어 있지 않지만 변수가 이미 코드에 정의되어 있음을 의미합니다. 이처럼 :

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

이 경우 변수 유형은 실제로 Object입니다. 그것을 테스트하십시오.

window.alert(typeof myEmptyValue); // prints Object
  1. 정의되지 않음 : 변수가 코드에서 이전에 정의되지 않았으며 예상대로 값이 포함되지 않은 경우. 이처럼 :

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

그러한 경우 변수 유형은 '정의되지 않음'입니다.

형식 변환 비교 연산자 (==)를 사용하면 JavaScript는 이러한 빈 값 모두에 대해 동일하게 작동합니다. 이들을 구별하려면 항상 유형 엄격한 비교 연산자 (===)를 사용하십시오.


1
실제로 널은 값입니다. Object 유형의 특수한 값입니다. null로 설정되는 변수는 데이터를 포함하고 데이터는 null 객체에 대한 참조임을 의미합니다. 코드에서 변수를 정의되지 않은 값으로 정의 할 수 있습니다. 이것은 선언되지 않은 변수와 동일하지 않습니다.
— Ates Goral

선언되고있는 변수의 실제 차이 : alert (window.test) / * undefined * /; 경고 (창에서 "테스트") / * false * /; window.test = 정의되지 않음; 경고 (window.test) / * undefined * /; 경고 (창에서 "테스트") / * true * /; for (var p in window) {/ * p는 "test"* /} 일 수 있습니다
— Ates Goral

1
그러나 (비트 역설) 정의 되지 않은 값 으로 변수를 정의 할 수 있습니다var u = undefined;
— Serge

@AtesGoral re null입니다. 당신이 말을하는 것은 사실이지만, 관례 , "널 (null)"는 표현 "(유용한) 데이터의 부재"를 . 따라서 "데이터 없음"으로 간주됩니다. 그리고 이것이 "널 병합 연산자"에 관한 질문에 대한 답변이라는 것을 잊지 마십시오. 이러한 맥락에서 null은 내부적으로 표현되는 방법에 관계없이 "데이터 없음"으로 처리됩니다.
— ToolmakerSteve

4

설명을 읽은 후 @Ates Goral의 답변은 C #에서 수행하는 것과 동일한 작업을 JavaScript로 수행하는 방법을 제공합니다.

@Gumbo의 답변은 null을 확인하는 가장 좋은 방법을 제공합니다. 그러나 특히 JavaScript 확인 및 / 또는 문제 ==와 관련 ===하여 JavaScript 와의 차이점에 유의해야합니다.undefinednull .

여기 에 두 용어의 차이점에 대한 좋은 기사가 있습니다 . 기본적으로, ==대신에 를 사용하면 ===JavaScript가 비교중인 값을 통합 하고이 병합 후 비교 결과를 반환한다는 것을 이해하십시오 .


그 기사 (및 Jash)에 대해 나를 괴롭힌 한 가지는 정의되지 않은 window.hello 속성이 어떤 이유로 null로 평가된다는 것입니다. 대신 정의되지 않아야합니다. Firefox 오류 콘솔을 사용 해보고 직접 확인하십시오.
— Ates Goral

3

React의 create-react-app툴체인은 버전 3.3.0 (5.12.2019 릴리스) 이후 null 병합을 지원합니다 . 릴리스 정보에서 :

선택적 체인 및 Nullish Coalescing 연산자

우리는 이제 선택적인 chaining and nullish coalescing operator를 지원합니다!

// 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

이것은 create-react-app3.3.0 이상 을 사용하는 경우 이미 React 앱에서 이미 null-coalesce 연산자 를 사용할 수 있다고 말했습니다 .


3

예, 제안 은 4 단계 입니다. 이는 제안서가 공식 ECMAScript 표준에 포함될 준비가되었음을 의미합니다. 최신 데스크톱 버전의 Chrome, Edge 및 Firefox에서 이미 사용할 수 있지만이 기능이 브라우저 간 안정성에 도달 할 때까지 조금 더 기다려야합니다.

다음 예제를 통해 동작을 설명하십시오.

// 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}`);

이전 예는 다음과 같습니다.

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

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

참고 nullish 병합이 됩니다 하지 위협 falsy 있는 값 방식 ||운영자가 한 (그것은 단지에 대한 검사 undefined또는 null값), 따라서 같은 역할을합니다 다음 코드는 다음과 같습니다 :

// 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}`);


TypesScript 사용자의 경우 TypeScript 3.7부터이 기능을 사용할 수 있습니다.


2

2020 년 4 월 현재 제안 단계에 있기 때문에 곧 자바 스크립트로 제공 될 예정입니다. 호환성 및 지원에 대한 상태를 https://developer.mozilla.org/en-US/docs/Web/ 에서 모니터링 할 수 있습니다. 자바 스크립트 / 참조 / 운영자 / Nullish_coalescing_operator

Typescript를 사용하는 사람들 은 Typescript 3.7 의 nullish 통합 연산자 를 사용할 수 있습니다

문서에서-

이 기능 생각할 수 - ??연산자 - 기본 값을 "가을 다시"에 대한 방법을 다룰 때 같이 null나 undefined. 우리가 같은 코드를 작성할 때

let x = foo ?? bar();

이것은 값 foo이“존재할 때”사용될 것이라고 말하는 새로운 방법입니다 . 그러나 null또는 undefined일 때 bar()대신 계산하십시오 .


0

정답 확인

JavaScript로 존재합니까? 그렇습니다. 그러나. 현재 3 단계 에서 2020-02-06 현재 이며 아직 모든 곳에서 지원되지는 않습니다.아래 URL의 링크를 따라 "사양"및 "브라우저 호환성"헤더로 이동하여 자세한 정보를 확인하십시오.

인용 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator

Nullish 통합 연산자 (??)는 왼쪽 피연산자가 null이거나 정의되지 않은 경우 오른쪽 피연산자를 반환하고 그렇지 않으면 왼쪽 피연산자를 반환하는 논리 연산자입니다.

논리 OR (||) 연산자와 달리 왼쪽 피연산자가 Null이거나 정의되지 않은 잘못된 값이면 왼쪽 피연산자가 반환됩니다. 즉, ||를 사용하면 다른 변수 foo에 기본값을 제공하기 위해 잘못된 값을 사용 가능한 것으로 간주하면 (예 : ''또는 0) 예기치 않은 동작이 발생할 수 있습니다. 자세한 예는 아래를 참조하십시오.

예를 원하십니까? 내가 게시 한 링크를 따라 가십시오 .



MDN 링크는 도움이되지만 중복 된 답변입니다. 대신 vaughan 's answer 아래에 주석을 달아야합니다.
— 크리스

@ 크리스 그의 대답은 충분하지 않으므로 내 대답.
— Karl Morrison

0

이제 Chrome, Edge, Firefox, Safari 등과 같은 주요 브라우저의 최신 버전을 완벽하게 지원합니다. 다음은 null 연산자와 Nullish Coalescing Operator의 비교입니다.

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.