6일차
let, const 변수와 블록 스코프
let
과const
는 같은 이름을 갖는 변수의 재선언을 허용하지 X. 유효범위: 블록 스코프함수의 매개변수나,
var
변수는 함수 스코프를 갖는다. 유효범위: 함수var
변수를 둘러싸고 있는 함수가 없을 경우, 유효범위는 전체가 된다.
1 | { |
- 비슷한 작업을 여러 번 하는데, 같은 이름의 변수가 사용될 때 ,{}로 묶어주면 같은 이름의 let 변수를 여러 번 선언해도 오류가 나지 않도록 해준다. (유효범위가 블록 스코프이므로)
var 변수와 함수 스코프
- var 변수는 변수의
선언부
를 맨 위로 끌어올린다. 대입부
는 그 자리에 그대로. -> 이 과정을호이스팅
이라고 한다.
1 | function print() { |
1 | // 호이스팅 |
var
변수는 함수 스코프를 갖기 때문에 함수가 아닌 블록에서 정의된 var변수가 해당 블록 바깥에서도 유효할 수 있다.var
변수를 사용하면,중첩된
for`루프와 같이 블록이 중첩된 코드에서 의도치 않은 동작을 할 수 있다.
1 | var i; |
전역 변수 (Global Variable)
- 전역 변수라는 용어는 쓰이고, 요즘은 지역 변수라는 용어는 쓰이지 않는다.
- 전역 스코프는 스코프 체인의 가장 바깥쪽에 있는 스코프
- 전역 스코프에 선언된 변수를
전역 변수(global variable)
라고 한다.
변수를 전역 스코프에서 선언하지 않고, 한 번도 선언되지 않은 이름으로 안쪽 스코프에서
let
,const
,var
를 붙여주지 않고 변수를 선언하면, 전역 스코프에 변수가 만들어진다. - 변수를 선언할 때, let이나 const를 꼭 써주자.전역 변수에 의존해서 프로그래밍을 하는 것은 굉장히 금기시되는 일이다. - 값을 공유해야 할 일이 생긴다면, 다른 방식으로 값을 공유하자.
전역 객체 (Global Object)
var
변수로 전역 변수를 만들었을 때, 전역 객체의 속성이 되어 전역 객체를 통해서 접근할 수 있게 된다.let
,const
변수는 전역 객체의 속성이 되지 않는다.
참조 (Reference)
- 객체가 컴퓨터 메모리 상에서 어디에 저장되었는지를 가리키는 값
- 화살표를 생각하면 됨. 사실 변수에 저장되는 건 객체 그 자체가 아니라 참조(화살표)다.
- 원시 타입(primitive type)
- 참조 타입(reference type)
함수 호출
- 값이 전달되는 것이지, 변수가 전달되는 것이 X.
- 함수를 호출하면, 변수 안에 값은 그대로 있고, 그 값이 복사되어 인수로 넘긴다.
- 원시 타입을 인수로 넘길 때는 원본을 변경할 수 없지만, 참조 타입으로 인수로 넘길 때는 원본을 변경할 수 있다.
1 | const obj = {}; |
객체의 같음 (Equality)
===
로 비교를 하면,같은 객체를 가리키고 있으면
true
, 다른 객체를 가리키고 있지 않으면 ->false
를 반환내가 지금 객체의 내용이 다른지, 아닌지를 판별하고 싶은지 or 두 참조가 정말로 같은 객체를 가리키고 있는지를 알고 싶은지를 구분해야 한다.
1 | var equal = require("fast-deep-equal"); |
- 객체를 내용을 통해서 비교하고 싶을 때
- 깊은 비교기능을 지원하는 라이브러리를 이용
- Node.js에 require라는 함수가 들어있다.
- 정확히 어떤 내용을 비교하고 싶은지를 가지고 함수 혹은 메소드를 작성 -> 그것을 이용
- 깊은 비교기능을 지원하는 라이브러리를 이용
불변성 (Immutability)
- 원시 타입의 특징
- Object타입(ex) 객체, 배열, 함수)가 아닌 원시타입(ex) boolean, null, number, string 등)은 원본의 값 자체를 변경할 수 있는 방법은 없다.
- ex) 문자열을 변형하는 메소드는 모두 기존 문자열의 내용을 바꾸는 게 아니라 새 문자열을 반환한다.
- -> 원시타입의 값을 바꾸려면, 오직 변수에 다른 값을 재대입하는 방법 밖에 없다.
- 객체는 가변(mutable)이다.
- 객체는 가변이지만 일부러 불변으로 만들어주고 사용할 때도 있다.
- 어떤 값이 가변이면 그 값이 변경되지 않았을까? 걱정하면서 프로그래밍 할 수 있는데, 이럴 경우를 대비하기 위해 객체를 불변으로 만들기도 한다.
- ex1)
Object.freeze
를 사용해서 객체를 얼려서 속성의 추가/변경/삭제를 막는다. But 사용하기 조금 불편하다.Object.freeze
를 호출한다고 해서 객체 안에 있는 객체까지 얼리는 것은 아니기 떄문이다. 중첩된 객체는Object.freeze
를 사용하기가 조금 까다롭다.
1 | const obj = { |
- ex2) Immutable.js같은 라이브러리를 사용
Object.freeze
처럼 객체를 정말로 얼려버리지는 않음.- 이 객체들은 메소드를 통해 내용이 조금이라도 달라지면 아예 새로운 객체를 반환
- 내용이 달라지면 참조 역시 달라지게 된다.
1 | import { List } from "immutable"; |
- const와 불변성을 잘 구분해야 한다.
const
는 재대입을 막는 것이지, 원본이 변경되지 않는다는 걸 보장해주는 게 X.- 불변성은 값 자체가 변하지 않는 것을 의미한다.
래퍼 객체 (Wrapper Object)
- 원시 타입의 값에 대해 속성을 읽으려고 시도하면, 그 값을 그 순간에만 객체로 변환되어 마치 객체인 것처럼 작동한다.
1 | const s = "hello"; |
함수 더 알아보기
객체로서의 함수
- 함수는
Function
생성자로부터 생성되는 객체 - 다른 객체들과는 다르게 호출할 수 있다는 특징이 있다.
- length - 함수의 매개변수의 개수를 반환합니다.
- name - 함수의 이름을 반환합니다.
주인 없는 this
- 생성자나 메소드가 아닌 함수에서
this
키워드를 사용하면 에러는 나지 않지만,this
가 전역 객체를 가리키게 된다.
1 | function Person(name) { |
엄격 모드(Strict Mode)
1 | function Person(name) { |
- 항상 엄격 모드를 켜고 프로그래밍을 하는 게 좋다.
- 실무에서는 항상 ‘use strict’를 써줄 필요는 없다. -> 나중에 모듈을 쓴다면 자동으로 엄격 모드가 켜지기 떄문에
- 만약, react에서 작동하지 않는데, repl.it에서는 작동할 경우 -> repl.it에서는 엄격 모드가 꺼진 채로 작동하기 때문에 ‘엄격모드’ 떄문일 수 있다.
this 바꿔치기
window.name에는 빈문자열(‘’)이 저장되어 있다.
call
과apply
는 인수를 넘겨주는 형식에 차이가 있다.
1 | function printGrade(grade) { |
arguments와 나머지 매개변수 (Rest Parameters)
- 인수의 개수에 제한이 없는 함수
function
구문을 통해 생성된 함수가 호출될 때,arguments
라는 변수가 함수 내부에 자동으로 생성된다.
1 | function add() { |
arguments
는 ES2015 이전까지 인수의 개수에 제한이 없는 함수를 정의하는 데에 사용되곤 했다.- ES2015에서 도입된 나머지 매개변수(rest parameters) 문법을 통해서 똑같은 기능을 더 깔끔한 문법으로 구현할 수 있기 떄문에
arguments
는 더 이상 사용되지 않는 기능이다. ...
문법은 마지막 매개변수에만 사용할 수 있다.- 자바스크립트는 매개변수의 개수와 인수의 개수가 일치하지 않아도 에러가 나지 않는다는 특징이 있다.
1 | function func() { |
화살표 함수(Arrow Function)
- ES2015에서 도입된 새로운 유형의 함수
- 화살표 함수는 생성자로 사용될 수 없다.
- 따라서, 화살표 함수는
prototype
속성을 가지고 있지 X. - function 키워드로 만든 함수는 모두 생성자로 사용될 수 있다.
1 | function func() { |
1 | const func = () => { |
- 화살표 함수는 스스로의
this
를 가지지 않는다. - 화살표 함수는 자기
this
가 없으므로, 바로 바깥에 있는this
를 가져다 쓴다. - 화살표 함수 내부에서
this
를 사용하면, 함수가 정의된 스코프에 있는this
를 가리킨다. - 화살표 함수 내부의
this
는 화살표 함수가 정의된 문맥에 의해 결정되고, 그 후에는 절대 바꿀 수 없다.
1 | function Person(name) { |
- 브라우저 환경의 전역 객체인
window
는name
이라는 속성에 빈 문자열을 갖고 있기 때문에, 이 값이 대신 반환됩니다.
- 객체의 속성 값에 메소드를 직접 정의할 때는 화살표 함수를 사용해서는 안 된다.
- 화살표 함수는 어떻게 호출되지는 상관 X. 어떻게 정의되었는지에 따라서 동작한다.
1 | // 매개변수로 function keyword 함수를 넘겨주면, this의 주인이 없는채로 실행된다. |
매개변수의 기본값(Default Parameter)
함수 호출 시에 인수에 값을 넘겨주지 않으면, 매개변수가
undefined
가 대입된다.name은 var변수처럼 재대입이 가능하다.
- 매개변수의 기본값 지정하기
1 | // 'Mary'가 `name` 매개변수의 기본값이 됩니다. |