시작하기 전에......

 

이번엔 객체를 중심적으로 다룬다.

 

1. 객체란?

2. 속성과 메소드(this)

3. 화살표함수와 메소드

4. 객체의 속성과 메소드(new)

5. 일반 자료형의 일시적 승급

6. 일반자료형을 위한 새로운 속성 또는 메소드 정의

7. Number의 속성과 메소드

8. String의 속성과 메소드

 


1. 객체란?

객체란 사물이라고 할 수 있고 이름과 값으로 구성된 속성을 가진 기본 데이터 타입이라 할 수 있다.

 

이게 뭔 소리냐?

 

게임 캐릭터를 예시로 설명해보자

 

사진은 오리와 눈 먼숲 시리즈에 등장하는 주인공 오리라는 캐릭터다

이름 오리
종족 가디언
나이 알 수 없음
능력 1 삼단점프()
능력 2 튕겨내기()
능력 3 올가미()
능력 4 파고들기()

 

 

여기서 오리는 객체에 해당한다.

 

그리고 이름, 종족, 나이, 능력 등은 속성에 해당한다.

 

여기서 능력 1~4은 메소드(동작 가능한 함수)라고 할 수 있다.

 

즉 속성은 해당 객체의 특징을 나타내는 것이고

메소드는 해당 객체가 할 수 있는 것들 이라고 할 수 있다.

 

배열 또한 객체의 일종이다.

배열 또한 여러 자료를 다룰 수 있었다.

배열도 객체이기 때문이다.

당장 배열을 typeof로 자료형을 출력해보면 object라고 나오는 것을 알 수 있다.

 

배열과 객체는 유사하지만 배열은 인덱스를 이용해 접근했다면

객체는 키를 이용하여 접근한다.

객체는 중괄호를 사용해 생성하며 쉼표를 연결하여 입력한다.

 

위의 오리를 예시로 만들어보자

const character = {
  name: 'ORI',
  race: 'Guardian',
  age: undefined,
  ability_1: 'tripleJump()',
  ability_2: 'bash()',
  ability_3: 'Grapple()',
  ability_4: 'Burrow()'
}

console.log(character)

// 결과
// name:"ORI"
// race:"Guardian"
// age:undefined
// ability_1:"tripleJump()"
// ability_2:"bash()"
// ability_3:"Grapple()"
// ability_4:"Burrow()"

어빌리티의 tripleJump() 등은 선언된 함수가 아니기 때문에 오류가 발생한다.

때문에 여기선 스트링으로 처리했다.

 

객체 요소에 접근해보자

위의 코드에서 이어진다.

onsole.log(character['name'])
console.log(character.name)

// 결과
// ORI
// ORI

보시다시피 두 가지 접근 방법이 있다.

대괄호에 따옴표로 이름을 가져오는 것과

점을 써서 가져오는 방법 두가지다.

 

사람들은 이 중 점을 쓰는 방법을 더 선호한다.

단, 이름이 식별자로 사용할 수 없는 글자들로 구성된 경우(ex: name!@#!@%)에는 대괄호를 사용해야 한다.

 

2. 속성과 메소드(this)

앞서 말했듯이 속성가운데 함수가 속성이면 메소드가 된다.

아까의 오리의 경우엔 (비록 에러를 피하기 위해 스트링 처리했지만) 어빌리티들이 메소드에 속한다.

 

const character = {
  name: 'ORI',
  race: 'Guardian',
  age: undefined,
  ability_1: 'tripleJump()',
  ability_2: 'bash()',
  ability_3: 'Grapple()',
  ability_4: function (skill) {
    console.log(this.name + '는 ' + skill+ '를 사용')
  }
}

character.ability_4('버로우')

//결과
//ORI는 버로우를 사용

맨 처음 코드에서 4번 기술을 스트링이 아닌 함수로 바꾸었다.

 

여기서 this라는 키워드가 사용되었다.

this란 말 그대로 그 객체를 의미한다.

메소드에서 this 를 사용하면 그 메소드를 사용하는 객체를 뜻한다.

즉, 자신의 상위 개념을 가리킬 때 사용하는 개념이다.

 

3. 화살표함수와 메소드

익명함수와 화살표함수는 메소드로 사용될 때 this를 다른 방식으로 사용한다.

const test = {
	a: function (){console.log(this)},		//익명함수
	b: () => {console.log(this)}			//화살표함수
}

test.a()
test.b()

//결과
//{a: a(), b : b()}
//b의 경우는 실행환경에 따라 결과가 다름

 

b는 window객체를 출력한다.

이는 웹브라우저에서 실행하는 자바스크립트의 핵심 객체라 할 수 있다.

 

이처럼 화살표 함수는 this가 가리키는 대상이 이상해지기 때문에 화살표 함수를 메소드로 사용하지는 않는다.

 

 

4. 객체의 속성과 메소드(new)

앞서 설명했듯 배열은 객체이며 함수도 객체에 해당한다.

단, typeof를 사용해서 함수를 확인해보면 object 타입이 아닌 function 타입으로 나온다.

 

속성은 어디까지나 객체만이 가질 수 있으며 일반적인 자료형은 속성을 가질 수 없다.

때문에 객체가 아닌 대상에게 속성값을 넣어주면 애러는 안뜨지만 반응을 안한다.

const d = '안녕'
d.sample = 10
console.log(d.sample)

// 결과
// undefined

즉, 저런 문장을 쓸 수는 있지만 아무 의미없는 것이라고 할 수 있다.

 

그렇다면 일반 자료형을 객체로 바꿀 수 없을까?

다음과 같은 방법을 쓰면 가능하다.

let n = new Number(273)

변수 n이 선언되었는데 이것은 숫자형 자료를 가진 273이며 이것은 객체로 생성되었다는 의미다.

이제 n을 typeof로 검사해보면 object라고 뜨는 것을 알 수 있다.

 

 

5. 일반 자료형의 일시적 승급

일반 자료형은 속성을 가질 수 없다.

그러나 코딩의 편의를 위해 속성을 사용할 수 있는데, 이 경우 일시적으로 자료형이 승급된다.

a = 'JavaScript'
console.log(a.length)

// 결과
// 10

a는 객체가 아닌 일반 자료형이다.

그런데 langth라는 속성을 사용할 수 있다.

이를 일시적 승급이라고 한다.

a = 'JavaScript'
console.log(a.abcde = 10)
console.log(a.abcde)

// 결과
// 10
// undefined

일시적 승급은 그 순간에만 적용된다.

때문에 abcde라는 속성을 추가해주어도 그 순간에만 적용될 뿐

그 이후에는 적용되지 않아 undefined가 나오는 것을 알 수 있다.

 

 

6. 일반자료형을 위한 새로운 속성 또는 메소드 정의

 

prototype속성을 사용하여 가능하다.

Number.prototype.abcde = 10;

const i = 24;

console.log(i)
console.log(i.abcde)

// 결과
// 24
// 10

Number는 자료형, 즉 숫자임을 뜻한다.

그리고 abcde라는 속성을 새로 생성했고 이것은 10이라는 숫자를 가진다.

이제 자료형에 abcde라는 속성을 넣어주면 10이 출력된다.

 

 

Number.prototype.abc = function (n){
	return this.valueOf() **n
}

const a = 12
console.log(a.abc(3))

// 결과
// 1728

여기서 **은 제곱을 뜻한다.

즉 **n은 n제곱을 말한다.

 

this는 이것, 즉 자신을 사용할 존재을 뜻하고

valueOf()는 function에 입력된 값을 뜻한다 (사실 이부분은 생략해도 된다.)

 

정리하자면 abc라는 메소드는 파라미터로 n을 받으며 자신을 사용할 존재가 가진 값에 n제곱을 리턴한다는 뜻이다.

 

때문에 a.abc(3)은 12의 3제곱인 1728이 출력된다.

 

보너스

indexOf() 메소드는 문자열의 위치를 말해준다.

const j = '안녕하세요안녕하세요';

console.log(j.indexOf('안녕'))
console.log(j.indexOf('녕'))
console.log(j.indexOf('뷁'))

// 결과
// 0
// 1
// -1

안녕이라는 글자는 j의 0번에서 시작하고

녕이라는 글자는 j의 1에 위치해 있다.

단, 중복되는 글자가 있을 경우 가장 앞에 있는 글자를 리턴한다.

 

만약 없는 글자를 호출할 경우, -1을 리턴한다.

즉, 이 메소드를 사용해서 얻은 값이 0 이상이라면 파라미터 내의 문제를 포함한다고도 할 수 있다.

 

이 메소드는 배열에 사용할 경우, 해당 인덱스에 있는 값을 보여준다 (입력은 당연히 숫자로 해야한다.)

 

 

7. Number의 속성과 메소드

 

toFixed(n)는 해당 변수의 소숫점 n번째 자리까지 표시할 때 쓰인다.

const i = 3.141592
console.log(i.toFixed(0))
console.log(i.toFixed(1))
console.log(i.toFixed(2))

// 결과
// 3
// 3.1
// 3.14

 

 

isNaN(n)은 Number와 함께 쓰며, Number.isNaN(n)이라고 쓰며 n의 값이 NaN인가 여부를 출력한다.

const i = 3.141592
const j = '자바스크립트'
const k = Number('asdf')
console.log(Number.isNaN(i))
console.log(Number.isNaN(j))
console.log(Number.isNaN(k))
console.log(Number(j))

// 결과
// false
// false
// true
// nan

여기서 이상한 점이 하나 있다.

자바스크립트라는 문자열이 NaN이 아니라고 출력한 것인데

막상 자바스크립트라는 문자열을 Number로 출력하면 nan이라고 뜨는 것이다.

아직은 원인을 알 수 없으니 지금은 넘어가자

 

isFinite(n)은 Number와 함께 쓰며, Number.isFinite(n)이라고 쓰며 n의 값이 무한인가 여부를 출력한다.

정확히는 n은 셀 수 있는 숫자인가? 를 묻는 여부다.

무한으로 만드는 방법은 간단한데 그냥 0으로 나누어주면 된다.

const i = 10 / 0
const j = -5 / 0
console.log(i)
console.log(j)
console.log(Number.isFinite(i))

// 결과
// Infinity
// -Infinity
// false

보통 0으로 나누는 것은 금지되어 있으나

실제로 나눗셈을 할때 양수를 0에 가까운 값으로 나누어줄수록 값이 커지는 것을 알 수 있다.

때문에 0에 가까운 값이 아닌 0으로 나누어 줄 경우 무한이 나올 수 있으며 이러한 특징 때문에 0으로 나누는 것은

통념상 금지되어 있지만 자바스크립트에서는 무한으로 출력하며 음수를 나누어주면 -무한이 출력된다.

 

마지막으로 i가 셀 수 있는 숫자인가? 라는 질문에서 false라고 출력하는 것을 알 수 있다.

 

8. String의 속성과 메소드

trim()은 문자열 앞 뒤에 있는 공백과 줄바꿈을 없애준다.

const a = '   가나다\n라마 바 사\n\n'
const b = '경계선'
console.log(a)
console.log(b)
console.log(a.trim())
console.log(b)

// 결과
//  가나다
//라마 바 사
//
//경계선
//가나다
//라마 바 사
//경계선

a는 문자열 앞이 띄어쓰기, 뒤는 줄바꿈으로 이루어 져있다.

그러나 trim을 사용하자 문자열의 앞 뒤에 있던 띄어쓰기와 줄바꿈이 사라졌다.

 

split()는 문자열을 다른문자열을 기준으로 잘라서 배열을 만든다.

const a = '하나, 둘, 셋, 넷, 다섯'
console.log(a.split(','))

// 결과
// ["하나", " 둘", " 셋", " 넷", " 다섯"]

 

 

'Language > JavaScript' 카테고리의 다른 글

JavaScript 공부정리 - 객체 - 리터럴  (1) 2022.10.07
JavaScript 공부정리 - 객체 - 중간편  (1) 2022.10.01
JavaScript 공부정리 - 배열  (0) 2022.09.28
JavaScript 공부정리 000  (0) 2022.09.28
JavaScript 공부정리 002  (0) 2022.09.28

시작하기 전에...

 

이번엔 배열을 집중적으로 다룬다.

 

1. 배열선언

2. 배열접근

3. 배열내 값의 갯수 확인

4. 배열에 요소 추가(뒷 부분에 추가, 특정 위치에 추가)

5. 배열 요소 제거


1. 배열 선언

const arr = [1, 2, 3, 'string', true]

배열을 선언하고 숫자와 문자열, 불 값을 넣었다.

이 선언문을 기준으로 아래를 설명한다.

 

2. 배열 접근

맨 위의 코드에서 이어진다.

arr[0]			// 1
arr[3]			// "string"

arr의 0번째 값은 1, 3번째 값은 "string"이다.

 

3. 배열내 값의 갯수 확인

맨 위의 코드에서 이어진다.

 

arr.length			//5

length라는 속성으로 구해온다.

5개의 값이 들어가 있으므로 5가 리턴된다.

 

4. 배열에 요소 추가(뒷 부분에 추가, 특정 위치에 추가)

맨 위의 코드에서 이어진다.

arr.push('우유')			//[1, 2, 3, 'string', true, "우유"]

push라는 속성으로 넣는다.

 

다른 방법도 있다.

arr[10] = '윈도'

//결과
//[1, 2, 3, "string", true, empty, empty, empty, empty, empty, "윈도"]

이런식으로 넣어줄 수도 있다.

 

 

이번엔 특정 위치에 요소를 추가해 보자

마찬가지로 맨 위의 코드에서 이어진다.

arr.splice(1, 0, '엉덩이')

// 결과
// [1, "엉덩이", 2, 3, "string", true]

후술하겠지만 splice는 원래 값을 지우는 데 사용한다 (자세한건 아래 참조)

그런데 역으로 값을 추가할 때 사용할 수도 있다.

1번 인덱스에 값을 0개 제거하고 '엉덩이' 값을 추가한다고 해석할 수있다.

 

 

 

!!여기서 의문

const는 분명 상수다.

그런데 push속성을 사용하자 값이 변경된 것을 볼 수 있다.

이건 정상적인 상황일까?

const arr = [1, 2, 3, 'string', true]
console.log(arr)
arr.push('우유')
console.log(arr)

// 결과
// [1, 2, 3, "string", true]
// [1, 2, 3, "string", true, "우유"]

 

일단은 넘어가자

 

 

5. 배열 요소 제거

맨 위의 코드에서 이어진다.

아래는 인덱스 번호를 기반으로 지우는 명령이다.

arr.splice(1, 2)

// 결과
// [1, "string", true]

splice 속성으로 제거한다.

1번 인덱스부터 총 2개를 제거한다는 의미다.

즉 1번 인덱스와 2번 인덱스의 값이 사라졌고

1번 인덱스 자리에는 3번 인덱스의 값이 들어와 있다.

 

 

이번엔 값을 기반으로 지워보자

const arr = [1, 2, 3, 'string', true]
const index = arr.indexOf("string")
arr.splice(index, 1)

console.log(arr)

// 결과
// [1, 2, 3, true]

최초의 배열에서

"string"값을 가진 변수 index를 만들고

그 index와 같은 값을 가진 부분을 없애도록 명령을 만들었다.

 

 

참고로 이 명령은 한 번 실행 된다

즉 배열안에 string 값이 두 번 들어가 있을 경우

낮은 인덱스 값부터 없어진다.

const arr = [1, 2, 3, 'string', 'string', true, 'string']
const index = arr.indexOf("string")
arr.splice(index, 1)
arr.splice(index, 1)
console.log(arr)

// 결과
// [1, 2, 3, true, "string"]

arr 배열에 string 값이 3개가 들어가 있다.

그리고 string을 없애라는 명령을 두 번 실행 했다

그러자 가장 마지막에 있는 string은 살아남았다.

 

 

 

'Language > JavaScript' 카테고리의 다른 글

JavaScript 공부정리 - 객체 - 중간편  (1) 2022.10.01
JavaScript 공부정리 - 객체 - 기본편  (1) 2022.09.28
JavaScript 공부정리 000  (0) 2022.09.28
JavaScript 공부정리 002  (0) 2022.09.28
JavaScript 공부정리 001  (0) 2022.09.28

시작하기전에......

이번에는 JS의 기본적인 내용 가운데 모르고 넘어갔거나

혹은 알아두면 좋은 사항에 대해 정리한다.

 

1. 키워드 목록

1-1. 분류

2. 특수문자열

2-1. 문자열 관련 추가사항

3. 상수와 변수

4. 증감연산자와 전위연산과 후위연산

5. 문자열과 참 거짓의 입력

6. 자료형 변환

6-1. 다른자료형 -> 숫자 자료형

6-2. 다른자료형 -> 문자열

6-3. 다른자료형 -> 불자료형


1. 키워드 목록

JS에는 변수명이나 함수명으로 쓸 수 없는 키워드가 있다.

이 키워드들은 각자 저마다의 역할을 가지고 있다.

 

 

await break case catch class const
continue debugger default delete do else
export extends finally for function if
import in instanceof new return super
switch this throw try typeof var
void while with yield let static
true false null as from get
of set target      

각 키워드의 기능에 대해선 다음에 알아보도록 하고

메소드나 속성은 제외되어 있다.

 

1-1. 분류

 

괄호가 있는 형태는 함수, .을 사용했다면 속성, .과 ()를 같이 사용한 형태는 메소드로 볼 수 있다.

alert('Hello World') 함수
Array.length 속성
input 변수
prompt('Message', Defstr) 함수
Math.PI 속성
Matg.abs(-273) 메소드

표는 예시



2. 특수 문자열

\"" 따옴표 자체를 출력하기 위해 사용
따옴표와 그 안의 내용이 출력된다
\n 줄바꿈
\t 탭
\\ 역슬래시

 

2-1. 문자열 관련 추가사항


문자열 내부 글자 선택
예시
'안녕하세요'[0] 안
'안녕하세요'[1] 녕
'안녕하세요'[2] 하


console.log('this is 'string'') 애러
console.log('this is "string"') 정상출력
따옴표를 한 종류만 쓰면 햇갈릴 수 있다.

3. 상수와 변수

상수: 항상 같은 수, 변하지 않기 때문에 저장효율이 좋음
변수: 바꿀 수 있는 수, 저장효율이 나쁨

상수는 선언할 때 값을 지정해주어야 한다.

 

4. 증감연산자와 전위연산과 후위연산

증감연산자의 전위연산과 후위연산
전위연산: ++i 실행 전에 값을 더함
후위연산: i++ 실행 하고 값을 더함

alert(a++) a이 10이라면 10 출력됌( 이후 1을 더함)
alert(++b) b가 10이라면 11출력

5. 문자열과 참 거짓의 입력

문자열을 입력받을 때 사용하는 함수는 prompt() 이다.

 

const input_String = prompt('message', '_default')

 

 

위 함수를 작성하면 이런 창이 뜬다.

input_String은 내가 정한 이름이고

message는 제목처럼 뜨는 내용이며

_default는 기본적으로 들어가 있는 내용이다 (직접 지워서 수정해야함)

 

 

참 거짓을 요구하는 메시지를 띄우는 창은 comfirm() 함수이다.

const input_bool = confirm()

 

 

 

6. 자료형 변환

6-1. 다른자료형 -> 숫자 자료형

Number('273')

"273"이라는 문자열을 273이라는 숫자로 변환

 

만약 변환이 불가능할 경우 NaN을 출력

 

"52" - 0

true - 0

위와 같은 경우에도 변환이 가능하다.

위는 52라는 문자열이 숫자로 변환 되며

 

아래의 경우도 true는 기본적으로 1이라고도 할 수 있으니 1이 출력된다.

참고로 false는 0으로 해석되며 true + 1 은 2가 된다.

 

6-2. 다른자료형 -> 문자열

String(52)

52라는 숫자를 문자열로 변환한다.

 

273 + ""

true + ""

위와 같은 경우도 변환이 가능하다

위는 "273"이라는 문자열이 되고

아래는 "true"라는 문자열이 된다.

 

6-3. 다른자료형 -> 불자료형

다른 자료형을 참 거짓으로 바꾼다.

전에도 말한 적 있지만 자바스크립트는 모든 것을 참 거짓으로 구분할 수 있다.

Boolean(NaN)

0, NaN, "", null, undefined은 false로 반환되고

선언만 되었을 뿐 값이 없는 변수 또한 false로 반환된다.

그 이외의 모든 값은 전부 true로 반환된다.

 

참고로 0은 false지만 "0"은 true인데 "0"인 빈 문자열이 아니기 때문이다

 

 

 

 

 

 

 

 

 

 

 

 

 

'Language > JavaScript' 카테고리의 다른 글

JavaScript 공부정리 - 객체 - 기본편  (1) 2022.09.28
JavaScript 공부정리 - 배열  (0) 2022.09.28
JavaScript 공부정리 002  (0) 2022.09.28
JavaScript 공부정리 001  (0) 2022.09.28
코딩테스트 연습 ~10 JavaScript  (1) 2022.09.24

시작하기 전에...

 

이번에 배울 내용은 다음과 같다.

1. 즉시호출함수

1-1. 엄격모드

2. 익명함수와 선언적 함수


1. 즉시호출함수

 

여러개의 스크립트를 한 곳으로 모아서 호출할 경우 변수의 이름이 겹치는 문제가 발생할 수 있다.

이 문제를 피하기 위해 함수 블록을 사용해 충돌 문제를 해결할 수 있다.

    let a = 123
    console.log(a)
    {
        let a = 'a의 값'
        console.log(a)
    }
    
    //결과
    //123
    //a의 값

보시다시피 블록을 나누어 주면 변수명이 겹치지 않는다.

 

이와 같은 현상은 중괄호로 나누어준 모든 곳에서 발생한다

때문에 for문을 사용할 때도 for문을 각자 따로 격리해서 선언하면 i값이 겹치지 않는다.

하지만 for문 안에 또 for문을 사용할 경우 i값이 겹치기 때문에 안에 있는 for문은 다른 변수명을 써줘야 한다.

이 경우 에러가 뜨는 것은 아니지만 프로그래머의 의도와는 다른 결과를 낼 수 있다.

for(i=0; i <5 ; i++){
    console.log(i)
    for(i=40; i < 45 ; i++){
        console.log(i)
    }
    console.log('경계선')
    console.log(i)
}

//결과
//0
//40
//41
//경계선
//42

i의 시작값은 0이다.

때문에 처음에 0이 나오지만 그 다음 for문에서 i는 40으로 재정의 되었고 i가 42가 될때까지 반복한다.

그리고 i는 42가 되었는데 이게 for문을 나와서도 그대로 적용되는 바람에

바깥쪽 for문은 한 번만 실행되었다.

 

for(i=0; i <3 ; i++){
    console.log(i)
    for(j=40; j < 42 ; j++){
        console.log(j)
    }
    console.log('경계선')
    console.log(i)
}

//결과값
//0
//40
//41
//경계선
//0
//1
//40
//41
//경계선
//이후 생략

결과값이 너무 길어져서 일부를 생략했다

안쪽 for문을 j로 바꾸어주자 의도에 맞게 실행되는 것을 볼 수 있다.

 

 

이렇듯 여러곳에서 스크립트를 가져와서 변수명이 겹치는 문제가 발생하는 것을 즉시호출함수문제라고 하는데

이는 상술했듯 블록{}을 사용하여 해결할 수 있다.

 

1-1. 엄격모드

일반적으로 자바스크립트는 코드를 대충 작성해도 얼추 알아먹는다.

data = 10
console.log(data)

위 코드는 let이라는 선언자가 없음에도 불구하고 정상작동한다.

 

하지만 다음과 같은 경우에는 그렇지 않다.

'use strict'
data = 10			//애러!!
console.log(data)

'use strict'이라는 명령은 코드를 엄격하게 검사하라는 특수 키워드다

이것을 읽은 시점부터, 자바스크립트는 코드를 엄격하게 검사한다.

때문에 선언문이 없는 data를 보고 바로 애러를 일으키는 것이다.

 

자바스크립트는 프로그래머가 몇 가지 실수를 해서 오류가 발생하도 유도리있게 넘어가는 경우가 종종 있다.

그러나 이것은 치명적인 실수를 유발하기도 하기 때문에 일반적으로는 사용하는 것이 좋다.

 

그리고 'use strict'을 읽은 시점부터 엄격모드가 적용되기 때문에

함수 내부 최상단에 작성할 경우, 그 함수에만 엄격모드를 적용시킬 수도 있다.

 

2.익명함수와 선언적 함수

익명함수는 그 함수가 위치한 줄을 읽을 때 생성되는 반면 선언적 함수는 위치에 상관없이 일단 생성되고 본다.

때문에 선언적 함수는 어디에 위치해 있든지 상관 없는 반면 익명함수는 위치를 잘 선정해 주어야 할 필요가 있다.

 

그렇다면 이 두가지를 같은 이름을 써서 선언하면 어떻게 될까?

함수 = function(){
    console.log('익명함수')
}
function 함수 (){
    console.log('선언함수')
}
함수()

//결과
//익명함수

똑같은 함수 명을 가진 함수를 선언하 되 하나는 선언함수, 하나는 익명함수로 선언했다.

그러나 실행해본 결과 익명함수가 나오는 것을 알 수 있다.

 

이는 선언함수가 먼저 실행되었지만 이후 실행된 익명함수에 의해 함수의 내용이 덮어진 것이다.

즉 나중에 실행된 함수가 먼저 실행된 함수의 내용을 덮어버렸기에 이런 현상이 나타난 것이다.

 

당연한 이야기겠지만 혹시라도 함수선언할 때 함수명을 겹치는 행동은 대단히 위험한 일이다.

그러니 위와같은 코딩은 가급적 지양하도록 하자

 

여담이지만 이번에 새로 안 사실인데 한글로 함수명을 작성해도 잘 돌아간다.

 

그렇다면 익명함수는 어떤 때에 자주 사용하는가?

 

<script>
function 함수 (){
    console.log('선언함수 1')
}
</script>

<script>
function 함수 (){
    console.log('선언함수 2')
}
</script>

<script>
함수()
</script>

//결과
//선언함수 1
//선언함수 2

 

HTML에서 자바스크립트를 사용한 모습이다.

코드를 살펴보면 분명 함수는 한 번 실행했지만

내용이 덮어씌워지지 않고 두 함수가 동시에 실행된 것을 볼 수 있다.

 

이런식으로 스크립트 블록을 나누어 버리면 선언적 함수의 실행 순서는 예측하기가 어렵고

만에하나 함수의 이름이 겹칠 경우, 예상치 못한 결과가 튀어나올 수 있기 때문에 이런 경우 익명함수를 더 선호하는 편이다.

 

따라서 한가지로 통일하는 것이 오류의 위험을 줄일 수 있고

가급적 익명함수를 쓰는 쪽이 더 유리하다.

 

 

 

시작하기 전에

 

이번에 알아볼 내용은

1. 전개연산자

2. 파라미터의 기본 값

3. 콜백함수

3-1. 콜백함수를 쓰는 메소드

3-1-1. forEach()

3-1-2. map()

3-1-3. filter()

4. 화살표함수

5. 타이머함수


1. 전개연산자

파라미터에 ...을 쓰면 배열로 인식한다.

function s(a, b, ...c)
	console.log(a, b, c)
}

s(1, 2)
s(1, 2, 3)
s(1, 2, 3, 4, 5)

//결과
//1 2 []
//1 2 [3]
//1 2 [3, 4, 5]

 

a와 b는 일반 숫자로 인식하였지만 3부터는 배열로 인식하는 것을 볼 수 있다.

 

주의사항

...c 와 같은 형태는 반드시 마지막 파라미터로 와야하며 중간에 올 경우 애러가 난다.

 

function s(...i){
	console.log(i)
}

const array = [1, 2, 3, 4]
s(array)
s(...array)

//결과
//[[1, 2, 3, 4]]
//[1, 2, 3, 4]

파라미터에서 이미 배열화해서 받는다고 되어 있다.

그리고 array는 배열로 만들어졌고

그것을 s에 넣으니 배열안에 배열이 있는 형태가 완성된다.

반면, 전개연산자를 써서 넣으니 배열이 전개가 되면서 들어간 탓에 일반적인 배열의 모습으로 들어갔다.

 


2. 파라미터의 기본 값

파라미터에 기본값을 넣어줄 수 있다.

function func (a, b= 1000, c= 24){
	console.log(a, b, c)
}

func()
func(50, 2000)
func(50, 2400, 50)
func(50, undefined, 28)

//결과
//undefined 1000 24
//50 2000 24
//50 2400 50
//50 1000 28

a는 기본값이 정의되어 있지 않기 때문에 아무것도 넣지 않을 경우 undefined가 나오지만

그 외에는 기본 값이 정의되어 있기에 기본값이 출력되는걸 알 수 있다.

마지막 테스트를 보면 b에 undefined가 들어있는게 보이는데 이를 통해 기본값이 나오도록 활용할 수 있다.


3. 콜백함수

다른 프로그래밍 언어에선 찾기 힘든 개념으로 함수를 파라미터로 받는다.

function call(c_b){
    for (i = 0; i<3; i++){
        c_b(i)
    }
}
function print (k)
{
    console.log(`${k}번째 함수 호출`)
}
call(print)

//결과
//0번째 함수 호출
//1번째 함수 호출
//2번째 함수 호출

call 함수의 파라미터에 print라는 함수를 넣었다.

그리고 그 print라는 함수는 call함수의 반복문에 들어갔고 for문의 i값을 파라미터로 넣었다.

그 결과 print 함수에 파라미터 i를 받아 실행된 결과가 나왔다.

 

 

 

 

3-1. 콜백함수를 쓰는 메소드

3-1-1. forEach()

let numbers = [273, 52, 103, 32, 57]
numbers.forEach(function (v, i, a){
    console.log(`${i}번째 요소 ${v} 배열은 ${a}`)
    })

//결과
//0번째 요소 273 배열은 273,52,103,32,57
//1번째 요소 52 배열은 273,52,103,32,57
//2번째 요소 103 배열은 273,52,103,32,57
//3번째 요소 32 배열은 273,52,103,32,57
//4번째 요소 57 배열은 273,52,103,32,57

forEach 메소드는 function을 파라미터로 받고 순서대로 배열의 값, 배열의 번호, 배열 전체 값을 받는다.

때문에 보통 value, index, array로 입력하곤 하나 여기선 그냥 첫글자(via)로 줄였다

 

forEach는 리턴값이 없다.

때문에 위의 경우 numbers에 forEach를 달아줘도 numbers의 값은 변하지 않는다.

그러나 numbers 의 특성을 이용해서 마치 for문 처럼 사용할 수는 있다.

3-1-2. map()

map은 지금까지 사람들이 쓰는것을 여러번 봐온 만큼 그만큼 중요한 메소드라고 여겨진다.

map또한 배열에 사용하며 forEach랑 같은 형태의 파라미터를 받는다.

let numbers = [273, 52, 103, 32, 57]
numbers.map(function (v, i, a){
    console.log(`${i}번째 요소 ${v} 배열은 ${a}`)
})

//결과
//0번째 요소 273 배열은 273,52,103,32,57
//1번째 요소 52 배열은 273,52,103,32,57
//2번째 요소 103 배열은 273,52,103,32,57
//3번째 요소 32 배열은 273,52,103,32,57
//4번째 요소 57 배열은 273,52,103,32,57

아까의 코드에서 forEach만 map으로 바꿨을 뿐인데 같은 결과가 나온다

 

그렇다면 이 둘은 어떻게 다른가

forEach는 return을 하지 못한다.

그러나 map은 가능하다.

let ar = [1,2,3,4,5];
let a = ar.forEach(function(value){
	return value;
});
console.log(a) +1; 

//결과
//undefined
let ar=[1,2,3,4,5];
let a = ar.map(function(value){
	return value+1;
});
console.log(a); 

//결과
//[2, 3, 4, 5, 6]

forEach와 map의 결과물 차이

forEach를 한번 쓰고 나면 a는 undefined가 되지만

map의 경우 리턴을 통해 a값을 변경할 수 있다.

 

 

let a = [273, 52, 103, 32]
let b = a.map(function (v, i){
  a[i] = a[i] + 1
  return a;
  })

console.log(b)
console.log(a)

//결과
//[[274, 53, 104, 33], [274, 53, 104, 33], [274, 53, 104, 33], [274, 53, 104, 33]]
//[274, 53, 104, 33]
let a = [273, 52, 103, 32]
let b = a.forEach(function (v, i){
  a[i] = a[i] + 1
  return a;
  })

console.log(b)
console.log(a)

//결과
//undefined
//[274, 53, 104, 33]

 

위 두 결과를 보자

forEach는 리턴 명령을 무시한다

때문에 b에는 어떠한 값도 리턴되지 않았고 이로인해 undefined가 출력되었다

 

반면 map은 리턴 명령을 수행한다

때문에 b에 명령이 총 4번(a의 길이만큼) 반복되어 결과값이 4번 들어간걸 볼 수 있다.

 

 

 

 

참고사항

여기선 map이나 forEach에 파라미터 3종류를 다 넣었지만, 실제론 필요한 값만 넣어서 쓰는 경우가 많다.

즉 numbers.map(function (v){~~~})형태로 쓰는 경우가 많다.

 

3-1-3 filter()

let numbers = [1, 2, 3, 4, 5]
let Fnum = numbers.filter(function (v){
    return v % 2 ===0
})

console.log(`원래 값 ${numbers}`)
console.log(`필터 값 ${Fnum}`)
//결과
//원래 값 1,2,3,4,5
//필터 값 2,4

마찬가지로 배열에 사용한다.

역시 value, index, array 3가지 값을 받지만 한 가지만 사용하였다

역시 이전의 map과 비슷해보이지만 한가지 다른 점은 저 리턴 값에 들어간 조건을 만족하는 값만 내놓고 나머지는 버린다는 것이다.

 

let numbers = [1, 2, 3, 4, 5]
let Fnum = numbers.filter(function (v, i){
    let a = v%2 ===0
    return a;

때문에 이런식으로 쓸 수도 있다.

결과 값은 앞선 코드와 같다.

 

let numbers = [1, 2, 3, 4, 5]
let Fnum = numbers.map(function (v, i){
    return v%2 ===0;
})

console.log(`원래 값 ${numbers}`)
console.log(`필터 값 ${Fnum}`)
//결과
//원래 값 1,2,3,4,5
//필터 값 false,true,false,true,false

filter를 map으로 바꿔보았다.

이번엔 불리언 값으로 나오는 것을 알 수 있다.

 

 


4. 화살표 함수

콜백함수를 쉽게 입력하기 위해 사용한다.

대강 이런식으로 작성한다.

(파라미터) => { 내용 }

──────────────────────────────────또는──────────────────────────────────

(파라미터) => 리턴값

 

콜백함수를 위해 사용한다니 여기에 대표적인 콜백함수인 map을 써보겠다

//화살표 함수 사용
const array =[0,1,2,3,4,5,6]
console.log(array.map((value) => value + 1))

//화살표 함수 미사용
const array=[0,1,2,3,4,5,6];
let a = array.map(function(value){
	return value+1;
});
console.log(a); 

//결과 (위 아래 동일)
//[ 1, 2, 3, 4, 5, 6, 7 ]

보시다시피 화살표 함수를 통해 보다 더 짧게 나타낼 수 있다.

 

let array=[0,1,2,3,4,5,6];
array
    .filter((value) => value % 2 ===0)
    .map((value) => value *value)
    .forEach((value) => {console.log(value)})

//위 코드는 아래 코드를 보기 좋게 정렬한 것이다.
array.filter((value) => value % 2 ===0).map((value) => value *value).forEach((value) => {console.log(value)})


//결과
//0
//4
//16
//36

자 이 코드를 해석해보자

배열이 선언되어 있고

필터를 통해 짝수인 값을 제외한 나머지 값이 버려졌다.  => [0, 2, 4, 6]

맵을 통해 각 값들이 제곱이 되었다 => [0, 4, 16, 36]

이후 forEach에 의해 내용이 분해되었다 => 0 4 16 36

 

 


5. 타이머함수

자바스크립트에는 특정시간마다, 또는 특정시간 이후에 콜백함수를 호출할 수 있는 타이머 함수가 있다.

 

setTimeout(함수, 시간): 시간 후 함수 한 번 호출

setInterval(함수, 시간): 특정시간마다 함수 호출

 

시간단위는 기본적으로 밀리초 단위로 1000이 1초이다.

타이머를 종료할 때는 다음 함수를 사용한다.

 

clearTimeout(타이머_ID): setTimeout함수로 설정한 타이머를 제거

clearInterval(타이머_ID): setInterval함수로 설정한 타이머를 제거

 

여기서 타이머_ID란 setTimeout함수를 호출했을 때 리턴값으로 나오는 숫자이다.

let id
let count = 0
id = setInterval(() => {
    console.log(`${count} 번째`)
    count++
}, 1*1000)


setTimeout(()=> {
    console.log('종료')
    clearInterval(id)
}, 5*1000)                     


//결과
//0 번째
//1 번째
//2 번째
//3 번째
//종료

 

화살표 함수를 보자

우선 지금까지 배운 것과 다르게 화살표 좌측이 비어있고 파라미터도 비어있다.

다만 내용으로 몇번째인지 출력하는 문구와 count값을 1 증가시키는 내용이 있다.

이 말은 1초마다 id를 한번 실행하라는 뜻이다.

그리고 setTimeout의 내용은

id라는 setInterval로 실행된 함수를 정지 시키라는 뜻이며

정지시키기 전에 종료 메시지를 띄우게 되어 있다.

이때 정지 조건은 5초가 되었을 때로 되어 있다.

 

 

 

 

 

 

 

 

'Language > JavaScript' 카테고리의 다른 글

JavaScript 공부정리 000  (0) 2022.09.28
JavaScript 공부정리 002  (0) 2022.09.28
코딩테스트 연습 ~10 JavaScript  (1) 2022.09.24
코딩테스트 연습 1 - 직사각형 별 찍기.JavaScript  (1) 2022.09.23
JavaScript 기본  (1) 2022.09.23

 

지난번에 올린 코딩테스트 연습의 연장이다.

 

문제설명 -> 제한 조건  -> 최초 답안 -> 개선 답안 -> 다른사람이 작성한 모범답안

 

순서대로 진행한다.


문제설명

두 정수 a, b가 주어졌을 때 a와 b 사이에 속한 모든 정수의 합을 리턴하는 함수, solution을 완성하세요.
예를 들어 a = 3, b = 5인 경우, 3 + 4 + 5 = 12이므로 12를 리턴합니다.

 

제한 조건

a와 b가 같은 경우는 둘 중 아무 수나 리턴하세요.
a와 b는 -10,000,000 이상 10,000,000 이하인 정수입니다.
a와 b의 대소관계는 정해져있지 않습니다.

 

최초 답안

function solution(a, b) {   
    if (a > b){
        let c = a-b;
        let d = b
        for (i = 0; i <c; i++){
            d = d+1;
            b = b+d;
        }        
        return b;
    }
    if (a < b){
        let c = b-a;
        let d = a
        for (i = 0; i <c; i++){
            d = d+1;
            a = a+d;
        }
        return a;        
    }
    if(a=b) return a;
}

길다....

 

개선 답안

 

 

타인이 작성한 모범답안

function solution(a, b){
    return (a+b)*(Math.abs(b-a)+1)/2;
}

 

모범답안을 볼 때마다 느끼는 거지만 이러한 수학적 계산이 필요한 문제에선

Math와 삼항연산자의 영향력이 크게 미치는 것 같다.

지금까지 나는 사실상 4칙연산 하나만 가지고 푸는 격이었기에

Math에 대한 공부의 필요성을 느끼게 된다.

 

 

 


문제설명

문자열 s를 숫자로 변환한 결과를 반환하는 함수, solution을 완성하세요.

예를들어 str이 "1234"이면 1234를 반환하고, "-1234"이면 -1234를 반환하면 됩니다.
str은 부호(+,-)와 숫자로만 구성되어 있고, 잘못된 값이 입력되는 경우는 없습니다.

 

 

제한 조건

  • s의 길이는 1 이상 5이하입니다.
  • s의 맨앞에는 부호(+, -)가 올 수 있습니다.
  • s는 부호와 숫자로만 이루어져있습니다.
  • s는 "0"으로 시작하지 않습니다.

최초 답안

function solution(s) {
    return parseInt(s);
}

개선 답안

 

타인이 작성한 모범답안

function solution(s) {
    return s/1;
}

형 변환 명령없이 그저 1로 나누라는 명령 하나만으로 자연스럽게 형변환을 했다.


문제설명

0부터 9까지의 숫자 중 일부가 들어있는 정수 배열 numbers가 매개변수로 주어집니다. numbers에서 찾을 수 없는 0부터 9까지의 숫자를 모두 찾아 더한 수를 return 하도록 solution 함수를 완성해주세요.

 

입출력 예 #1
5, 9가 numbers에 없으므로, 5 + 9 = 14를 return 해야 합니다.

 

제한 조건

1 ≤ numbers의 길이 ≤ 9
0 ≤ numbers의 모든 원소 ≤ 9
numbers의 모든 원소는 서로 다릅니다.

최초 답안

function solution(numbers) {
    let result = 0;
    for (i = 0; i < 10; i++){
        if (numbers.includes(i)){  
        }else{
            result += i
        }        
    }
    return result;
}

.includes()

괄호안의 파라미터를 포함하는지에 대한 여부를 묻는다.

개선 답안

 

타인이 작성한 모범답안

function solution(numbers) {
    return 45 - numbers.reduce((cur, acc) => cur + acc, 0);
}

여기서 45는 0에서 9까지의 합으로 보인다.

acc와 cur은 변수명이 바뀌었다고 하는데 좀 더 알아봐야겠다.


문제설명

어떤 정수들이 있습니다. 이 정수들의 절댓값을 차례대로 담은 정수 배열 absolutes와 이 정수들의 부호를 차례대로 담은 불리언 배열 signs가 매개변수로 주어집니다. 실제 정수들의 합을 구하여 return 하도록 solution 함수를 완성해주세요.

 

입출력 예 #1
signs가 [true,false,true] 이므로, 실제 수들의 값은 각각 4, -7, 12입니다.
따라서 세 수의 합인 9를 return 해야 합니다.

 

제한 조건

absolutes의 길이는 1 이상 1,000 이하입니다.
absolutes의 모든 수는 각각 1 이상 1,000 이하입니다.
signs의 길이는 absolutes의 길이와 같습니다.
signs[i] 가 참이면 absolutes[i] 의 실제 정수가 양수임을, 그렇지 않으면 음수임을 의미합니다.

 

최초 답안

function solution(absolutes, signs) {    
    const l = absolutes.length;
    let a = 0;    
    for (i = 0 ; i<l; i++){
        (signs[i]==true ? a += absolutes[i] : a -= absolutes[i])
    } 
    return a;
}

삼항 연산자를 사용해 보았다.

확실히 코드가 줄었다.

 

개선 답안

 

타인이 작성한 모범답안

function solution(absolutes, signs) {
    return absolutes.reduce((acc, val, i) => acc + (val * (signs[i] ? 1 : -1)), 0);
}

이번엔 화살표 함수가 사용된 것을 볼 수 있다.


문제설명

정수를 담고 있는 배열 arr의 평균값을 return하는 함수, solution을 완성해보세요.

 

제한 조건

arr은 길이 1 이상, 100 이하인 배열입니다.
arr의 원소는 -10,000 이상 10,000 이하인 정수입니다.

최초 답안

function solution(arr) {
    let a = 0;
    let b = 0;
    for(let i = 0; i < arr.length ; i++){
        a += arr[i]
        console.log(a)
        b = a/arr.length
    }
    return b
}

길다.... 정말로...

개선 답안

타인이 작성한 모범답안

function average(arr){
  return arr.reduce((a, b) => a + b) / arr.length;
}

문제설명

프로그래머스 모바일은 개인정보 보호를 위해 고지서를 보낼 때 고객들의 전화번호의 일부를 가립니다.
전화번호가 문자열 phone_number로 주어졌을 때, 전화번호의 뒷 4자리를 제외한 나머지 숫자를 전부 *으로 가린 문자열을 리턴하는 함수, solution을 완성해주세요.

 

제한 조건

phone_number는 길이 4 이상, 20이하인 문자열입니다.

최초 답안

function solution(phone_number) {
    const leg = phone_number.length - 4;
    let a = ""
    let b = phone_number.substring(leg, phone_number.length)
    let answer = ""
    for(let i = 0 ; i < leg ; i++){
        a = a + "*"
    }
    answer = a + b
    return  answer;
}

 

 

꽤나 어려웠다.

스트링을 조작하는 메소드에 대해 잘 모르다보니 꽤 오랜시간 고민한거 같다.

 

그나저나 이쯤되니 내가 너무 조건문과 반복문에 의지하는 코딩을 하고 있는게 아닌가 싶은 생각이 든다.

개선 답안

 

타인이 작성한 모범답안

 

function hide_numbers(phone_number) {
  return phone_number.replace(/\d(?=\d{4})/g, "*");
}

이건 또 뭔 내용일까....

사람들 반응을 보니 정규식이라는거 같은데... 좀 더 나중에 알아도 될 법한 내용이지 않을까 싶다.

 

 

 

function hide_numbers(phone_number){
  var result = "*".repeat(phone_number.length - 4) + phone_number.slice(-4);
  return result;
}

이쯤되면 자괴감이 들기 시작한다.

 

왜이리 다들 짧고 간단하게 문제를 푸는가

 

 


문제설명

행렬의 덧셈은 행과 열의 크기가 같은 두 행렬의 같은 행, 같은 열의 값을 서로 더한 결과가 됩니다. 2개의 행렬 arr1과 arr2를 입력받아, 행렬 덧셈의 결과를 반환하는 함수, solution을 완성해주세요.

 

제한 조건

행렬 arr1, arr2의 행과 열의 길이는 500을 넘지 않습니다.

 

최초 답안

function solution(arr1, arr2) {    
    const array = []
    
    for(i=0; i<arr1.length; i++){
    let arr = []
        for(j=0; j<arr2.length; j++){            
            let a = 0;
            a = arr1[i][j]+arr2[i][j]
            if (isNaN(a)==true) {
                continue;
            }
            arr.push(a)
        }
        array.push(arr)
        arr = []
    }    
    return (array);
}

처음으로 오답이 났다.

테스트를 통과했고

테스트 케이스에 더러운 값을 추가했음에도 불구하고

막상 채점을 하자 반 정도에서 탈락해고 오답처리 당했다.

 

문제는 대체 어디가 문제인지 모르겠다는 것이다. 

개선 답안

function solution(arr1, arr2) {       
    const array = []  
    for(i=0; i<arr1.length; i++){
    let arr = []        
        for(j=0; j<arr2[i].length; j++){            
            arr.push(arr1[i][j]+arr2[i][j])
        }
        array.push(arr)
        arr = []
    }    
    return (array);
}

그리하여 개선한 답안

차이점이라면 let a를 쓰는 것 대신에 그냥 array에 직접 푸쉬를 해주는 형태로 바꾸면서 자연스럽게 NaN을 판별하는

if문이 사라졌다.

 

그러나 이건 그저 코드길이 몇개 줄여주는 정도에서 끝이고 중요한건 아니다

 

가장 중요한건 바로 두 번째 for문의 조건문에서 [i]가 추가된 것이다.

 

arr2 행렬에서 행의 번호의 길이를 가져오는 것이다.

 

즉 테스트케이스에선 행의 길이에서 차이가 있었던 부분이 있던 모양이다.

 

타인이 작성한 모범답안

function solution(arr1,arr2){
    return arr1.map((a,i) => a.map((b, j) => b + arr2[i][j]));
}

 

......

이쯤되면 나는 코딩에 재능이 없는 건가 싶은 생각만 든다.

 

대체 저 map이라는 명령은 또 뭐란 말인가.

 


정리

Math

map

.reduce를 포함한 텍스트 조작명령

 

이렇게 3가지에 대해서 제대로 공부를 하고

 

삼항연산자

화살표함수

이 두가지 또한 익숙해질 필요가 있음을 느꼈다.

 

'Language > JavaScript' 카테고리의 다른 글

JavaScript 공부정리 000  (0) 2022.09.28
JavaScript 공부정리 002  (0) 2022.09.28
JavaScript 공부정리 001  (0) 2022.09.28
코딩테스트 연습 1 - 직사각형 별 찍기.JavaScript  (1) 2022.09.23
JavaScript 기본  (1) 2022.09.23

시작하기 전에

 

 

나에게 주어진 문제

풀이 과정

이 문제를 통해 알게 된 것

 

순서대로 진행한다.

 


 

문제
이 문제에는 표준 입력으로 두 개의 정수 n과 m이 주어집니다.
별(*) 문자를 이용해 가로의 길이가 n, 세로의 길이가 m인 직사각형 형태를 출력해보세요.
제한조건
  • n과 m은 각각 1000 이하인 자연수입니다.
최초코드
process.stdin.setEncoding('utf8');
process.stdin.on('data', data => {
    const n = data.split(" ");
    const a = Number(n[0]), b = Number(n[1]);
    console.log(a);
    console.log(b);
});

 

????

 

처음엔 이게 뭔 개소린가 싶었다.

 

그냥 print('*****')를 3번 입력하면 되는거 아닌가? 라고 생각해서 코드 다 지워버리고

print만 3줄 적었는데 print 가 아예 먹질 않았다.

 

대체 이게 뭐 어쩌라는 걸까 싶어서 알아보니

저기 저 최초의 코드를 이용해서 문제를 풀라는 소리였다.

 

이 실행 결과창도 처음엔 이해를 못했는데

입력값이라는건 말 그대로 5 와 3이 입력되었고

 

그 결과로

*****

*****
*****

를 기대하였으나

 

실제로 출력된건

5 3

이었다는 뜻이다.

 


최초코드
process.stdin.setEncoding('utf8');
process.stdin.on('data', data => {
    const n = data.split(" ");
    const a = Number(n[0]), b = Number(n[1]);
    console.log(a);
    console.log(b);
});

 

우선 저 최초코드를 다시 살펴보자 a와 b를 출력하라고 되어있는데

그것이 각각 5와 3이었다.

 

그리고 문제에서 원한 결과는

*****

*****

*****

였다.

 

즉 이걸로 반복문을 만들라는 소리라고 할 수 있다.

 

 

최초답안 실행결과
process.stdin.setEncoding('utf8');
process.stdin.on('data', data => {
    const n = data.split(" ");
    const a = Number(n[0]), b = Number(n[1]);
    
    const star = '*'
    
    for(let i = 0 ; i < a; i++){
        console.log(star.repeat(b))
    }
    
});
***
***
***
***
***

그렇게 처음 작성한 답안

 

색을 칠해준 부분이 내가 추가해준 부분이다.

 

기존의 console 구문들은 지웠다.

 

그런데 이거 실행결과가 가로세로가 바뀌게 나왔다..... 세상에....

 

 

 

최초답안 실행결과
process.stdin.setEncoding('utf8');
process.stdin.on('data', data => {
    const n = data.split(" ");
    const a = Number(n[0]), b = Number(n[1]);
    
    const star = '*'
    
    for(let i = 0 ; i < b; i++){
        console.log(star.repeat(a))
    }
    
});
*****
*****
*****

아 그럼 a랑 b만 바꿔주면 되지 엌ㅋㅋㅋㅋ

 


어쨋든 테스트는 통과했고

 

이제 이 테스트를 어떻게 사용하는지 알것 같다.

 

그리고 검색과정에서 repeat라는 메소드도 알게 되었다.

 

 

'Language > JavaScript' 카테고리의 다른 글

JavaScript 공부정리 000  (0) 2022.09.28
JavaScript 공부정리 002  (0) 2022.09.28
JavaScript 공부정리 001  (0) 2022.09.28
코딩테스트 연습 ~10 JavaScript  (1) 2022.09.24
JavaScript 기본  (1) 2022.09.23

시작하기 전에....

 

Javasript는 개발 도중 문제를 일으킨 명령어들이 꽤나 있었던 것으로 보인다.

 

때문에 지금은 거의 사용하지 않는 명령어들이 있다.

 

얘네들이 있음을 인지하고 쓰지 않도록 하자


여기서 배워가는 것

 

변수

비교연산자

자료형

조건문

반복문

논리연산자

함수
구조분해 할당
동기와 비동기
Blocking과 NonBlocking
Promise
비동기함수
await연산자

 


■변수

 

변수의 종류: var, let, const

 

대충 이런것들이 있다는 것만 알면 된다.

원래는 var만 있었지만 이게 문제아라서 let과 const라는 새로운 모범생이 추가된 것이다.

그러니까 var은 쓰지 말자

var 문제아
let 값을 다른 값으로 바꿀 수 있다
const 값을 바꿀 수 없다!

■비교연산자

비교연산자의 종류: ===, !==, >, <, >=, <=, ==, !=

=== 좌우의 값이 같으면 true, 다르면 false로 한다.
!== 위와는 정반대로 좌우의 값이 같으면 false, 다르면 true로 한다.
>, <, >=, <=, = 수학에서 말하는 초과, 미만, 이상, 이하와 같다. 좌우가 같다면 =을 사용한다.
==, != 위에 설명한 ===와 !==와 같은 기능하지만 여러가지 문제가 있으므로 사용하지 않도록 한다.

■자료형

색이 있는 칸은 후술한다.

Boolean 참, 거짓 형 자료형(true, false)
Sting 문자열, 외따옴표나 쌍따옴표를 사용해야 한다  ex: 'value' 또는 "value" 
Number 숫자, 따옴표를 사용하지 않는다.  때문에 '10' 는 문자열, 10은 숫자로 판별한다.
undefined 변수에 값이 할당되지 않으면 가지게 되는 값으로 원시 자료형이다.
null 값 자체가 비어있는 것을 의도적으로 표현할 때 사용
Object 타 언어의 딕셔너리에 해당하는 형태, {key1: value, key2: value} 형태로 사용한다.
Array 배열, [value0, value1, value2] 형태로 표현한다.
NaN 숫자가 아닌 값을 숫자로 변환할 때 이것으로 반환된다.
Function 함수

 

■Object

아래 예시를 보자

const person = {
	name: '사람이름',
	age: 24
};

person.name;
person['name'];
person.hobby;

위에 선언된 person은 const 변수이며 Object형태로 선언되었다.

person에는 name: '사람이름' 과 age: 24가 선언되었다.

여기서 '사람이름'은 따옴표를 통해 선언되었으니 문자열로 인식하고

24는 그런거 없이 선언되었으니 숫자로 인식한다.

 

그 아래 person.name 을 통해 person 이라는 변수의 name에 접근할 수 있다.

 

마찬가지로 person.age 라고 입력하면 person의 age에 접근할 수 있다.

 

아래 person['name']은 person.name과 모양만 다를뿐 같은 명령이다.

person에는 hobby라는 것이 선언된 적이 없다.

때문에 person.hobby는 undifined라는 값이 반환된다.

 

■Array

여러개의 값을 나열한다.

const ay = [123, 222, 314, 456]

ay[0];
ay[1];

ay라는 변수에 123 과 222와 314와 456이 순서대로 선언되었다

 

각 칸을 인덱스라고 하며 가장 처음의 칸은 0번째 칸으로 본다

 

즉 ay의 0번째 칸에는 123이라는 값이, 2번째 칸에는 314라는 값이 들어가 있다.

 

아래 ay[0]이라고 입력하면 123이라는 값이 나올 것이다.

 

■NaN

Not a Number의 줄임말로 다소 특이하다.

NaN은 그 어떤 값과도 같다고 여겨지지 않는다.

isNaN() 라는 명령어는 ()안의 값이 NaN인지 아닌지를 판별해주는 명령어다.

NaN === NaN;        // false
Num.NaN === NaN; // false
isNaN(NaN);         // true
isNaN(Num.NaN);  // true

 

■Function

각종 기능을 모아둔 곳으로 자판기에 비유할 수 있다.

자판기는 동전을 받아서 3번째 단추를 누르면 음료수가 나온다고 하자

동전과 단추 번호는 parameter라고 하며

나온 음료수는 return이라고 한다.

 

자판기는 동전과 단추번호를 받고 어떤 음료수를 줘야할지, 또는 반응해야할지(돈이 부족하다던가, 거스름돈이라던가)

를 판단해야 하는데 그 판단과정이 바로 함수의 내용이라고 할 수 있다.

 

아래 예시를 보자

function getMyName() {
	return '함수가 반환할 값';
}

getMyName(); // 위처럼 정의된 함수는 이렇게 사용할 수 있습니다.
// Print: '함수가 반환할 값'

getMyName이라는 함수(자판기)가 선언되었다

()안이 바로 parameter인데 여기가 비어있다는건 아무것도 받지 않는다는 뜻이다.

{}안은 함수의 내용인데 return을 빼면 아무 내용도 없다.

그러니까 묻지도 따지지도 않고 음료수(return)을 내놓는다고 보면 된다.

여기서 내놓는 음료수는 '함수가 반환할 값' 이다.

 

이제 이 자판기는

getMyName() 이라고 적어만 주면 작동한다.

const variable = function() {
	return '함수가 반환할 값';
}

variable(); // 위처럼 정의된 함수는 이렇게 사용할 수 있습니다.
// Print: '함수가 반환할 값'

이건 변수에 함수를 할당한 것이다.

별 의미는 없는것 같다.

 

function getMyName(myName) {
	return myName;
}

getMyName('인자를 넣습니다.'); // 위처럼 정의된 함수는 이렇게 사용할 수 있습니다.
// Print: '인자를 넣습니다.'

 

맨 위의 예시와는 달리 ()안에 myName이라는 내용이 들어가 있다.

이는 이 자판기가 myName이라는걸 받는다는 뜻이다.

그런데 return도 myName이다

이는 받은 값을 그대로 돌려준다고 해석할 수 있다.

 

몇몇 고장난 자판기는 동전을 넣는 족족 다시 동전을 토해내는데

이거랑 똑같은거라고 생각할 수 있다.

 


■진실 혹은 거짓

진실로 취급될 수 있는 값 거짓으로 취급될 수 있는 값이 아닌 모든 것
거짓으로 취급될 수 있는 값 빈문자열 '', 숫자 0, 불리언 false, null, undefied, NaN

단, 항상 진실로 취급될 수 있는 값이 있으니 이것은 앞서 배운 Array와 Object다

 

컴퓨터에는 여러종류의 값이 있는데 여기에 어거지로 진실 혹은 거짓을 규명해 줄 수 있는데 이게 바로 Boolean 명령이다.

괄호안에 집행하고자 하는 대상을 넣어주면 된다.

 

예시

Boolean('') 는 빈 문자열이 들어가 있으니 거짓으로 판명한다.

Boolean('죄수')는 죄수라는 문자열이 들어가 있으니 진실로 판명한다.

Boolean(undefined)는 undefied가 들어가 있으니 거짓으로 판명한다.

 

 


■ 조건문

어느 언어에나 있는 흔하디 흔한 if문과 else문과 else if문이다.

if와 else if는 ()를 대동한다. ()안이 조건이며 이 내용이 참이면 실행하고 거짓이면 else를 실행한다.

대략적인 구조는 아래 예시를 보자

if (조건1) {
  실행문1
} else if (조건2) {
  실행문2
} else {
  실행문3
}

 

조건 1이 참이면 실행문 1을 수행한다.

조건 1이 거짓이면 조건 2를 판명한다.

 

조건 2가 참이면 실행문 2를 수행한다.

조건 2가 거짓이면 실행문 3을 수행한다.

 

if (죄가 있는가?) {
  징역!
} else if (금전적 손해를 끼쳤는가?) {
  배상!
} else {
  석방!
}

죄가 있으면 징역을, 손해를 끼쳤으면 배상을, 그것도 아니면 석방을 하라는 예시문이다.

 

대략 이런 절차로 조건문이 실행된다고 할 수 있다.

 

 


■논리연산자

논리연산자 종류: &&, ||, !

&& AND연산으로 좌우의 값이 둘 다 true일 때 true를 내놓는다.
|| OR연산으로 좌우 값 중 하나라도 true일 때 true를 내놓는다.
! NOT연산으로 참거짓 값을 뒤집는다

AND와 OR은 둘 다 좌우에 비교대상을 넣어야 하지만

NOT은 그렇지 않다.

 

!'value' 라고 입력하면 value의 참거짓 여부가 뒤집어진다.

'value'는 빈 문자열이 아니기 때문에 기본적으로 참으로 판명한다.

그러나 앞에 !가 있으므로 !'value'는 거짓으로 판명된다.

 

 

과제는 오늘내로

문제는 천천히

 


■반복문

어느 언어에나 다 있는 흔하디 흔한 for문이다

원래 while도 있지만 별 차이는 없기에 생략한다.

for문은 괄호안에 3가지 구문을 넣어줘야 한다.

 

for (초기문 ; 조건문; 증감문){반복하고자 하는 내용}

 

으로 구성된다.

for (let i = 0; i < 5; i++) {
}

초기문: 우선 i를 선언하고 이것의 초기값은 0이다.

증감문: 한번 실행할 때 마다 i값을 1씩 올린다 (i++)

조건문: i < 5 라면 반복하고자 하는 내용을 실행한다.

 

즉 한번 실행할 때 마다 i값이 1씩 올라가고 그것이 조건문을 만족하는 이상 계속 반복한다.

 

■제어문

종류: break, continue

 

제어문은 특정 조건을 만족하면 조건문을 아예 끝내버리거나 몇 단계 건너뛰게 하는 명령이다.

break 반복문을 아예 끝내버린다. 이게 실행되면 반복문은 끝난다.
continue 다음 반복스탭으로 넘어간다.
for (let i = 0; i < 5; i++) {
	if(i===2) continue;    
    if(i===4) break;
    console.log(i);

}

맨 아래 console문은 ()안의 값을 출력하라는 뜻이다.

 

i가 시작할때 0이니 0을 출력한다.

i가 1이 증가하고 그 값을 출력한다.

이것을 i가 5가 될 때까지 반복한다.

 

위의 내용이 반복문의 내용이지만 중간에 i가 2일 경우 continue를, 4일령우 break를 하라고 하고 있다.

i가 2가 되면 console.log(i)명령을 수행하지 않고 i를 3 올린다.

그리고 i가 4가 되면 반복문이 끝난다.

 

때문이 위 구문을 출력하면 0 1 3 이 출력된다.

 

 

■for-of문

Array, Map과 같은 반복 가능한(Iterable) 객체의 value(요소)를 하나씩 반복한다.

const persons = ['아마', '홍길동', '김아무개'];

for (const person of persons) {
  console.log(person);
}

배열이 선언되어 있고 그 안에 3개의 값이 있다.

person은 for문에서 사용하는 이름이고 persons는 배열의 이름이다 (비슷하지만 다름을 주의)

가장 처음, persons의 값의 첫번째인 아마를 받아온다.

그리고 그것을 출력한다.

그 다음, persons의 다음 값인 홍길동을 받아오고 출력한다.

 

이런식으로 작동하며 출력결과 값은

아마

홍길동

김아무개

 

가 된다.

 

■for-in문

위의 for-of와 비슷하지만 내용이 아닌 인덱스번호를 가져온다는게 차이점이다.

const persons = ['아마', '홍길동', '김아무개'];

for (const person in persons) {
  console.log(person);
}

이를 출력하면 0 1 2 가 된다.

 

만약 인덱스의 내용을 출력하고 싶다면 다음 예시를 참조하자

 

const persons = ['아마', '홍길동', '김아무개'];

for (const index in persons) {
  const person = persons[index];
	console.log(person);
}

이를 출력하면 아마 홍길동 김아무개가 된다.

이렇게 person이라는 변수를 선언하고 그것을 맨 위의 persons의 index로 선언하면 된다

 

하지만 굳이 이렇게 쓸 필요는 없고 그냥 내용이 필요하면 for-of문을 쓰면 될듯하다

 


■함수

예를 들어 슈퍼마켓 사업을 한다고 가정한다면

각지의 슈퍼마켓 마다 계산대, 물품관리, 고객응대, 배달담당 등 다양한 부서가 있을 것이다.

이 부서가 함수라고 할 수 있다.

 

계산대를 예로 들자면 계산대 직원이 일을 하기 위해선

고객이 가져온 물품이 있어야 하고 그 물건을 바탕으로 금액을 청구하고 계산한다.

여기서 고객이 가져온 물품, 지불할 금액 등이 인자(파라미터 또는 매개변수)이고

계산 후 고객에게 주는 물품과 영수증은 리턴이라고 할 수 있다.

const sum = function(a, b) {
  return a + b;
};

a와 b를 받으면 그 두개를 더한 값을 반환하는 함수이다.

가장 기본적인 형태라고 볼 수 있다.

 

■화살표 함수

함수의 한 형태로 함수를 짧게 작성한거라 할 수 있다.

const sum = (a, b) => a + b;

아까 위에 작성한 함수와 같은 내용이다.

여기서 => 는 대소관계를 나타내는 것이 아님을 주의

 

■익명 함수

쉽게 말해 함수에 이름이 없고 대신 변수에 함수를 담아 사용하는 경우이다.

이건 1회성 함수로 자주 사용하는데 한 번 쓰고 버림으로써 불필요한 메모리를 차지하는 것을 막을 수 있다.

// 일반 함수
function foo() {
  console.log("bar");
}

// 익명 함수
let foo = function () {
  console.log("bar");
};

 

그러나 이건 순서를 지켜야한다는 단점이 있다.

코드는 위에서 아래 순서대로 작동을 하는데 함수는 어느 위치에 있든지 상관없이 불러올 수 있지만

익명함수는 호출코드가 본인보다 위에 있으면 인식하지 못한다.

 


■구조분해 할당

배열이나 객체가 가진 값을 분해해서 개별 변수에다 담는 것을 말한다.

■배열에서 구조분해 할당

const [a, b] = [100, 200];
console.log(a); // 100   a가 100의 값을 가져가고
console.log(b); // 200   b가 200의 값을 가져간다.

//혹은 아래와 같이 표현할수있습니다.

const array = [100,200]
const [a,b] = array
console.log(a); //100   a가 100의 값을 가져가고
console.log(b); //200   b가 200의 값을 가져간다.

// a 에는 array[0] , b에는 array[1] 값이 할당 되었습니다.

array는 원래 [100, 200]이었다

그러나 [a, b]가 array에 들어옴에 따라

a값이 100, b값이 200이 되었다.

 

즉 array가 가지고 있던 [100, 200]은 분해되어

a가 100을 가져가고 b가 200을 가져가게 되었다.

 

■객체에서 구조분해 할당

이번엔 객체를 구조분해 할당을 해보자

const student = {
  name: "Sparta",
  age: 18,
  onlineClass: "Node JS",
};
const { name, age, onlineClass } = student
console.log(name); // "Sparta"
console.log(age); // 18
console.log(onlineClass); // "Node JS"

student라는 객체에는 name, age, onlineClass가 있고 각각 Sparta, 18, Node JS 라는 값을 가진다

그리고 그것을 name, age, onlineClass로 분해했다(이름은 똑같이 설정)

지금까지는 student가 각 3가지 값을 가졌지만

이제는 분해할 때 사용했던 이름인 name, age, onlineClass라는 변수를 사용해 그 값을 가져온다.

 

 


■동기와 비공기(Sync, Async)

동기 먼저 실행된 코드의 결과가 나올때까지 대기
비동기 실행된 순서와 상관없이 결과가 나옴

동기는 집단주의, 비동기는 개인주의라고 할 수 있다.

 

동기는 한 번에 수용할 수 있는 사람을 다 수용한 뒤 작업에 들어간다.

그리고 그것이 끝나야지 다음 사람을 받을 수 있다.

비동기는 수용할 수 있는 양만큼 다 수용하나 먼저 일이 끝난 사람은 돌려보내고 다음 사람을 받는다.


■Blocking Model & Non-Blocking Model

■Blocking Model이란, 코드의 실행이 끝나기 전까지 실행 제어권을 다른곳에 넘기지 않아 다른 작업을 하지 못하고 대기

 

■Non-Blocking Model이란, 코드의 실행이 끝나지 않아도 실행 제어권을 다른곳에 넘겨서 다른 작업을 하게 하는 것

 

이러한 특징  덕분에 Non-Blocking은 비동기와 연관이 깊고

Blocking은 동기와 연관이 깊다.

 

자바스크립트는 비동기 + Non-Blocking 을 채용하여 현재 실행중인 코드의 실행이 끝나지 않아도 다음 코드를 호출한다.

 

function first() {
  console.log('First');
}

setTimeout(first, 1000); // 1000ms(1초) 뒤에 first 함수를 실행해준다.

console.log('Middle');
console.log('Last');

// Print: Middle
// Last
// First

이 코드의 setTimeout은 1초를 기다린 다음 first 함수를 실행하라는 뜻이다.

 

그러나 자바스크립트는 비동기식이고 아래 console 명령은 처리하는데 1초도 걸리지 않음으로

Middle이 먼저 출력되고 그 다음 Last, 마지막으로 first가 출력된다

 

만약 자바스크립트가 Blocking 모델이었다면 first, Middle, Last 순서대로 출력되었을 것이다.


■Promise

자바스크립트에서 비동기 처리를 동기로 처리하게 해주는 객체유형이다.

Promise라는 이름의 생성자를 사용한다.

new Promise(executor);

// 예제
new Promise((resolve, reject) => {
	// 여기에 명령문을 입력
});

■promise의 상태

프로미스의 상태는 대기(Pending), 이행(Fulfilled), 거부(Rejected) 로 나뉜다.

대기는 말 그대로 대기상태, 이행은 연산이 성공적으로 완료된 상태, 거부는 연산이 실패한 상태이다

 

프로미스가 만들어 질때는 집행관(executor)가 실행된다.

집행관이 resolve함수를 호출하면 Fulfulled Promise라고 한다.

 

■Promise.catch

쉽게 말해 에러를 잡아내는 것이다.


■비동기 함수(Async Function)

일반함수나 화살표함수와 아주 비슷하지만 두가지가 다르다.

1. 비동기 함수의 결과값은 항상 Promise 객체로 resolve가 된다

2. 비동기 함수 안에서만 await 연산자를 사용할 수 있다.

 

이 두가지만 빼면 일반함수나 화살표함수처럼 사용할 수 있다

 

// 비동기 + 일반 함수
async function 함수이름() {
	// 명령문
}

// 비동기 + 익명 함수
async function() {
  // 명령문
}

// 비동기 + 화살표 함수
async () => {
	// 명령문
}

 

3가지 모두 비슷한 방법이다.

 


■await 연산자

await 연산자를 사용하면 promise가 fulfil 되거나 rejected 될 때까지(성공하거나 실패할 때까지)

함수의 실행을 중단하고 기다린다.

 

promise의 연산이 끝나야 함수에서 반환한 값을 얻을 수 있다.

 

await연산자는 async함수안에서만 사용할 수 있다.

 

async function abcdefg() {
	const result = await 'Test!';
	console.log(result);
}

abcdefg();
// Print: 'Test!';

abcdefg는 임의로 정한 함수 이름이다.

 

+ Recent posts