자바 스크립트에서 undefined 7 가지 팁
본문
약 8 년 전에 JavaScript를 배우기 시작했을 때, 빈약한 값을 나타내는 undefined와 null이 존재한다는 기괴한 상황이었습니다.
그들 사이의 명확한 차이점은 무엇입니까?
둘 다 빈 값을 정의하는 것 같으며, null == undefined 비교는 true로 평가됩니다.
Ruby, Python 또는 Java와 같은 대부분의 최신 언어에는 단일 null 값 (nil 또는 null)이 있으며 이는 합리적인 접근 방식입니다.
https://dmitripavlutin.com/7-tips-to-handle-undefined-in-javascript/
JavaScript의 경우 인터프리터는 아직 초기화되지 않은 변수 또는 객체 속성에 액세스 할 때 undefined를 반환합니다.
예를 들면 다음과 같습니다.
let company;
company; // => undefined
let person = { name: 'John Smith' };
person.age; // => undefined
다른 한편으로 null은 누락된 객체 참조를 나타냅니다.
JavaScript 자체는 변수 또는 객체 속성을 null로 설정하지 않습니다.
String.prototype.match()와 같은 일부 고유 메소드는 누락 된 오브젝트를 표시하기 위해 널을 리턴 할 수 있습니다.
샘플을 살펴보십시오.
let array = null;
array; // => null
let movie = { name: 'Starship Troopers', musicBy: null };
movie.musicBy; // => null
'abc'.match(/[0-9]/); // => null
JavaScript의 허용 특성으로 인해 개발자는 초기화되지 않은 값에 액세스하려는 유혹을 받습니다. 나도 그런 나쁜 연습에 유죄입니다.
이러한 위험한 작업으로 인해 정의되지 않은 관련 오류가 발생하여 스크립트 번개가 빨리 종료됩니다. 관련된 일반적인 오류 메시지는 다음과 같습니다.
- TypeError : 'undefined'는 함수가 아닙니다
- TypeError : undefined '<prop-name>'속성을 읽을 수 없습니다
- 그리고 type errors 같은.
JavaScript 개발자는 이 농담의 아이러니를 이해할 수 있습니다.
function undefined() {
// problem solved
}
이러한 오류의 위험을 줄이려면 undefined가 생성 된 경우를 이해해야 합니다. 더 중요한 것은 모양을 억제하고 응용 프로그램 내에서 확산되어 코드 내구성을 높입니다.
undefined 탐색과 코드 안전에 미치는 영향에 대해 자세히 살펴 보겠습니다.
1. undefined?
JavaScript에는 6 가지 기본 유형이 있습니다.
- Boolean: true or false
- Number: 1, 6.7, 0xFF
- String: "Gorilla and banana"
- Symbol: Symbol("name") (starting ES2015)
- Null: null
- Undefined: undefined.
분리 된 객체 유형 : {name : "Dmitri"}, [ "apple", "orange"].
6 개의 기본 유형에서 undefined는 자체 유형이 Undefined 인 특수 값입니다. ECMAScript 사양에 따르면 :
Undefined 값 기본 값은 변수에 값이 지정되지 않은 경우 사용됩니다.
이 표준은 초기화 되지 않은 변수, 존재하지 않는 객체 속성, 존재하지 않는 배열 요소 등에 액세스 할 때 정의되지 않은 값을 받는다는 것을 명확하게 정의합니다. 예를 들어 :
let number;
number; // => undefined
let movie = { name: 'Interstellar' };
movie.year; // => undefined
let movies = ['Interstellar', 'Alexander'];
movies[3]; // => undefined
위의 예는 다음에 액세스하는 방법을 보여줍니다.
- an uninitialized variable number
- a non-existing object property movie.year
- or a non-existing array element movies[3]
undefined로 평가됩니다.
ECMAScript 사양은 undefined 값의 유형을 정의합니다.
undefined 유형은 유일한 값이 undefined 값인 유형입니다.
이런 의미에서 typeof 연산자는 undefined 값에 대해 'undefined'문자열을 반환합니다.
typeof undefined === 'undefined'; // => true
물론 typeof는 변수에 undefined 값이 포함되어 있는지 확인하는 데 효과적입니다.
let nothing;
typeof nothing === 'undefined'; // => true
2. undefined을 만드는 일반적인 시나리오
2.1 초기화되지 않은 변수
아직 값이 지정되지 않은 (초기화되지 않은) 선언 된 변수는 기본적으로 undefined입니다.
평범하고 간단한 :
let myVariable;
myVariable; // => undefined
myVariable이 선언되었지만 아직 값이 지정되지 않았습니다. 변수에 액세스하면 undefined로 평가됩니다.
초기화되지 않은 변수의 문제를 해결하기 위한 효율적인 접근 방법은 가능할 때마다 초기 값을 지정하는 것입니다. 초기화되지 않은 상태의 변수가 적을수록 좋습니다. 이상적으로 선언 직후에 값을 할당하는 것이 좋습니다 const myVariable = '초기 값'이지만 항상 가능한 것은 아닙니다.
팁 1 : const를 선호하고, 그렇지 않으면 let을 사용하지만 var에 작별 인사를 하십시오.
제 생각에 ECMAScript 2015의 가장 큰 특징 중 하나는 const와 let을 사용하여 변수를 선언하는 새로운 방법입니다. 큰 발전입니다. const와 let은 블록 범위가 지정되고 (이전 함수 범위가 var과는 달리) 선언 행까지 임시 데드 존에 존재합니다.
변수가 한 번 영원히 값을 받으면 const 선언을 사용하는 것이 좋습니다. 불변의 바인딩을 작성합니다.
const의 멋진 기능 중 하나는 const myVariable = 'initial'변수에 초기 값을 할당해야 한다는 것입니다. 변수는 초기화되지 않은 상태에 노출되지 않으며 정의되지 않은 액세스는 단순히 불가능합니다.
단어가 회문인지 여부를 확인하는 기능을 확인해 보겠습니다.
function isPalindrome(word) {
const length = word.length;
const half = Math.floor(length / 2);
for (let index = 0; index < half; index++) {
if (word[index] !== word[length - index - 1]) {
return false;
}
}
return true;
}
isPalindrome('madam'); // => true
isPalindrome('hello'); // => false
길이 및 반 변수에는 값이 한 번 할당됩니다. 이러한 변수는 변경되지 않으므로 const로 선언하는 것이 합리적입니다.
변수를 리 바인드 해야 하는 경우 (즉, 여러 번 할당) let 선언을 적용하십시오. 가능할 때마다 초기 값을 즉시 할당하십시오 (예 : 인덱스 = 0으로하자.
올드 스쿨 var는 어떻습니까? ES2015의 관점에서, 나는 그것을 사용하지 않는 것이 좋습니다.
var 선언 문제는 전체 함수 범위에서 변수 게양입니다. 함수 범위의 끝에 어딘가에 var 변수를 선언 할 수 있지만 선언하기 전에 액세스 할 수 있습니다. 그러면 undefined 값이 표시됩니다.
function bigFunction() {
// code...
myVariable; // => undefined
// code...
var myVariable = 'Initial value';
// code...
myVariable; // => 'Initial value'
}
bigFunction();
myVariable에 액세스 할 수 있으며 선언 행 앞에도 undefined 내용이 포함됩니다. var myVariable = '초기 값'.
반대로, let (const 포함) 변수는 선언 행 전에 액세스 할 수 없습니다. 변수가 선언 전에 일시적인 데드 존에 있기 때문에 발생합니다. undefined 항목에 액세스 할 기회가 적기 때문에 좋습니다.
var 대신에 let으로 업데이트 된 위의 예제는 임시 데드 존의 변수에 액세스 할 수 없으므로 ReferenceError를 발생시킵니다.
function bigFunction() {
// code...
myVariable; // => Throws 'ReferenceError: myVariable is not defined'
// code...
let myVariable = 'Initial value';
// code...
myVariable; // => 'Initial value'
}
bigFunction();
불변 바인딩에 const 사용을 장려하거나 초기화되지 않은 변수의 모양을 줄이는 방법을 보장합니다.
팁 2 : 응집력 향상
Cohesion은 모듈의 요소 (네임 스페이스, 클래스, 메소드, 코드 블록)가 함께 속하는 정도를 나타냅니다. 응집력의 측정은 일반적으로 높은 응집력 또는 낮은 응집력으로 기술된다.
단일 작업에만 집중할 수 있도록 모듈 요소를 설계 할 것을 권장하기 때문에 높은 응집력이 바람직합니다. 모듈을 만듭니다.
- Focused and understandable: 모듈이 하는 일을 이해하기 쉽게
- Maintainable and easier to refactor: 모듈의 변화는 더 적은 수의 모듈에 영향을 미칩니다
- Reusable: 단일 작업에 집중함으로써 모듈을 보다 쉽게 재사용 할 수 있습니다.
- Testable:단일 작업에 중점을 둔 모듈을 쉽게 테스트 할 수 있습니다.
느슨한 결합을 수반하는 높은 응집력은 잘 설계된 시스템의 특성입니다.
코드 블록 자체는 작은 모듈로 간주 될 수 있습니다. 높은 응집력의 이점을 활용하려면 변수를 사용하는 코드 블록에 변수를 최대한 가깝게 유지해야 합니다.
예를 들어 변수가 블록 범위의 논리를 형성하기 위해 존재하는 경우 변수를 선언하고 변수가 해당 블록 내에서만 작동하도록 허용합니다 (const 또는 let 선언 사용). 외부 블록은 이 변수에 신경 쓰지 않아야 하므로 이 변수를 외부 블록 범위에 노출 시키지 마십시오.
불필요하게 연장 된 변수 수명의 전형적인 예는 함수 내부의 사이클 사용입니다.
function someFunc(array) {
var index, item, length = array.length;
// some code...
// some code...
for (index = 0; index < length; index++) {
item = array[index];
// some code...
}
return 'some result';
}
인덱스, 항목 및 길이 변수는 함수 본문의 시작 부분에 선언됩니다. 그러나 끝 부분에서만 사용됩니다. 그렇다면 그러한 접근 방식의 문제점은 무엇입니까?
변수 선언문의 맨 위 선언과 사용법 사이의 모든 방법은 초기화되지 않고 정의되지 않은 항목에 노출됩니다. 전체 기능 범위에서 수명이 부적절하게 길다.
더 좋은 방법은 이러한 변수를 가능한 한 사용 위치에 가깝게 옮기는 것입니다.
function someFunc(array) {
// some code...
// some code...
const length = array.length;
for (let index = 0; index < length; index++) {
const item = array[index];
// some
}
return 'some result';
}
인덱스 및 항목 변수는 for 문의 블록 범위에만 있습니다. 외부의 의미는 없습니다.
길이 변수도 그 사용처에 가깝게 선언됩니다.
수정 된 버전이 초기 버전보다 나은 이유는 무엇입니까?
- 변수는 초기화되지 않은 상태에 노출되지 않으므로 undefined에 액세스 할 위험이 없습니다
- 변수를 사용 위치에 최대한 가깝게 이동하면 코드 가독성이 향상됩니다.
- 응집력이 높은 코드 덩어리는 리팩토링하기 쉽고 필요한 경우 별도의 기능으로 추출
2.2 존재하지 않는 자산에 액세스
존재하지 않는 객체 속성에 액세스하면 JavaScript가 undefined 상태로 반환됩니다.
예를 들어 설명하겠습니다.
let favoriteMovie = {
title: 'Blade Runner'
};
favoriteMovie.actors; // => undefined
favoriteMovie는 단일 속성 제목을 가진 객체입니다. 속성 접근자를 사용하여 존재하지 않는 속성 액터에 액세스하면 favoriteMovie.actors 속성이 정의되지 않은 것으로 평가됩니다.
존재하지 않는 속성에 액세스해도 오류가 발생하지 않습니다. 존재하지 않는 속성 값에서 데이터를 가져 오려고 할 때 실제 문제가 나타납니다. 이것은 가장 일반적인 정의되지 않은 관련 트랩으로, 잘 알려진 오류 메시지 TypeError : undefined의 <prop> 속성을 읽을 수 없습니다.
TypeError throw를 설명하기 위해 이전 코드 스니펫을 약간 수정 해 보겠습니다.
let favoriteMovie = {
title: 'Blade Runner'
};
favoriteMovie.actors[0];
// TypeError: Cannot read property '0' of undefined
favoriteMovie에는 속성 액터가 없으므로 favoriteMovie.actors는 undefined 로 평가됩니다.
결과적으로 favoriteMovie.actors[0] 표현식을 사용하여 undefined은 값의 첫 번째 항목에 액세스하면 TypeError가 발생합니다.
존재하지 않는 속성에 액세스 할 수 있는 JavaScript의 허용 특성은 혼동의 원인입니다. 속성이 설정되거나 설정되지 않을 수 있습니다. 이 문제를 우회하는 이상적인 방법은 개체가 항상 보유하고 있는 속성을 정의하도록 제한하는 것입니다.
불행히도 종종 개체를 제어 할 수 없습니다. 이러한 개체는 다양한 시나리오에서 다른 속성 집합을 가질 수 있습니다. 따라서 이 모든 시나리오를 수동으로 처리해야 합니다.
새로운 요소의 배열의 시작과 끝에 추가하는 함수 append (array, toAppend)를 구현해 봅시다. toAppend 매개 변수는 특성이 있는 오브젝트를 승인합니다.
- first : 배열의 시작 부분에 삽입 된 요소
- last : 배열의 끝에 삽입 된 요소.
이 함수는 원래 배열을 변경하지 않고 새 배열 인스턴스를 반환합니다 (예 : 순수한 함수).
순진한 append()의 첫 번째 버전은 다음과 같습니다.
function append(array, toAppend) {
const arrayCopy = array.slice();
if (toAppend.first) {
arrayCopy.unshift(toAppend.first);
}
if (toAppend.last) {
arrayCopy.push(toAppend.last);
}
return arrayCopy;
}
append([2, 3, 4], { first: 1, last: 5 }); // => [1, 2, 3, 4, 5]
append(['Hello'], { last: 'World' }); // => ['Hello', 'World']
append([8, 16], { first: 4 }); // => [4, 8, 16]
toAppend 객체는 첫 번째 속성이나 마지막 속성을 생략 할 수 있으므로 이러한 속성이 toAppend에 존재하는지 확인 해야 합니다.
속성이 없는 경우 속성 접근자는 정의되지 않은 것으로 평가합니다. 첫 번째 또는 마지막 속성이 있는지 확인하려는 첫 번째 유혹은 정의되지 않은 속성에 대해 확인하는 것입니다. if (toAppend.first) {} 및 if (toAppend.last) {}…를 조건부로 확인하겠습니다.
그렇게 빠르지 않습니다. 이 방법에는 단점이 있습니다. 정의되지 않았으며 false, null, 0, NaN 및 ''는 잘못된 값입니다.
append()의 현재 구현에서 이 함수는 잘못된 요소를 삽입 할 수 없습니다.
append([10], { first: 0, last: false }); // => [10]
0과 거짓은 거짓입니다. if (toAppend.first) {} 및 if (toAppend.last) {}가 실제로 거짓과 비교되기 때문에 이러한 요소는 배열에 삽입되지 않습니다. 이 함수는 수정하지 않고 초기 배열 [10]을 반환합니다.
다음 팁은 속성 존재를 올바르게 확인하는 방법을 설명합니다.
팁 3 : property 존재를 확인
다행히도 JavaScript는 객체에 특정 속성이 있는지 확인하는 여러 가지 방법을 제공합니다.
- obj.prop !== undefined: undefined와 직접 비교
- typeof obj.prop !== 'undefined': 특성 값 유형을 확인하십시오.
- obj.hasOwnProperty('prop'): 객체에 자체 속성이 있는지 확인
- 'prop' in obj: 객체에 고유 한 속성이 있는지 상속 된 속성이 있는지 확인
내 추천은 연산자로 사용하는 것입니다. 짧고 달콤한 구문이 있습니다. 연산자가 있으면 실제 속성 값에 액세스하지 않고 개체에 특정 속성이 있는지 여부를 명확하게 확인할 수 있습니다.
obj.hasOwnProperty ( 'prop')도 훌륭한 솔루션입니다. 연산자보다 약간 길며 개체의 자체 속성에서만 확인합니다.
undefined와 비교하는 두 가지 방법이 효과적 일 수 있습니다 ...하지만 obj.prop! == undefined and typeof obj.prop! == 'undefined'는 장황하고 이상하게 보이며 직접 처리하는 의심 경로에 노출되는 것으로 보입니다. 미정.
in 연산자를 사용하여 append (array, toAppend) 기능을 개선해 보겠습니다.
function append(array, toAppend) {
const arrayCopy = array.slice();
if ('first' in toAppend) {
arrayCopy.unshift(toAppend.first);
}
if ('last' in toAppend) {
arrayCopy.push(toAppend.last);
}
return arrayCopy;
}
append([2, 3, 4], { first: 1, last: 5 }); // => [1, 2, 3, 4, 5]
append([10], { first: 0, last: false }); // => [0, 10, false]
toAppend의 'first'(toAppend의 'last')는 해당 속성이 존재하는지 여부에 관계없이 true이고, 그렇지 않으면 false입니다.
in 연산자를 사용하면 거짓 요소 0과 거짓을 삽입 할 때 발생하는 문제가 해결됩니다. 이제 [10]의 시작과 끝에 이러한 요소를 추가하면 예상 결과 [0, 10, false]가 생성됩니다.
팁 4 : 객체 속성에 액세스하도록 구조화
객체 속성에 액세스 할 때 속성이 존재하지 않는 경우 기본값을 표시해야 하는 경우가 있습니다.
삼항 연산자와 함께 사용하여 다음을 수행 할 수 있습니다.
const object = { };
const prop = 'prop' in object ? object.prop : 'default';
prop; // => 'default'
확인할 속성 수가 증가하면 삼항 연산자 구문의 사용이 어려워집니다. 각 속성에 대해 기본값을 처리하기 위해 새로운 코드 줄을 만들어야 유사한 유사 삼항 연산자의 벽이 늘어납니다.
보다 우아한 접근 방식을 사용하기 위해 객체 파괴라는 훌륭한 ES2015 기능에 대해 알아 보겠습니다.
객체 파괴를 통해 객체 속성 값을 변수로 직접 인라인 추출하고 속성이 존재하지 않는 경우 기본값을 설정할 수 있습니다. undefined를 직접 처리하지 않는 편리한 구문입니다.
실제로 속성 추출은 짧고 의미 있게 보입니다.
const object = { };
const { prop = 'default' } = object;
prop; // => 'default'
작동하는 것을 보기 위해 문자열을 따옴표로 묶는 유용한 함수를 정의 해 봅시다. quote (subject, config)는 첫 번째 인수를 줄 바꿈 할 문자열로 받아들입니다. 두 번째 인수 구성은 속성이 있는 객체입니다.
- char: 따옴표 문자 (예 : '(작은 따옴표) 또는 "(큰 따옴표). 기본값은"입니다.
- skipIfQuoted:문자열이 이미 인용 된 경우 인용을 건너 뛸 부울 값 기본값은 true입니다.
객체 파괴의 이점을 적용하면서 quote()를 구현해 봅시다.
function quote(str, config) {
const { char = '"', skipIfQuoted = true } = config;
const length = str.length;
if (skipIfQuoted
&& str[0] === char
&& str[length - 1] === char) {
return str;
}
return char + str + char;
}
quote('Hello World', { char: '*' }); // => '*Hello World*'
quote('"Welcome"', { skipIfQuoted: true }); // => '"Welcome"'
const {char = ' "', skipIfQuoted = true} = 한 줄로 구성을 할당 해제하면 구성 객체에서 char 및 skipIfQuoted 속성이 추출됩니다. 구성 오브젝트에서 일부 특성을 사용할 수 없는 경우, 구조 지정 지정에서 기본값은 char에 대해서는 "" ', skipIfQuoted에 대해서는 false를 설정합니다.
다행히도 이 함수는 여전히 개선의 여지가 있습니다.
파괴 할당을 매개 변수 섹션으로 바로 옮기겠습니다. 그리고 기본 설정이 충분할 때 두 번째 인수를 건너 뛰려면 config 매개 변수의 기본값 (빈 오브젝트 {})을 설정하십시오.
function quote(str, { char = '"', skipIfQuoted = true } = {}) {
const length = str.length;
if (skipIfQuoted
&& str[0] === char
&& str[length - 1] === char) {
return str;
}
return char + str + char;
}
quote('Hello World', { char: '*' }); // => '*Hello World*'
quote('Sunny day'); // => '"Sunny day"'
소멸 할당은 함수 서명의 구성 매개 변수를 대체합니다. 나는 그것을 좋아한다 : quote ()는 한 줄 더 짧아진다. destructuring assignment의 오른쪽에 = {}를 사용하면 두 번째 인수가 모든 quote ( 'Sunny day')에 지정되지 않은 경우 빈 개체가 사용됩니다.
객체 파괴는 객체에서 속성 추출을 효율적으로 처리하는 강력한 기능입니다. 액세스 된 속성이 존재하지 않을 때 반환 될 기본값을 지정할 수 있는 가능성이 마음에 듭니다. 결과적으로 정의되지 않은 처리 및 처리와 관련된 문제점을 피할 수 있습니다.
팁 5 : 기본 속성으로 객체 채우기
소멸 할당과 같이 모든 속성에 변수를 만들 필요가 없는 경우 일부 속성이 누락 된 개체는 기본값으로 채워질 수 있습니다.
ES2015 Object.assign (target, source1, source2, ...)은 열거 가능한 모든 자체 속성 값을 하나 이상의 소스 객체에서 대상 객체로 복사합니다. 이 함수는 대상 객체를 반환합니다.
예를 들어, 항상 전체 속성 세트를 포함하지는 않는 unsafeOptions 객체의 속성에 액세스 해야 합니다.
unsafeOptions에서 존재하지 않는 속성에 액세스 할 때 정의되지 않은 것을 피하려면 다음과 같이 조정 해 보겠습니다.
- 기본 특성 값을 보유하는 오브젝트 기본값을 정의하십시오.
- Object.assign ({}, 기본값, unsafeOptions)을 호출하여 새 객체 옵션을 만듭니다. 새 객체는 unsafeOptions에서 모든 속성을 수신하지만 누락 된 속성은 기본값에서 가져옵니다.
const unsafeOptions = {
fontSize: 18
};
const defaults = {
fontSize: 16,
color: 'black'
};
const options = Object.assign({}, defaults, unsafeOptions);
options.fontSize; // => 18
options.color; // => 'black'
unsafeOptions에는 fontSize 속성 만 포함되어 있습니다. defaults 객체는 fontSize 및 color 속성의 기본값을 정의합니다.
Object.assign()은 첫 번째 인수를 대상 객체 {}로 사용합니다. 대상 객체는 unsafeOptions 소스 객체에서 fontSize 속성 값을받습니다. unsafeOptions는 색상을 포함하지 않기 때문에 기본 소스 객체의 색상 속성 값도 있습니다.
소스 객체가 열거되는 순서는 중요합니다. 나중에 소스 객체 속성이 이전 객체를 덮어 씁니다.
이제 unsafeOptions에서 처음 사용할 수 없었던 options.color를 포함하여 options 객체의 모든 속성에 액세스 할 수 있습니다.
다행히도 기본 속성으로 객체를 채우는 더 쉽고 가벼운 방법이 있습니다. 객체 초기화 프로그램에서 속성을 확산 시킬 수 있는 새로운 JavaScript 기능 (현재 3 단계)을 사용하는 것이 좋습니다.
Object.assign () 호출 대신, 오브젝트 스프레드 구문을 사용하여 소스 오브젝트에서 모든 고유하고 열거 가능한 특성을 대상 오브젝트에 복사하십시오.
const unsafeOptions = {
fontSize: 18
};
const defaults = {
fontSize: 16,
color: 'black'
};
const options = {
...defaults,
...unsafeOptions
};
options.fontSize; // => 18
options.color; // => 'black'
객체 이니셜 라이저는 기본값 및 unsafeOptions 소스 객체의 속성을 분산 시킵니다. 소스 객체가 지정된 순서는 중요합니다. 나중에 소스 객체 속성이 이전 객체를 덮어 씁니다.
불완전한 객체를 기본 속성 값으로 채우는 것은 코드를 안전하고 내구성 있게 만드는 효율적인 전략입니다. 상황에 관계없이 개체에는 항상 전체 속성 집합이 포함되어 있으며 정의되지 않은 항목을 생성 할 수 없습니다.
보너스 팁 : 무효 병합
nullish coalescing (2019 년 8 월 3 단계 제안)이라는 새 연산자는 피연산자가 정의되지 않았거나 null 인 경우 기본값으로 평가됩니다.
const value = nullOrUndefinedValue ?? defaultValue;
Nullish 통합 연산자는 객체 속성에 액세스하는 것이 편리하지만 이 속성이 undefined거나 null 인 경우 기본값이 있습니다.
const styles = {
fontSize: 18
};
styles.color ?? 'black'; // => 'black'
styles.fontSize ?? 16; // => 18
styles 객체에는 속성 색상이 없으므로 styles.color 속성 접근자가 정의되지 않습니다. styles.color ?? 'black'은 기본값 'black'으로 평가됩니다.
styles.fontSize는 18이므로 Null이 없는 병합 연산자는 속성 값 18로 평가됩니다.
2.3 기능 매개 변수
함수 매개 변수는 암시적으로 기본적으로 undefined로 설정됩니다.
일반적으로 특정 개수의 매개 변수로 정의 된 함수는 동일한 개수의 인수로 호출해야 합니다. 이러한 경우 매개 변수는 예상 값을 얻습니다.
function multiply(a, b) {
a; // => 5
b; // => 3
return a * b;
}
multiply(5, 3); // => 15
multiply (5, 3)를 호출하면 매개 변수 a와 b가 해당 5와 3 값을 받습니다. 곱셈은 예상대로 계산됩니다 : 5 * 3 = 15.
호출에 대한 인수를 생략하면 어떻게 됩니까? 함수 내부의 파라미터는 undefined니다.
하나의 인수로 함수를 호출하여 이전 예제를 약간 수정 해 보겠습니다.
function multiply(a, b) {
a; // => 5
b; // => undefined
return a * b;
}
multiply(5); // => NaN
함수 곱하기 (a, b) {}는 두 개의 매개 변수 a와 b로 정의됩니다. multiply (5) 호출은 단일 인수로 수행됩니다. 결과적으로 a 매개 변수는 5이지만 b 매개 변수는 undefined니다.
팁 6 : 기본 매개 변수 값 사용
때때로 함수는 호출시 전체 인수 세트를 필요로 하지 않습니다. 값이 없는 매개 변수의 기본값을 간단히 설정할 수 있습니다.
이전 예제를 다시 생각해 보자. b 매개 변수가 undefined 경우 기본값 2가 지정됩니다.
function multiply(a, b) {
if (b === undefined) {
b = 2;
}
a; // => 5
b; // => 2
return a * b;
}
multiply(5); // => 10
이 함수는 단일 인수 multiply (5)로 호출됩니다. 초기에 매개 변수는 2이고 b는 undefined입니다.
조건문은 b가 undefined인지 검증합니다. 이 경우 b = 2 대입이 기본값을 설정합니다.
제공된 기본값을 지정하는 방법이 효과가 있지만 undefined과 직접 비교하는 것은 좋지 않습니다. 장황하고 해킹처럼 보입니다.
더 좋은 방법은 ES2015 기본 매개 변수 기능을 사용하는 것입니다. 짧고 표현력이 있으며 undefined과 직접 비교하지 않습니다.
b의 기본 매개 변수를 사용하여 이전 예제를 수정하면 실제로 좋아 보입니다.
function multiply(a, b = 2) {
a; // => 5
b; // => 2
return a * b;
}
multiply(5); // => 10
multiply(5, undefined); // => 10
함수 시그니처의 b = 2는 b가 undefined 경우 매개 변수의 기본값은 2입니다.
ES2015 기본 매개 변수 기능은 직관적이고 표현력이 있습니다. 선택적 매개 변수의 기본값을 설정하려면 항상이 매개 변수를 사용하십시오.
2.4 함수 반환 값
암시적으로 return 문이 없으면 JavaScript 함수는 undefined를 반환합니다.
JavaScript에서 return 문이 없는 함수는 암시 적으로 undefined를 반환합니다.
function square(x) {
const res = x * x;
}
square(2); // => undefined
square() 함수는 계산 결과를 반환하지 않습니다. 함수 호출 결과가 undefined입니다.
return 문이 있지만 근처에 표현식이 없는 경우에도 동일한 상황이 발생합니다.
function square(x) {
const res = x * x;
return;
}
square(2); // => undefined
반환; statement가 실행되지만 식을 반환하지 않습니다. 호출 결과도 undefined입니다.
물론, 리턴 할 표현식을 거의 리턴으로 표시하면 예상대로 작동합니다.
function square(x) {
const res = x * x;
return res;
}
square(2); // => 4
이제 함수 호출은 4로 평가되는데, 이는 2 제곱입니다.
팁 7 : 자동 세미콜론 삽입을 신뢰하지 마십시오
JavaScript의 다음 명령문 목록은 세미콜론 (;)으로 끝나야합니다.
- empty statement
- let, const, var, import, export declarations
- expression statement
- debugger statement
- continue statement, break statement
- throw statement
- return statement
위의 설명 중 하나를 사용하는 경우 끝에 세미콜론을 표시하십시오.
function getNum() {
// Notice the semicolons at the end
let num = 1;
return num;
}
getNum(); // => 1
let 선언과 return 문이 끝나면 의무적 인 세미콜론이 작성됩니다.
세미콜론을 표시하지 않으려면 어떻게 됩니까? 예를 들어 소스 파일의 크기를 줄입니다.
이러한 상황에서 ECMAScript는 누락 된 세미콜론을 삽입하는 ASI (Automatic Semicolon Insertion) 메커니즘을 제공합니다.
ASI의 도움을 받아 이전 예제에서 세미콜론을 제거 할 수 있습니다.
function getNum() {
// Notice that semicolons are missing
let num = 1
return num
}
getNum() // => 1
위의 텍스트는 유효한 JavaScript 코드입니다. 누락 된 세미콜론이 자동으로 삽입됩니다.
언뜻 보기에 그것은 유망한 것으로 보입니다. ASI 메커니즘을 사용하면 불필요한 세미콜론을 건너 뛸 수 있습니다. JavaScript 코드를 작고 읽기 쉽게 만들 수 있습니다.
ASI가 만든 작지만 성가신 함정이 하나 있습니다. 개행 문자가 return과 반환 된 식 return \ n 식 사이에 있으면 ASI는 개행 문자 반환 전에 세미콜론을 자동으로 삽입합니다. \ n 식.
함수 내부에서 리턴한다는 것은 무엇을 의미합니까? 성명서? 이 함수는 undefined를 반환합니다. ASI의 메커니즘을 자세히 모르면 예기치 않게 반환 된 undefined가 잘못된 것입니다.
예를 들어, getPrimeNumbers() 호출의 반환 값을 살펴 보겠습니다.
function getPrimeNumbers() {
return
[ 2, 3, 5, 7, 11, 13, 17 ]
}
getPrimeNumbers() // => undefined
return 문과 배열 리터럴 식 사이에는 줄 바꿈이 있습니다. JavaScript는 반환 후 세미콜론을 자동으로 삽입하여 코드를 다음과 같이 해석합니다.
function getPrimeNumbers() {
return;
[ 2, 3, 5, 7, 11, 13, 17 ];
}
getPrimeNumbers(); // => undefined
statement는 반환합니다. getPrimeNumbers() 함수가 예상 배열 대신 undefined를 리턴하도록 합니다.
리턴과 배열 리터럴 사이의 개행을 제거하면 문제가 해결됩니다.
function getPrimeNumbers() {
return [
2, 3, 5, 7, 11, 13, 17
];
}
getPrimeNumbers(); // => [2, 3, 5, 7, 11, 13, 17]
이러한 상황을 피하기 위해 Automatic Semicolon Insertion이 정확히 어떻게 작동하는지 연구하는 것이 좋습니다.
물론, return과 return 식 사이에 개행 문자를 넣지 마십시오.
2.5 void 연산자
void <expression>은 표현식을 평가하고 평가 결과에 관계없이 undefined를 반환합니다.
void 1; // => undefined
void (false); // => undefined
void {name: 'John Smith'}; // => undefined
void Math.min(1, 3); // => undefined
void 연산자의 사용 사례 중 하나는 평가의 부작용에 따라 표현식 평가를 정의되지 않은 상태로 억제하는 것입니다.
3. 배열에서 undefined
범위를 벗어난 인덱스로 배열 요소에 액세스 할 때 정의되지 않습니다.
const colors = ['blue', 'white', 'red'];
colors[5]; // => undefined
colors[-1]; // => undefined
색상 배열에는 3 개의 요소가 있으므로 유효한 인덱스는 0, 1 및 2입니다. 인덱스 5 및 -1에는 배열 요소가 없으므로 접근 자 색상 [5] 및 색상 [-1]은 undefined입니다.
JavaScript에서는 소위 희소 배열이 발생할 수 있습니다. 이들은 공백이 있는 배열입니다. 즉, 일부 색인에서는 요소가 undefined입니다.
희소 배열 내부에 빈 공간 (일명 빈 슬롯)에 액세스하면 undefined 값도 얻게 됩니다.
다음 예제는 희소 배열을 생성하고 빈 슬롯에 액세스 하려고 합니다.
const sparse1 = new Array(3);
sparse1; // => [<empty slot>, <empty slot>, <empty slot>]
sparse1[0]; // => undefined
sparse1[1]; // => undefined
const sparse2 = ['white', ,'blue']
sparse2; // => ['white', <empty slot>, 'blue']
sparse2[1]; // => undefined
sparse1은 숫자로 된 첫 번째 인수로 Array 생성자를 호출하여 생성됩니다. 빈 슬롯이 3 개 있습니다.
sparse2는 누락 된 두 번째 요소가 있는 배열 리터럴로 작성됩니다. 빈 공간에 액세스하는 이러한 희소 배열 중 하나에서 undefined로 평가됩니다.
배열로 작업 할 때 undefined catch를 피하려면 유효한 배열 인덱스를 사용하고 sparse 배열을 만들지 마십시오.
4. undefined와 null의 차이점
합리적인 질문이 나타납니다 : undefined와 null의 주요 차이점은 무엇입니까? 두 특수 값 모두 빈 상태를 의미합니다.
가장 큰 차이점은 undefined는 아직 초기화되지 않은 변수의 값을 나타내고 null은 의도적으로 객체가 없음을 나타냅니다.
몇 가지 예의 차이점을 살펴 보겠습니다.
그러나 변수 번호가 정의되어 있지만 초기 값이 지정되지 않았습니다.
let number;
number; // => undefined
숫자 변수는 undefined으며 초기화되지 않은 변수를 명확하게 나타냅니다.
존재하지 않는 객체 속성에 액세스 할 때 초기화되지 않은 동일한 개념이 발생합니다.
const obj = { firstName: 'Dmitri' };
obj.lastName; // => undefined
lastName 속성이 obj에 없기 때문에 JavaScript는 obj.lastName을 undefined로 올바르게 평가합니다.
다른 경우에는 변수가 객체 또는 객체를 반환하는 함수를 보유 할 것으로 예상한다는 것을 알고 있습니다. 그러나 어떤 이유로 든 객체를 인스턴스화 할 수 없습니다. 이러한 경우 null은 누락 된 객체를 나타내는 의미 있는 지표입니다.
예를 들어 clone()은 일반 JavaScript 객체를 복제하는 함수입니다. 이 함수는 객체를 반환 할 것으로 예상됩니다 :
function clone(obj) {
if (typeof obj === 'object' && obj !== null) {
return Object.assign({}, obj);
}
return null;
}
clone({name: 'John'}); // => {name: 'John'}
clone(15); // => null
clone(null); // => null
그러나 clone ()은 객체가 아닌 인수 15 또는 null (또는 일반적으로 기본 값인 null 또는 undefined)을 사용하여 호출 할 수 있습니다. 이 경우 함수는 복제본을 만들 수 없으므로 누락 된 객체의 지표 인 null을 반환합니다.
typeof 연산자는 두 값을 구별합니다.
typeof undefined; // => 'undefined'
typeof null; // => 'object'
엄격한 품질 연산자 ===는 undefined와 null을 올바르게 구분합니다.
let nothing = undefined;
let missingObject = null;
nothing === missingObject; // => false
5. 결론
undefined 존재는 다음을 사용할 수 있는 JavaScript의 허용 특성의 결과입니다.
- 초기화되지 않은 변수
- 존재하지 않는 객체 속성 또는 메서드
- 배열 요소에 액세스 하기 위한 범위를 벗어난 인덱스
- 아무것도 돌려주지 않는 함수의 호출 결과
undefined지만 권장되지 않는 방법에 의존하기 때문에 대부분 정의되지 않은 것과 직접 비교하는 것은 나쁜 습관입니다.
효율적인 전략은 코드에서undefined 키워드의 모양을 최소한 줄이는 것입니다. 그 사이에 항상 잠재적 인 외모를 놀라운 방식으로 기억하고 다음과 같은 유익한 습관을 적용하여 이를 방지하십시오.
- 초기화되지 않은 변수의 사용을 줄입니다
- 변수 수명 주기를 짧고 사용 소스에 가깝게 만듭니다.
- 가능할 때마다 변수에 초기 값을 할당하십시오
- const 선호, 그렇지 않으면 let 사용
- 중요하지 않은 함수 매개 변수에 기본값 사용
- 속성이 있는지 확인하거나 안전하지 않은 개체를 기본 속성으로 채 웁니다.
- sparse 배열의 사용을 피하십시오
- 이전글meSpeak.js 2.0 발표 19.08.23
- 다음글JavaScript의 객체 레스트 / 스프레드 속성에 대한 쉬운 안내서 19.08.22