객체에서 프로퍼티 정보를 표현할 때 축약할 수 있는 표현 방식
const firstName = "Carrot";
const lastName = "Wilted";
const carrot = {
firstName, // firstName: "Carrot" 형태를 축약
lastName,
printName () { // printName: function () {} 형태를 축약
return `${this.firstName} ${this.lastName}`
}
}
리덕스에서 combineReducer
함수를 통해 분리 작성해 놓은 여러 리듀서들을 불러와 합치는 작업을 수행하는데 이때 combineReducer
함수에서 인자로 받는 리듀서 형태 또한 축약할 수 있다.
import userReducer from "./userReducer"
import todoReducer from "./todoReducer"
const rootReducer = combineReducer({
userReducer,
todoReducer,
})
{
[expression]: value
}
계산된 프로퍼티명으로 ES2015부터 지원된 문법이다. 프로퍼티의 이름을 정의하는 새로운 방법이다.
객체 리터럴의 프로퍼티명 자리에 대괄호[]
와 표현식의 조합으로 사용되며 expression
의 실행 결과가 프로퍼티의 이름이 된다.
// react에서 useState와 change event에서 자주 사용하는 패턴
const handleChange = (e) => {
setState({
[e.target.name]: e.target.value
})
}
배열 데이터 구조에서 키와 밸류로 나열되어 있는 구조? computed property name
을 활용해서 불필요한 if문, switch 분기문을 줄일 수 있는 방법으로 데이터를 함수에서 분리하여 함수를 조금 더 유연하게 활용할 수 있도록 도움을 준다.
// if 혹은 switch문의 case가 많아져서 길어지는 경우
function getUserType(type) {
switch(type) {
case "ADMIN":
return "관리자";
case "INSTRUCTOR":
return "강사";
case "STUDENT":
return "수강생";
default:
return "해당 없음";
}
}
function getUserType(type) {
const USER_TYPE = {
ADMIN: "관리자",
INSTRUCTOR: "강사",
STUDENT: "수강생",
UNDEFINED: "해당 없음"
}
return USER_TYPE[type] ?? USER_TYPE['UNDEFINED'];
}
USER_TYPE
을 분리하여 상수로 관리하고 import해서 사용한다면 함수의 구조를 변경하지 않고도 추가적인 case들을 적용할 수 있다.
import USER_TYPE from "./USER_TYPE";
function getUserType(type) {
return USER_TYPE[type] || USER_TYPE.UNDEFINED;
}
객체를 구조분해 하고 할당하는 방법.
// 객체 프로퍼티명으로 분해할 수 있다.
const user = { id: 1, name: "carrot" };
const { id, name } = user;
// 배열도 분해할 수 있다.
const [first, , third] = [1, 2, 3];
// api 요청에 대한 response 단계에서도 자주 사용한다.
export default (req, res) => {
const { id, name } = req.body;
}
구조분해의 장점으로는 입력받는 프로퍼티의 순서에 의존하지 않아도 된다는 점과, 필수 프로퍼티와 옵션 프로퍼티를 구분할 수 있다는 점이다.
function User(id, name) {
this.id = id;
this.name = name;
}
const Carrot = new User(1, "carrot");
위 예제의 User 생성자 함수는 id와 name 값을 특정 순서로 입력받아야 의미 있는 User 데이터를 생성합니다.
구조분해 할당시 이와같은 순서에서 벗어날 수 있습니다.
function User({ id, name }) {
this.id = id;
this.name = name;
}
const Carrot = new User({name: "carrot", id: 1})
필수 프로퍼티와 옵션 프로퍼티를 나눌 수 있다.
function User(name, { id, email }) {
this.name = name;
this.id = id || -1
this.email = email || ""
}
const Carrot = new User("carrot", {})
객체의 원본을 변경하지 않도록 해주는 내장 메서드.
const STATUS = Object.freeze({
PENDING: "PENDING",
SUCCESS: "SUCCESS",
FAIL: "FAIL"
})
// STATUS 객체의 프로퍼티 값을 수정하거나 추가하는 작업이 모두 막힌다.
STATUS.PENDING = "P-END-ING";
STATUS.NEW_PROP = "PRE-";
console.log(STATUS); // {PENDING: "PENDING", SUCCESS: "SUCCESS", FAIL: "FAIL"}
객체가 동결되어 있는지 확인할 수 있는 내장 메서드는 isFrozen()
console.log( Object.isFrozen(STATUS) ); // true
freeze
는 객체의 1단계 프로퍼티까지만 데이터를 동결해주며, 2단계 이상의 depth로 내려가는 데이터의 경우 동결되지 않으므로, 별도의 동결 처리를 거쳐야 한다.
ES2015 문법에서 class
가 지원되기 전 까지는 생성자 함수라는 것을 통해서 클래스를 구현했음.
function User(id, name) {
this.id = id;
this.name = name;
}
User.prototype.printName = function () {
return "User Name : " + this.name
}
자바스크립트 명세서의 발전으로 class 문법을 지원함으로써 위와 같은 생성자 함수나 함수의 프로토타입에 메서드를 추가하는 코드는 보기 힘들어졌다. 때문에 프로토타입을 조작하는 일의 필요성 자체가 줄어들었다고 볼 수 있다.
객체 내장 메서드인 hasOwnProperty
는 해당 객체의 프로퍼티 값을 가지고 있는지 여부를 boolean 형태로 결과를 나타내 주는 함수이다.
const Carrot = {id: 1, name: "carrot"};
Carrot.hasOwnProperty("name"); // true;
hasOwnProperty
는 오버라이드로 덮어씌워져 전혀 다른 메서드가 될 수 있으므로 이 경우 Object의 프로토타입에 접근해서 메서드를 호출하는 것이 안전하다.
Object.prototype.hasOwnProperty.call(Carrot, "name");
// 유틸 함수로 만들어 필요할 때 마다 호출해서 사용하는게 좋다.
export function hasOwnProp(targetObject, targetProperty) {
return Object.prototype.hasOwnProperty.call(targetObject, targetProperty)
}
hasOwnProp(Carrot, "name"); // true
Object Model에 접근할 수 있는 방법을 적절히 통제한다.
const user = {
name: "carrot",
email: "carrot@carrot.field.com",
status: "wilted",
isLogin: false,
isValidToken: false
}
로그인이나 로그아웃 같은 일련의 과정에서 user 데이터를 변경해야 한다면 다음과 같은 방법으로 직접 접근을 통제할 수 있다.
// user 객체에 접근할 수 있는 함수들을 생성한다.
const setLogin = (bool) => user.isLoggin = bool;
const setValidToken = (bool) => user.isValidToken = bool;
// 객체에 직접 접근하는 것이 아닌 대신 접근하는 함수들을 이용한다.
const login = () => {
setLogin(true);
setValidToken(true);
}
const logout = () => {
setLogin(false);
setValidToken(false);
}
유저가 동적으로 접하는 영역은 login
, logout
함수와 같은 메인 함수가 담당하고, 데이터를 변경하는 동작은 setLogin
, setValidToken
과 같은 함수가 담당한다.
동작하는 기능을 분리해 놓으면 디버깅도 쉬워지고, 로직을 변경할 때도 쉬워진다.