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.7nullish 통합 연산자 를 사용할 수 있습니다

문서에서-

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

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.