JS 기초 개념

SuJin·2022년 9월 8일
0

JavaScript

목록 보기
2/7

원시 자료형: 객체가 아니면서 method를 가지지 않는 6가지의 타입

  • number, boolean, (null), undefined, string, bigint, symbol
  • 값 복사. 기존 데이터에 영향X
  • 원시 자료형이 담기는 보관함의 크기는 고정되어 있다.
  • 데이터 보관함에 저장할때 하나의 데이터만 담을 수 있다.

참조 자료형

  • array, object, function
  • 메모리 주소에 변수가 저장됨
    • 변수: 데이터 보관함의 주소 담김
    • 주소를 따라가면 데이터 보관함 찾을 수 있음
    • 데이터 보관함(heap)은 동적으로 변함 → 대량의 데이터를 담을 수 있다
  • 주소 복사. 기존 데이터에 영향O
let first = [10, 20, 30, 40];
let second = first;
second[0] = 5;

fisrt     // [5, 20, 30, 40]

fisrt[2] = 55;
second    // [5, 20, 55, 40]

→ first의 0번째 인덱스에 있는 요소 = 5

→ first와 second는 같은 주소를 공유

→ 주소를 공유하고 있어서 second의 값을 변경하면 first의 값도 같이 변경된다.

참조 자료형의 === : 주소값이 같은지 확인

console.log([1,2,3] === [1,2,3]) → false

let x = { foo: 3};
let y = x;
y = 2;

// x.foo = 3
let myArr = [2, 3, 4, 5];
let ourArr = myArr;
ourArr[2] = 25;      // -> myArr: [2, 3, 25, 5]
ourArr = undefined;  // myArr에 접근 불가능
let score = 80;
function doStuff(value){
	value = 90;
}
doStuff(score)

score: 80

→ 매개변수 value에 score 값 80이 전달되고 value=90 에서 value에 90 할당

→ 변수 score의 값 80은, 참조 자료형이 아니라서 주소값 전달X

→ 초기 할당값 80 그대로 유지됨.


스코프

: 변수 접근 규칙에 따른 유효 범위

let username = 'kimcoding';
if (username) {
	let message = `Hello, ${username}!`;
	console.log(message);  // Hello, kimcoding!
}

console.log(message);   // ReferenceError

→ message 변수 자체가 중괄호 안쪽에 선언되어 있어서 바깥쪽에서 접근X

  • 바깥쪽 스코프에서 선언한 변수는 안쪽 스코프에서 사용O
  • 안쪽 스코프에서 선언한 변수는 바깥쪽 스코프에서 사용X
  • 중첩 가능
  • 가장 바깥의 스코프는 전역 스코프 (Global scope) 라고 부른다 ↔ 지역 스코프 (Local scope)
  • 지역 스코프에 선언한 변수는 지역 변수
  • 전역 스코프에서 선언한 변수는 전역 변수
  • 지역 변수는 전역 변수보다 더 높은 우선 순위를 가진다.
let name = '김코딩';     // 전역변수

function showName(){
	let name = '박해커';   // 지역변수
}

function Name(){
	name = '박해커';
}

console.log(name);    // 김코딩
showName();           // 박해커
console.log(name);    // 김코딩
Name();               // 박해커
console.log(name)     // 박해커

스코프의 종류

  • 중괄호로 둘러싼 범위 (block scope: 블록 스코프)
    • 화살표 함수는 블록 스코프에 해당
  • 함수로 둘러싼 범위 (function scope: 함수 스코프)
for (let i = 0; i < 5; i++){
	console.log(i); // 0 1 2 3 4 
}
console.log("final i:", i); // reference error

for (var i = 0; i < 5; i++){
	console.log(i); // 0 1 2 3 4 
}
console.log("final i:", i); // 5

→ var 키워드는 for문이 만들어낸 블록 스코프 무시

  • 변수를 정의하는 또 다른 키워드 var
    • 블록 스코프 무시(화살표 함수 블록은 무시 안함)
    • 함수 스코프만 따름 (let은 블록 스코프)
    • 블록 단위로 스코프를 구분했을때, 훨씬 더 예측 가능한 코드를 작성할 수 있으므로 let키워드 사용 권장
    • 함수 스코프는 let으로 선언된 변수의 접근 범위 제한
    • var 키워드는 재선언을 해도 에러 발생X
    • let 키워드는 재선언 방지 → var 키워드보다 let 키워드가 안전한 이유
  • 값이 변한지 않는 상수를 정의하는 const
    • 블록 스코프 따름

    • 값의 변경을 최소화하여 안전한 프로그램 만들기 가능

    • 값을 새롭게 할당하지 않으면 const 사용 권장됨

    • 값을 재할당하면 TypeError 발생

      letconstvar
      유효 범위블록 스코프


      함수 스코프 | 블록 스코프

      함수 스코프 | 함수 스코프 |
      | 값 재할당 | 가능 | 불가능 | 가능 |
      | 재선언 | 불가능 | 불가능 | 가능 |

var 키워드 사용시

let 키워드 사용시

greeting 변수 안보임

window 객체(브라우저 only)

  • var로 선언된 전역 변수 및 전역 함수는 window 객체에 속함
  • 브라우저 창을 대표하는 객체
  • 브라우저 창과 관계없이 전역 항목을 담고 있음

전역변수는 최소화하기

  • 전역변수: 어디서든 접근 가능한 변수
  • 편리하지만, 다른 함수 혹은 로직에 의해 의도되지 않은 변경 발생가능
    • side effect 발생

let, const 주로 사용하기

  • var 는 블록 스코프 무시, 재선언시 에러X
  • 전역변수를 var로 선언할때 문제 발생할 수도 → 브라우저 내장 기능 사용 못하는 상황 발생

선언 없는 변수 할당 금지

  • 선언없이 변수를 할당하면, 해당 변수는 var로 선언한 전역 변수처럼 취급
function showAge(){
	// age를 전역변수로 취급
	age = 90;
	console.log(age);     // 90
}

showAge();
console.log(age);          // 90
console.log(window.age);   // 90

→ age는 선언한적이 없지만 값을 할당하면서 마치 var로 선언된 전역변수처럼 작동

  • 실수를 방지하기 위해 Strict Mode를 사용할 수 있다
    • 'use strict'; → 브라우저가 보다 엄격하게 작동하도록 만들어줌


클로저

A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time the closure was created.

클로저는 함수와 함수가 선언된 어휘적 환경의 조합을 말한다.
이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다.

클로저 함수

const add = (x, y) => x + y;
add(5, 7);   // 12
const adder = x => y => x + y;
adder(5)(7);   // 12

→ 함수의 호출(invocation) 두 번 발생


typeof adder(5)   // 'function'

adder(5)   // y => x + y

adder(5) 의 리턴값이 함수의 형태

adder 는 함수를 리턴하는 함수

const adder = function (x) {
	return ***function (y) {
		return x+ y;
	}***
}

→ 클로저 함수는 위 코드와 비슷한 모양

  • “함수를 리턴하는 함수”
  • 함수와 함수가 선언된 어휘적 환경의 조합
  • return하는 함수에 의해 스코프(변수의 접근 범위)가 구분됨
  • 클로저의 핵심: 스코프를 이용해서 변수의 접근 범위를 닫는 데에 있음
    x 가 선언된 함수는 바깥쪽에 있으니 ‘외부 함수’
    y 가 선언된 함수는 안쪽에 있으니 ‘내부 함수’

Q. 외부 함수는 y 에 접근 가능??
→ X. 바깥 스코프에서 안쪽 스코프로의 접근은 불가능

Q. 내부 함수는 x에 접근 가능??
→ O. 안쪽 스코프는 바깥 스코프에서 선언된 변수에 접근 가능

  • 내부함수는 외부함수에 선언된 변수에 접근 가능하다

클로저 함수

  • 데이터를 보존하는 함수
    • 외부 함수(adder)의 실행이 끝나더라도, 외부 함수 내 변수 x 사용O

    • 외부 함수 내 변수가 메모리 상에 저장

      const adder = function (x) {
      	return function (y) {
      		return x + y;
      	}
      }
      
      const add5 = adder(5); // 함수 실행이 끝나도 5 값 사용 가능
      add5(7)   // 12 -> y에다가 7 넣기
      add5(10)  // 15 -> y에다가 10 넣기
  • HTML 문자열 만들기
    • 특정 데이터를 스코프 안에 가두어 둔 채로 계속 사용 가능

      const tagMaker = tag => content => `<${tag}>${content}</${tag}>`
      
      const divMaker = tagMaker('div');
      divMaker('Hello')  // '<div>hello</div>'
      divMaker('World')  // '<div>World</div>'
      
      const anchorMaker = tagMaker('a');
      anchorMaker('go') // '<a>go</a>'
      anchorMaker('urclass')  // '<a>urclass</a>'
  • 클로저 모듈 패턴
    • 클로저를 이용해 내부 함수를 단 하나만 리턴하지 않고, 객체에 담아 여러 개의 내부 함수를 리턴하도록 만든다.

      const makeCounter = () => {
      	let value = 0;
      	
      	return {
      		increase: () => {
      			value = value + 1
      		},
      		decrease: () => {
      			value = value - 1
      		},
      		getValue: () => value
      	}
      }
      
      const counter1 = makeCounter();
      counter1 // { increase: f, decrease: f, getValue: f }

      → makeCounter 함수는 increase, decrease, getValue 메서드를 포함한 객체 하나를 리턴.
      → counter1 은 객체 (함수 여러개를 포함한)

      Q. makeCounter 함수를 바꾸지 않고, value라는 변수에 값을 새롭게 할당할 수 있는 방법은?
      A. X: 외부 스코프에서는 내부 스코프의 변수에 접근할 수 없으므로 불가능
      대신, 리턴하는 객체가 제공하는 메서드를 통해 ‘value’ 값을 간접적으로 조작 가능.
      ⇒ 정보의 접근 제한(캡슐화). 스코프로 value값을 보존. 전역변수X

  • 모듈화: 함수 하나를 완전히 독립적인 부품 형태로 분리하는 것
    • 재활용이 가능한 makeCounter 함수

    • 여러 개의 counter를 만드는 것이 가능

      const counter1 = makeCounter();
      counter1.increase();
      counter1.increase();
      counter1.decrease();
      counter1.getValue();   // 1
      
      const counter2 = makeCounter();
      counter2.decrease();
      counter2.decrease();
      counter2.decrease();
      counter2.getValue();   // -3

      → counter1에서의 value와 counter2 에서의 value는 서로에게 영향X
      → 각각의 값을 보존

profile
Anyone can be anything.

0개의 댓글