<객체와 프로퍼티>
<객체에서 데이터 접근하기>
console.log(person.name) 과 같은 형식으로 객체의 데이터에 접근할 수 있다.console.log(person[' name'])undefined가 출력된다.<객체 다루기>
객체 수정할때는 객체에 접근해서 다시 값을 할당해주면 된다!
존재하지 않는 프로퍼티를 할당해주면서 추가할 수도 있다.
객체의 프로퍼티를 삭제할때는 delete person.name; 이런식으로 delete 명령어를 사용해주면 객체의 프로퍼티가 삭제된다.
- 객체 내에 프로퍼티가 존재하는지 확인하는 방법
- 1. undefined 비교
console.log(person.name !== undefined)
- 2. 프로퍼티 네임 in 객체
console.log('name' in person)
-> 있는지 확인해서 불린형태로 반환한다.
- 조금 더 안전하게 확인하기 위해서는 in 연산자를 확인하는게 좋다.
- 왜냐하면 실수로 프로퍼티에 undefined를 할당했거나, 다른 함수나 변수에 의해서 의도치않게 undefined가 할당될수도 있기 때문이다.
- 그리고 if문에서 조건으로 활용하기도 좋다. 불린형태로 반환하기 때문이다.
- 굉장히 많이 사용하는 방식이다. 잘 알아두자
<객체와 메소드>
ex) greetings['sayHello']('name')<for...in 반복문>
for (변수 in 객체) {
동작부분
}
let myObject = {
3: '정수3',
name: 'codeit',
1: '정수1',
birthDay: '2017.5.17',
2: '정수2',
};
for (let key in myObject) {
console.log(key);
}
1
2
3
name
birthDay
분명히 3, name, 1, birthday, 2순서로 프로퍼티가 작성되었음에도 불구하고, for...in문이 실행될 때는 오름차순으로 정렬이 되어 출력이 된 모습을 확인할 수 있다.
굳이 for문을 그대로 작성하지 않고도 그냥 콘솔에 myObject를 콘솔에 출력만 해봐도
{1: "정수1", 2: "정수2", 3: "정수3", name: "codeit", birthDay: "2017.5.17"}
객체가 정수형 프로퍼티에 한해서 오름차순으로 정렬이 되고 나머지는 추가한 순서대로 정렬이 되는 걸 확인할 수 있다.
처음에 살펴봤던 것처럼 정수형 프로퍼티에 따옴표를 붙여 문자열처럼 만들더라도, 정렬방식은 동일하게 처리된다.
<내장객체>
- 자바스크립트가 미리 가지고 있는 객체를 내장객체라고 한다. 대표적인 예로 Date가 있다.
let myDate = new Date();
Date 객체를 생성한 순간의 시간이 저장되는데, 소괄호 안에 숫자를 넣어주면 UTC 기준 1970년 1월 1일 00:00:00 에서 입력한 숫자 밀리초 만큼 지난 객체가 만들어진다.
근데 복잡하니깐 숫자 보단 문자열을 넣어주는 방법도 있다.
소괄호 안에 연-월-일T00:00:00 이런식을호 넣어주면된다.
시간을 지정해주면 그시간, 아니면 00:00:00 기준
소괄호안에 여러가지 값을 입력해주는 방식
연, 월, 일, 시, 분, 초 이런식으로 하되 월은 0부터 시작한단다.
생각보다 시간 계산이 필요할때 자주 쓰인다.
getTime 메소드
1970.1.1. 0시0분0초 기준으로 현재가 몇 밀리초를 지났는지 알려준다. 이를 타임스탬프(time stamp) 라고부른다.
Date 객체 정보 수정하기
set으로 시작하는 다양한 메서드를 활용하면, 생성된 Date객체의 정보를 수정할 수도 있습니다.
(대괄호로 감싸진 요소들은 선택적인 요소이다. 참고!)
setFullYear(year, [month], [date])
setMonth(month, [date])
setDate(date)
setHours(hour, [min], [sec], [ms])
setMinutes(min, [sec], [ms])
setSeconds(sec, [ms])
setMilliseconds(ms)
setTime(milliseconds)(1970년 1월 1일 00:00:00 UTC부터 밀리초 이후를 나타내는 날짜를 설정)
간단하게 시간 정보를 표현하고 싶다면 아래와 같은 메소드를 활용해 볼 수도 있습니다.
let myDate = new Date();
console.log(myDate.toLocaleDateString()); // myDate가 가진 날짜에 대한 정보 (년. 월. 일)
console.log(myDate.toLocaleTimeString()); // myDate가 가진 시간에 대한 정보 (시:분:초)
console.log(myDate.toLocaleString()); // myDate가 가진 날짜와 시간에 대한 정보 (년. 월. 일 시:분:초)
toLocaleDateString(), toLocaleTimeString(), toLocaleString() 메소드는 사용자의 브라우저에 설정된 국가의 표기에 맞춰 날짜와 시간을 보여줍니다.
똑똑한 Date?!
Date 객체엔 자동으로 날짜를 수정해주는 유용한 기능이 있습니다. 범위를 벗어나는 값을 설정하려고 하면 자동으로 날짜를 수정해줍니다.
let myDate = new Date(1988, 0, 32);
// 1988년 1월 32일은 없습니다
// 2월 1일로 자동고침 되는걸 확인할 수 있습니다.
console.log(myDate) // Mon Feb 01 1988 00:00:00
지금 이 순간..!?
Date.now() 메소드는 이 메소드가 호출된 시점의 타임스탬프를 반환합니다. 이렇게 하면 새로운 객체를 만들지 않아도 바로 현 시점의 날짜 값을 얻어낼 수 있는 것!
let myDate = new Date();
console.log(Date.now() === myDate.getTime()); // true
위 코드를 보면 알 수 있듯이 새로운 객체를 만들어서 getTime 메소드를 호출한 값과 일치한다는 사실을 확인할 수 있는데요.
새로운 객체를 만들지 않는다는 점은 일단 우리 눈에 코드 한 줄을 줄일 수 있다는 이점도 있고, 눈에는 드러나지 않지만 코드가 실행될 때 메모리의 부담을 줄여주기도 합니다.
그래서 특정한 시점이 아니라 단순히 순간순간 그때 당시 시간 값이 필요한 경우에는 Date.now() 메소드를 활용하는 것이 코드의 가독성 뿐만아니라 성능적인 측면에서도 좀 더 유리합니다.
Date객체의 형변환
let myDate = new Date(2017, 4, 18);
console.log(typeof myDate); // object
console.log(String(myDate)); // Thu May 18 2017 00:00:00 GMT+0900 (Korean Standard Time)
console.log(Number(myDate)); // 1495033200000
console.log(Boolean(myDate)); // true
let myDate = new Date(2017, 4, 18);
console.log(myDate.getTime() === Number(myDate)); // true
let myDate1 = new Date(2017, 4, 18);
let myDate2 = new Date(2017, 4, 19);
let timeDiff = myDate2 - myDate1;
console.log(timeDiff); // 86400000 (ms)
console.log(timeDiff / 1000); // 86400 (sec)
console.log(timeDiff / 1000 / 60) // 1440 (min)
console.log(timeDiff / 1000 / 60 / 60) // 24 (hour)
console.log(timeDiff / 1000 / 60 / 60 / 24) // 1 (date)
이렇게 하니깐 두 Date객체 사이의 시간차이를 어렵지 않게 확인할 수 있죠?
<배열 - Array>
console.log(배열이름[index])<배열 다루기>
조건으로 사용할때 많이 쓴다.<배열 메소드1>
splice(startIndex, deleteCount, item)<배열 메소드2>
배열에서 특정 값 찾기 (indexOf / lastIndexOf)
let brands = ['Google', 'Kakao', 'Naver', 'Kakao'];
console.log(brands.indexOf('Kakao'));
console.log(brands.indexOf('Daum'));
1
-1
let brands = ['Google', 'Kakao', 'Naver', 'Kakao'];
console.log(brands.lastIndexOf('Kakao'));
console.log(brands.lastIndexOf('Daum'));
3
-1
let brands = ['Google', 'Kakao', 'Naver', 'Kakao'];
console.log(brands.includes('Kakao'));
console.log(brands.includes('Daum'));
true
false
let brands = ['Google', 'Kakao', 'Naver', 'Kakao'];
console.log(brands);
brands.reverse();
console.log(brands);
(4) "Google", "Kakao", "Naver", "Kakao" ["Kakao", "Naver", "Kakao", "Google"]
사실 이 밖에도 배열이 가지고 있는 유용한 메소드들이 다양하게 있다. 더 많은 내용을 알고싶다면, 이 링크를 참고!
(https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array)
<for...of 반복문>
for(변수 of 배열){
동작부분;
}
<다차원 배열>
<다양한 숫자 표기법>
<숫자형 메소드>
toFixed
toString
이번에는 Math객체의 다양한 메소드에 대해 살펴봅시다.
절댓값 (Absolute Number)
학창 시절 수학 시간에서 배운 '절댓값(absolute value)' 기억하시나요? 간단하게 설명하자면, 어떤 값의 '양수(positive number)' 버전이라고 할 수 있습니다. 음수 -5의 절댓값은 양수 5고, 그냥 양수 5의 절댓값은 그대로 양수 5인 거죠.
- Math.abs(x)를 하면 x의 절댓값이 리턴됩니다.
console.log(Math.abs(-10));
console.log(Math.abs(10));
10
10
최댓값 (Maximum)
Math.max 함수에 파라미터로 여러 수를 넘겨주면, 그중 가장 큰 값이 리턴됩니다.
console.log(Math.max(2, -1, 4, 5, 0));
5
최솟값 (Minimum)
Math.min 함수에 파라미터로 여러 수를 넘겨주면, 그중 가장 작은 값이 리턴됩니다.
console.log(Math.min(2, -1, 4, 5, 0));
-1
거듭제곱 (Exponentiation)
'제곱'의 개념 기억하시나요? '2의 3승'(혹은 '2의 세제곱')을 하면, 2를 세 번 곱한다는 뜻입니다. '2 곱하기 2 곱하기 2'를 하면 8이죠? 마찬가지로 '5의 2승'을 하면, '5 곱하기 5'를 해서 25입니다.
자바스크립트에서 Math.pow(x, y)를 하면 x의 y승의 결괏값이 리턴됩니다.
console.log(Math.pow(2, 3));
console.log(Math.pow(5, 2));\
8
25
제곱근 (Square Root)
'제곱근(square root)'은 '제곱'의 반대라고 생각할 수 있습니다. 5의 제곱이 25이기 때문에, 25의 제곱근은 5입니다. 7의 제곱이 49이기 때문에, 49의 제곱근은 7입니다.
Math.sqrt(x)를 하면 x의 제곱근이 리턴됩니다.
console.log(Math.sqrt(25));
console.log(Math.sqrt(49));
5
7
반올림 (Round)
Math.round(x)를 하면 x의 반올림된 값이 리턴됩니다. 소수점 부분이 0.5 이상이면 가장 가까운 정숫값으로 올라가고, 소수점 부분이 0.5 미만이면 가장 가까운 정숫값으로 내려갑니다.
console.log(Math.round(2.3));
console.log(Math.round(2.4));
console.log(Math.round(2.49));
console.log(Math.round(2.5));
console.log(Math.round(2.6));
2
2
2
3
3
버림과 올림 (Floor and Ceil)
Math.floor(x)을 하면 x의 버림 값이, Math.ceil(x)을 하면 x의 올림 값이 리턴됩니다. 이 경우, 소수 부분이 얼마 인지와는 상관이 없습니다.
console.log(Math.floor(2.4));
console.log(Math.floor(2.49));
console.log(Math.floor(2.8));
console.log(Math.ceil(2.4));
console.log(Math.ceil(2.49));
console.log(Math.ceil(2.8));
2
2
2
3
3
3
난수 (Random)
Math.random을 하면 0 이상 1 미만의 값이 랜덤으로 리턴됩니다.
console.log(Math.random());
console.log(Math.random());
console.log(Math.random());
console.log(Math.random());
0.21458369059793236
0.6622040803059857
0.785172717569619
0.9056556038884926
이뿐만 아니라 '삼각 함수 계산'이나 '로그'같은 더 깊은 수학 계산도 가능합니다. 더 깊게 알아보고 싶다면 이 링크 를 참고하세요!
(https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math)
<문자열 심화>
자바스크립트에서는 문자열도 객체처럼 다룰 수 있다.
length 프로퍼티를 활용하면 공백포함해서 문자열의 길이를 알 수 있다.
요소에도 접근할 수 있는데
대괄호 표기법 - myString[3]
or
charAt 메소드 - myString.charAt(3)
or
indexOf 나 lastIndexOf를 활용할 수 있다.
(없는 문자열 찾을때는 역시 -1이 출력된다)
//대소문자 변환
myString.toUpperCase() -> 대문자로 바꿔
myString.toLowerCase() -> 소문자로 바꿔
//양 끝 공백 제거
mySting.trim()
//부분 문자열 접근 slice(start, end)
-> 2개의 파라미터를 가지고 있는데, 시작과 끝 인덱스이다. 끝 인덱스 바로 직전까지의 범위를 가져온다.
myString.slice(0,2) -> 0번부터 1번까지
myString.slice(3) -> 시작지점부터 끝까지
myString.slice() -> 문자열 전체
문자열도 생각해보면 '문자' + '열'이기 때문에 배열과 비슷한 부분들이 많습니다.
비슷한 점
배열과 문자열 모두 length프로퍼티를 가지고 있고, 대괄호 표기법으로 각 요소에 접근할 수 있다거나..
꽤 많은 메소드들이 배열과 문자열 모두 동일하게 사용되는 것도 확인할 수 있었다. 심지어 지난 시간에 다루진 못했지만 배열을 다룰 때 유용한 for..of문을 문자열에 활용할 수도 있습니다.
let myString = 'Codeit';
for (let str of myString) {
console.log(str);
}
C
o
d
e
i
t
다른 점
하지만 비슷하다고 해서 완전히 같다고는 할 수 없습니다.
let myString = 'Codeit';
let myArray = ['C', 'o', 'd', 'e', 'i', 't'];
console.log(typeof myString);
console.log(typeof myArray);
일단 typeof 연산자를 사용해서 두 값의 자료형을 비교해보면,
string
object
확실히 서로 다른 자료형인 걸 확인할 수 있고,
let myString = 'Codeit';
let myArray = ['C', 'o', 'd', 'e', 'i', 't'];
console.log(myString === myArray);
console.log(myString == myArray);
두 값을 서로 비교해 보아도
false
false
일치 비교뿐만 아니라, 느슨하게 비교하는 동등비교에서도 false가 출력되는걸 확인할 수 있습니다.
mutable vs. immutable
배열은 요소에 접근해서 할당연산자를 통해 요소를 수정할 수 있었죠?
문자열은 한 번 할당된 값을 수정할 수 없습니다. 다르게 표현해서, 변수에 할당된 문자열을 바꾸고 싶다면, 일부를 바꾸는 게 아니라 새로운 문자열을 지정해주어야 한다는 것이죠.
// 배열은 mutable
let myArray = ['C', 'o', 'd', 'e', 'i', 't'];
myArray[0] = 'B';
console.log(myArray);
// 문자열은 immutable
let myString = 'Codeit';
myString[0] = 'B';
console.log(myString);
(6) ["B", "o", "d", "e", "i", "t"]
Codeit
다시 한번 되돌아보면, 문자열이 가진 메소드들은 모두 return 값들을 활용하고, 본래의 문자열 값을 수정하지 않습니다.
같은 의미에서 문자열에 splice 같은 메소드들은 사용할 수 없겠죠?
문자열과 배열은 서로 비슷하지만 엄연히 다른 차이가 있다는 점 꼭 기억하자!
<기본형과 참조형>
객체(참조형, Reference Type)
<참조형 복사하기>
let course2 = Object.assign({}, course1)을 통해서 복사 후 course2만 수정 가능하다. function 함수(object){
let temp = {};
for(let key in object){
temp[key] = object[key]
}
return temp;
}
<const, 변수와 상수 사이>
참고: https://cwdeveloper.tistory.com/38
질문 2
다음 코드의 실행결과로 올바른 것을 고르세요.
let team1 = ['Drum', 'Bass', 'Saxophone'];
const team2 = team1;
team1.splice(2, 1, 'Trumpet');
team2.splice(2, 1, 'Piano');
console.log(team1);
console.log(team2);
해설
답: 2
자바스크립트에는 variable의 약자를 따서 var라는 키워드로 변수를 선언할 때가 있었습니다.
변수 선언
일단 아래 코드 처럼 var 변수는 let 이나 const 처럼 똑같이 키워드 다음에 변수 이름을 써서 선언할 수 있고,
var myVariable;
myVariable = 'codeit';
혹은 키워드와 변수이름, 그리고 할당연산자와 값으로 선언과 동시에 값을 할당해 줄 수도 있습니다.
var myVariable = 'codeit';
중복 선언 허용
var 키워드로 선언한 변수의 첫 번째 문제는, let과 const와는 다르게 중복 선언이 가능하다는 겁니다.
똑같은 이름으로 변수를 한 번 더 선언하게 되면, 에러가 발생하는 것이 아니라 그냥 기존의 변수를 덮어써 버리는 것이죠.
let키워드로 선언한 변수에 값을 재할당하는 것과는 엄연히 다릅니다.
var myVariable = 'codeit';
console.log(myVariable);
var myVariable = 'Codeit!';
console.log(myVariable);
codeit
Codeit!
이렇게 변수가 중복선언이 되면, 길고 복잡한 코드를 작성할 때 실수를 할 가능성이 커지고, 상황에 따라서는 치명적인 오류가 발생할 수 있습니다.
함수 스코프
{
let x = 3;
}
function myFunction( ) {
let y = 4;
}
console.log(x);
console.log(y);
//Uncaught ReferenceError: x is not defined
let이나 const 키워드의 경우에는 중괄호로 감싸진 경우라면 모두 중괄호 밖에서는 지역 변수에 접근할 수 없습니다.
{
var x = 3;
}
function myFunction() {
var y = 4;
}
console.log(x);
console.log(y);
//3
//Uncaught ReferenceError: y is not defined
하지만 var 변수는 지역변수의 구분이 함수에만 있기 때문에 if, for, while, switch 등 다양한 상황에서 선언한 변수가 자칫, 전역변수의 역할을 하게 될 수도 있는 것이죠.
참고로 이렇게 함수를 기준으로만 적용되는 스코프를 함수 스코프, 코드 블록을 기준으로 적용되는 스코프를 블록 스코프라는 용어를 사용한다는 점도 참고해 주세요!
끌어올림 (Hoisting)
console.log(myVariable);
let myVariable;
//Uncaught ReferenceError: Cannot access 'myVariable' //before initialization
let과 const로 선언한 변수는 선언되기 이전에 사용될 수 없습니다. 하지만, var 변수는 함수 스코프를 기준으로 선언되기 이전에도 변수에 접근이 가능한데요.
console.log(myVariable);
var myVariable;
//undefined
변수의 선언이 끌려 올라가서 마치, 2번째 줄과 첫 번째 줄이 바뀐 것처럼 동작하는 데요.
var myVariable;
console.log(myVariable);
이렇게 변수가 끌어올려 지는 현상을 '호이스팅(hoisting)'이라고 부른다는 점도 기억하자.
다행히 호이스팅은 선언과 동시에 값을 할당하더라도, 선언문만 올려지기 때문에 값은 그대로 두 번째 줄에 남아있는 데요.
console.log(myVariable);
var myVariable = 2;
console.log(myVariable);
//undefined
//2
하지만 이런 식으로 동작하는 방식은 코드의 흐름을 방해하기에 충분해 보이죠? 한 가지 주의해야 될 부분은, 함수를 선언할 때도 이 호이스팅이 적용됩니다.
sayHi();
function sayHi() {
console.log('hi');
}
이렇게 코드를 작성하더라도 실행해보면,
// hi
당연한 듯 함수가 잘 실행되는 모습을 확인할 수 있습니다.
이런 현상은 함수를 한 번 선언하고 나면 어디서든 유연하게 사용할 수 있다는 장점이 있지만, 코드의 흐름에는 부정적인 영향을 끼칠 수 있습니다.
그래서 함수를 선언할 때는 가급적 코드 윗부분에 선언하거나, 호출을 항상 아래쪽에서 한다거나 나름대로 규칙을 세워서 코드를 작성하시기를 권장한다.