javascript+es6

[ javascript ] 19. Object , JSON, Spread연산자, 나머지연산자, 옵셔널 체이닝

변쌤(이젠강남) 2023. 11. 7. 17:52
반응형

# Object와 JSON차이점, 스프레드연산자, 나머지연산자, 옵셔널 체이닝

 

 

Object와 JSON의 차이점

JavaScript Object : JS Object

JSON(JavaScript Object Notation) : JSON Object

 

JS Object : 객체의 내용을 기술하기 위한 텍스트 파일

JSON Object : JS Engine 메모리 안에 있는 데이터 구조

 

https://fullstack-eun.tistory.com/46

 

[ javascript ] 06. 원시타입, 참조타입, 객체

원시(Primitive) 타입, 참조(Reference) 타입 자바스크립은 크게 원시타입과 참조타입 2가지로 나눕니다. 원시타입은 number, bigint, string, boolean, null, undefined, symbol이고 값은 변수에 직접 저장됩니다. 참

fullstack-eun.tistory.com

 

JS Object와 JSON Object

 

JS Object

1. 키(이름, 속성) : 값

2. 값 : 숫자, 문자열, 객체(Object), 배열, Null

3. 메서드()

 

JSON Object

1. 키(이름, 속성)는 이중따옴표로 묶어준다 , ”name”

2. 값은 숫자, 논리값을 제외하고 이중따옴표로 묶어줌

3. 값 : 숫자, 문자열, 객체(Object), 배열, Null

 

객체명 = { "이름":값 , "이름":값}
객체명 = { "name":"홍길동" , "age":20 , "addr":"서울" , "isplay": true }
객체명 = { "name":"홍길동" ,"arr" :[] , "obj":{} }

 

JSON.parse() : JSON을 Obj(객체)로 변경

JSON.stringify() : Obj(객체)를 JSON으로 변경

 

JSON.stringify(value [, replacer, space])

value : 인코딩하려는 값

replacer : JSON으로 인코딩하길 원하는 프로퍼티가 담긴 배열. 또는 매핑 함수 function(key, value)

space : 서식 변경 목적으로 사용할 공백 문자 수

 

JS Object - 예) const obj = { name : "홍길동" , age : 20 }

JSON Object - 예) const json = { "name" : "홍길동" , "age" : 20 , "addr" : " 인천" }

 

서버에 있는 JSON 값을 클라이언트에 Object로 넣으려고 할 때

json = JSON.stringify( obj )

클라이언트에 Object를 서버에 있는 JSON 값을 넣으려고 할 때

obj = JSON.parse( json )

 

서버와 클라이언트가 데이터를 주고받음

JSON

# Object

명령어 설명 mdn
Object Object 클래스는 JavaScript의 데이터 유형 중 하나를 나타냅니다. mdn
Object.getOwnPropertyDescriptor() 객체 자신의 속성(즉, 객체에 직접 제공하는 속성, 객체의 프로토타입 체인을 따라 존재하는 덕택에 제공하는 게 아닌)에 대한 속성 설명자(descriptor)를 반환 mdn
Object.keys() 객체의 속성 이름들을 일반적인 반복문과 동일한 순서로 순회되는 열거할 수 있는 배열로 반환합니다. mdn
Object.values() 객체가 가지는 (열거 가능한) 속성의 값들로 이루어진 배열을 리턴합니다. mdn
Object.entries()  객체 자체의 enumerable 속성 [key, value] 쌍의 배열을 반환합니다.  mdn
Object.assign() 객체들의 모든 열거 가능한 자체 속성 (en-US)을 복사해 대상 객체에 붙여넣습니다. 그 후 대상 객체를 반환합니다. mdn
Object.fromEntries() 키값 쌍의 목록을 객체로 바꿉니다. mdn
Object.freeze() 객체를 동결합니다. 동결된 객체는 더 이상 변경될 수 없습니다 mdn
Object.seal() 객체를 밀봉합니다.  mdn
Object.defineProperty() 체에 직접 새 속성을 정의하거나 개체의 기존 속성을 수정하고 개체를 반환합니다. mdn
Object.prototype.hasOwnProperty() 개체가 지정된 속성을 자체 속성으로 갖고 있는지(상속하는 것이 아니라) 여부를 나타내는 부울 값을 반환합니다. mdn

 

 

- Object.keys() / Object.values()

 

문법  : Object.keys(obj)

const obj = { a: 1, b: 2 };

for (const key in obj) {
  console.log("key", key);
  console.log("value", obj[key]);
}

결과
key a
value 1
key b
value 2
const user  = {
  name : "홍길동", 
  age : 20
}

console.log( Object.keys( user )) 

//
["name","age"]
const data = {
  tokyo: 37833000,
  delhi: 24953000,
  shanghai: 22991000
}

Object.keys(data);
// ['tokyo', 'delhi', 'shanghai']

Object.values(data);
// [37833000, 24953000, 22991000]

 

let user = {
  name : "홍길동",
  age  : 20,
  getAge() {
    return this.age;
  }
}

Object.keys(user); //  ["name", "age", "getAge"]
let array = ['a', 'b', 'c'];
console.log(Object.keys(array)); // ['0', '1', '2']

let funObj = {
      fun : function () {
                ...
      }
}

console.log(Object.keys(funObj)) // ["fun"]

 

 

- forEach 사용

const person = {
    firstName: '길동',
    lastName: '홍',
    age: 20,
    ['tel']: '010-0000-1111'
};

Object.keys(person).forEach(key => console.log(person[key]))

결과

길동
홍
20
010-0000-1111

 

 

- Object.entries()

 
const person = {
    firstName: '길동',
    lastName: '홍',
    age: 20,
    ['tel']: '010-0000-1111'
};

const obj  = Object.entries(person);

console.log(obj );

결과
[
  [ 'firstName', '길동' ],
  [ 'lastName', '홍' ],
  [ 'age', 20 ],
  [ 'tel', '010-0000-1111' ]
]

 

const boxStyle = {
    color: 'red',
    borderWidth: '1px'
};

let arr = Object.entries(boxStyle);
console.log(arr);
 
Output:
[['color', 'red'],['borderWidth', '1px']]

 

 

- Object.formEntries()

 

let arr = [['color', 'red'],['borderWidth', '1px']];
let obj = Object.fromEntries(arr);
 
Output:
{color: "red", borderWidth: "1px"}

 

const arr = [
    ['firstName', 'John'],
    ['lastName', 'Doe'],
    ['age', 20]
];

const person = Object.fromEntries(arr);
console.log(person);
 
Output:
{firstName: "John", lastName: "Doe", age: 20}

 

 

- Object.assign()

Object.assign(target, ...sources)
let obj = {
    color: 'red'
};

let cloneObj = Object.assign({}, obj);

console.log(cloneObj);

 결과
 { color: 'red' }
const style = {
    width:'200px'
};
const blueSquare = {
    length: 100,
    color: 'blue'
};

const greenSquare = {
    ...blueSquare,
    ...style
};

const redSquare = Object.assign(greenSquare, {
    fontSize:'20px',
    background:'red'
});

console.log( redSquare )

Output :
{
  length: 100,
  color: 'blue',
  width: '200px',
  fontSize: '20px',
  background: 'red'
}
let box = {
    height: 10,
    width: 20
};

let style = {
    color: 'Red',
    borderStyle: 'solid'
};

let styleBox = Object.assign({}, box, style);

console.log(styleBox);

Output:
{
    height: 10,
    width: 20,
    color: 'Red',
    borderStyle: 'solid'
}
let box = {
    height: 10,
    width: 20,
    color: 'Red'
};

let style = {
    color: 'Blue',
    borderStyle: 'solid'
};

let styleBox = Object.assign({}, box, style);
console.log(styleBox);
 
Output:
{
    height: 10,
    width: 20,
    color: 'Blue',
    borderStyle: 'solid'
}

 

- Object.freeze()

const person = { age: 20 };
person.age = 30;  
console.log(person );  

const obj =  Object.freeze({age: 20});
obj.age = 30;  

console.log(obj);
const company = Object.freeze({
    name: 'ABC corp',
    address: {
        street: 'North 1st street',
        city: 'San Jose',
        state: 'CA',
        zipcode: 1234
    }
});
company.name = 'BBB'
company.address.country = 'USA'
company.address.zipcode = 4321

console.log( company )

# JSON

JSON(JavaScript Object Notation)은 일련의 데이터를 표현하기 위한 경량의 데이터 교환 형식입니다. 주로 웹 애플리케이션에서 데이터를 주고받을 때 사용됩니다. 아래는 JSON의 기본적인 구문과 규칙에 대한 설명입니다.

 

 

데이터 타입: JSON은 다음과 같은 데이터 타입을 지원합니다.


문자열(string): 큰따옴표로 둘러싸인 유니코드 문자열입니다.
숫자(number): 정수나 부동소수점 숫자입니다.

불리언(boolean): true 또는 false 값입니다.
배열(array): 대괄호([])로 둘러싸인 값들의 순서 있는 집합입니다.
객체(object): 중괄호({})로 둘러싸인 키-값(key-value) 쌍의 집합입니다.

널(null): 값이 없음을 나타내는 특별한 값입니다.

객체(Object): 중괄호({})로 둘러싸인 키-값 쌍의 집합으로 표현됩니다. 키는 문자열이어야 하며, 값은 다양한 데이터 타입일 수 있습니다. 키와 값은 콜론(:)으로 구분됩니다.

 

주석(Comment): JSON은 주석을 지원하지 않습니다. 즉, 주석을 추가할 수 없습니다.

공백: JSON은 공백을 무시합니다. 따라서 공백을 적절히 사용하여 가독성을 높일 수 있습니다.

 

JSON은 매우 간단하면서도 유연한 데이터 형식으로, 다양한 프로그래밍 언어와 플랫폼 간에 데이터를 교환에 사용합니다.

{
    "이름": "홍길동",
    "나이": 30,
    "성별": "남성",
    "직업": "개발자"
}

 

 

{
    "이름": "홍길동",
    "나이": 30,
    "성별": "남성",
    "주소": {
        "도시": "서울",
        "우편번호": "12345"
    },
    "취미": ["등산", "요리", "음악 감상"]
}

 

명령어 설명 mdn
JSON JSON 객체는 JavaScript Object Notation(JSON)을 분석하거나 값을 JSON으로 변환하는 메서드를 가지고 있습니다 mdn
JSON.parse() JSON 문자열의 구문을 분석하고, 그 결과에서 JavaScript 값이나 객체를 생성합니다. 선택적으로, reviver 함수를 인수로 전달할 경우, 결과를 반환하기 전에 변형할 수 있습니다. mdn
JSON.stringify() JavaScript 값이나 객체를 JSON 문자열로 변환합니다.  mdn

 

 

# 스프레드 연산자와 나머지 매개변수 

명령어 mdn
arguments 객체 mdn
스프레드연산자 mdn
나머지매개변수 mdn

 

- 스프레드 연산자

let rgb = [ 'red', 'green', 'blue' ];
let cmyk = ['cyan', 'magenta', 'yellow', 'black'];
let merge = [...rgb, ...cmyk];
console.log(merge);

Output:
[ 'red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'black' ]

 

const circle = {
    radius: 10
};
const coloredCircle = {
    ...circle,
    color: 'black'
};

console.log(coloredCircle);


Output:
{
    radius: 10,
    color: 'black'
}

 

const circle = {
    radius: 10
};

const clonedCircle = {...circle};

console.log(clonedCircle);
 
Output:
{ radius: 10 }

 

const circle = {
    radius: 10,
    style: {
        color: 'blue'
    }
};

const clonedCircle = {
    ...circle
};


clonedCircle.style = 'red';

console.log(clonedCircle);
 
Output:
{ radius: 10, style: 'red' }

 

const circle = {
    radius: 10
};

const style = {
    backgroundColor: 'red'
};

const solidCircle = {
    ...circle,
    ...style
};

console.log(solidCircle);
 
Output:
{ radius: 10, backgroundColor: 'red' }

 

- 나머지 연산자

function fn(a,b,...args) {
   //...
}

fn(1, 2, 3, "A", "B", "C");


a = 1
b = 2
...args : [3,'A','B','C']

 

const avg  = ( first = 0, ...rest ) => {
    let sum = first ;
    for( let item  of rest ) {
        sum += item 
    }
    return sum / ( 1 + rest.length )
}   

console.log( avg(1,10, 20 ))

 

 

문제 ) 코드 리팩토링 Code-Refactoring 

 

1. 아래 기본 예제를 변경하시오 

 

리팩터링(refactoring)은 소프트웨어 공학에서 '결과의 변경 없이 코드의 구조를 재조정함'을 뜻한다. 주로 가독성을 높이고 유지보수를 편하게 한다. 버그를 없애거나 새로운 기능을 추가하는 행위는 아니다.
-출처 : 위키백과

 

const arr = [2000, 1000, 3000, 5000, 4000 , 500 , 2500 , 3000 ];

function fn() {
	// console.log( arguments ) 
	let temp = [];

	for (let i = 0; i < arguments[0].length; i++) {		
		if (arguments[0][i] > 1000) {
			temp.push(arguments[0][i] + '원');
		}
	}
	return temp; 
}

console.log( fn( arr ) )

 

위 예시를 변경해보세요 

1. 배열의 값을 함수의 인자를 배열의 스프레드 연산자 이용 
2. 매개변수를 나머지매개변수 이용 
3. for 문을 수정 
   => filter , map , sort 사용
   1000 이상되는 것만 원을 추가 오름차순으로 정렬하시오

 

 

 

# 옵셔널 체이닝 

 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Optional_chaining

 

Optional chaining - JavaScript | MDN

optional chaining 연산자 (?.) 는 체인의 각 참조가 유효한지 명시적으로 검증하지 않고, 연결된 객체 체인 내에 깊숙이 위치한 속성 값을 읽을 수 있다.

developer.mozilla.org

 

 

안전하게 객체나 배열의 깊숙한 프로퍼티에 접근하기 위해서입니다. 주된 이유는 null이나 undefined일 수 있는 값을 처리할 때 에러를 방지하기 위해서입니다.  

 

optional chaining 연산자 (?.) 는 체인의 각 참조가 유효한지 명시적으로 검증하지 않고, 연결된 객체 체인 내에 깊숙이 위치한 속성 값을 읽을 수 있다.

?. 연산자는 . 체이닝 연산자와 유사하게 작동하지만, 만약 참조가 nullish (null 또는 undefined)이라면, 에러가 발생하는 것 대신에 표현식의 리턴 값은 undefined로 단락된다. 함수 호출에서 사용될 때, 만약 주어진 함수가 존재하지 않는다면, undefined를 리턴한다.

따라서 참조가 누락될 가능성이 있는 경우 연결된 속성으로 접근할 때 더 짧고 간단한 표현식이 생성된다. 어떤 속성이 필요한지에 대한 보증이 확실하지 않는 경우 객체의 내용을 탐색하는 동안 도움이 될 수 있다.

optional chaining은 선언되지 않은 루트 객체에 사용할 수 없지만, 정의되지 않은 루트 객체와는 함께 사용할 수 있다.

 

const adventurer = {
  name: 'Alice',
  cat: {
    name: 'Dinah',
  },
};

const dogName = adventurer.dog?.name;
console.log(dogName);
// Expected output: undefined

console.log(adventurer.someNonExistentMethod?.());
// Expected output: undefined

 

 

 

 

지원하지 않는 브라우저에서는 동작하지 않는다. 따라서, 옵셔널 체이닝을 사용하는 경우에는 브라우저 호환성을 고려해야 한다다.

옵셔널 체이닝은 프로퍼티나 메서드가 null 또는 undefined인 경우에만 동작한다. 다른 falsy 값, 예를 들어 0, "", false 등은 체이닝 연산의 결과가 아니라 그대로 반환된다.

옵셔널 체이닝을 남발하면 코드 가독성이 저하될 수 있다.

옵셔널 체이닝 연산자 ?.는 함수 호출 시 인자로 사용할 수 없다. 대신, 함수 호출 전에 체이닝 연산자를 사용하여 안전하게 객체의 프로퍼티나 메서드를 호출해야 한다.

옵셔널 체이닝은 객체 체이닝을 위해 만들어진 것이므로, 배열에서는 사용할 수 없다.(접근만 가능)

 

if (code) {
  // code가 존재하는 경우 실행할 코드
} else {
  // code가 존재하지 않는 경우 실행할 코드
}

// code가 존재하는 경우 실행할 코드
person?.address?.code && 코드 실행;

// code가 존재하지 않는 경우 실행할 코드
person?.address?.code || 코드 실행;

 

 

객체이름? 는 해당 객체가 undefined나 null이면 평가를 중지하고 undefined를 반환한다.
옵셔널 체이닝은 존재하지 않아도 괜찮은 대상에게만 사용하고
반드시 존재해야하는 객체에게는 if문으로 존재 여부를 검사하는 유효성 검사를 수행하는 것이 좋다.

 

 

const obj1 = { name: "홍길동" };
const obj2 = { };

console.log(obj1?.name ?? '이름 없음'); // "홍길동"
console.log(obj2?.name ?? '이름 없음'); // "이름 없음"

 

 

obj?.name:

  • 옵셔널 체이닝(?.)을 사용하여 obj가 null이나 undefined가 아니면 obj.name을 반환하고, 그렇지 않으면 undefined를 반환합니다.

 

??  '이름 없음':

  • 만약 obj1?.name이 null 또는 undefined라면 '이름 없음'을 반환합니다.
  • obj1?.name이 null이나 undefined가 아닌 경우에는 그 값을 그대로 반환합니다.

 

안전한 접근

일반적으로 객체의 프로퍼티에 접근할 때, 그 값이 null 또는 undefined일 경우 에러가 발생할 수 있습니다.

 

const obj = null;
console.log(obj.name);  // TypeError: Cannot read property 'name' of null

 

, 객체 obj가 null이기 때문에 name 프로퍼티에 접근하려고 하면 에러가 발생합니다. 하지만, 옵셔널 체이닝을 사용하면 안전하게 처리할 수 있습니다

 

const obj = null;
console.log(obj?.name);  // undefined (에러가 발생하지 않음)

 

중첩된 객체나 배열 접근

객체가 여러 계층으로 중첩되어 있을 경우, 중간 값이 null 또는 undefined일 수 있습니다. 이런 경우에도 오류 없이 접근할 수 있습니다.

const user = {
  profile: null,
};

console.log(user.profile.bio);  // TypeError: Cannot read property 'bio' of null

 

console.log(user.profile?.bio);  // undefined (에러 없이 안전하게 접근)

 

 

깔끔하고 간결한 코드

옵셔널 체이닝을 사용하면 코드가 더 간결해집니다. 기존 방식으로는 각 단계에서 null 또는 undefined를 체크해야 하기 때문에 코드가 길어질 수 있지만, 옵셔널 체이닝을 사용하면 이를 짧게 처리할 수 있습니다.

 

기존 코드 (옵셔널 체이닝 없이)

if (user && user.profile && user.profile.bio) {
  console.log(user.profile.bio);
}

 

옵셔널 체이닝 사용:

console.log(user?.profile?.bio);

 

 

불필요한 오류 방지

특정 값이 존재하지 않을 가능성이 있는 상황에서, 그 값을 접근하려다 발생하는 오류를 방지하기 위한 것입니다. 옵셔널 체이닝을 사용하면 값이 null 또는 undefined일 때에도 오류 없이 undefined를 반환합니다.

 

옵셔널 체이닝을 사용하는 이유 

  1. 에러 방지: 값이 null 또는 undefined일 때도 안전하게 접근할 수 있음.
  2. 간결한 코드: 중첩된 객체의 프로퍼티에 여러 번 null 체크를 할 필요가 없음.
  3. 중첩된 객체 안전하게 다루기: 깊이 중첩된 객체의 프로퍼티에 안전하게 접근 가능.
반응형