벌써 1월 반이 지나갔습니다!
시간 진짜 빠른것 같아요.
요즘 진행되는 작은 과제때문에 약간 업로드가 뜸해졌네요..!
마무리가 잘 되었으니, 추후에 업로드할 게시물 기대해주세요 :)
오늘 글은 꽤 오래전에 등록했던 [스터디/10기] 프론트엔드 개발을 위한 자바스크립트
에 대해서 잠깐 소개 겸, 사전에 풀었던 Quiz를 정리해보고자 합니다.
[스터디/10기] 프론트엔드 개발을 위한 자바스크립트
는요,
4주간 스터디 리더가 당신의 성장을 위한 미션을 매 주 부여합니다.
실무 경험이 풍부한 리더가 당신의 코드를 직접 리뷰하고, 피드백을 나눕니다.
코드에 대해 더 풍부한 의견을 나누기 위해 리뷰어 세 명도 함께합니다.
자바스크립트에 영 자신이 없는 모두에게 추천할게요.
라는 소개로, 온라인으로 4주동안 과제를 부여받고 제출하는 스터디입니다.
이곳, Programmers 사이트에서 확인 하실 수 있어요.
이렇게 크게 4개의 주제를 가지고 미션 및 피드백을 진행 하는 형태입니다.
이는 1월 20일
에 시작이되구요, 그 전에 워밍업으로 진행되었던 퀴즈를 정리해볼까해요.
사전 테스트로는 8개의 퀴즈를 풀어보았어요. 하나하나 정리해볼게요 😉
function Cat(name, age) {
this.name = name;
this.age = age;
}
const tabby1 = Cat("nana", 5);
console.log(tabby1. name);
"nana"
라는 출력값을 가집니다.
tabby1
라는 이름을 가진Cat 객체
를 만들며 속성을'name'
을'nana'
로,'age'
를5
로 설정했기 때문입니다.
인줄 알았지만.. 완전히 오답이였습니다.
정답은
'오류가 발생한다'
. 입니다.
apply
,call
,bind
등으로this
에 대해 주입한 상황이 아니고new
키워드없이 실행한 함수 내this
는전역 객체(window)
를 바라본다.
즉this.name = name
의 결과는window.name = name
이라는 이야기.
너무 당연하게 착각을 한 것 같았고, 중요한 사실을 깨달았습니다.
new
키워드가 없이 실행한 함수 내의this
는 전역, 즉window
를 가르킨다!
(function(name) {
console.log(`hello ${name}`)
}) ("roto")
"hello roto"
라는 출력값을 가집니다.
IIFE 으로 바로 실행되는 함수로, 인자를"roto"
를 넘겨주어 바로 실행하게 됩니다.
정답이였습니다!
"hello roto"
가 출력된다.
백틱
으로 감싼 문자열은ES6
에 있는template strings
라는 문법으로,
즉시 실행 함수 표현(IIFE
,Immediately Invoked Function Expression
)이라고 하며, 함수를 정의함과 동시에 실행한다.
JavaScript 특성상 변수의scope
는 해당 변수를 감싸고 있는function
에 한정되는데, 이걸 이용해 변수나 함수의 전역화를 최소화 시킬 수 있다.
var idiots = {
name : "idiots",
genre : "punk rock",
members : {
roto : {
memberName : "roto",
play : function () {
console.log(`band ${this.name} ${this.memberName} play start.`)
}
}
}
}
idiots.members.roto.play();
"band undefined roto play start"
라고 출력됩니다.
idiots
객체 안에는name
,genre
,members
라는 멤버 변수 혹은 객체가 있는데,members
객체안에는 또roto
라는 객체가, 그 안에는 멤버변수memberName
과 멤버함수play
가 있습니다.
play
함수에서 수행되는 코드는 단순한 출력인데,this
를 호출합니다.this
는 바로 윗 머리(?)인roto
객체이므로,roto
에는name
이 없어서undefined
가 출력되고,memberName
에는 선언이 이미 된"roto"
가 있기때문에, 정상적으로 출력됩니다.
결과는 맞았는데, 제가 생각하는.. 개념이 맞는지 확실하지 않은것 같더라구요.
function scope
관련 문제
정답은band undefined roto play start.
출력
play
함수의this
내에는name
이 없기 때문에undefined
가 출력 되는 것
뭐 어느정도 반정도는 맞은것 같네요! 😅
this
에 대한 개념은 다음과 같습니다:
this
를 쓰고 있는 scope에서 그 scope를 호출한 객체
perform()
함수를 실행하면, 각 member
의 perform
을 실행하려고 하는 코드입니다. 실제로 실행시 의도대로 동작하지 않는데, 해당 코드가 본래의 의도대로 실행되게 하는 법에 대해 아는 방법을 모두 나열하고 설명해주세요.function RockBand(members) {
this.members = members;
this.perform = function() {
setTimeout(function() {
this.members.forEach(function(member) { member.perform() })
}, 1000)
}
}
var theOralCigarettes = new RockBand( [
{
name : "takuya",
perform : function() { console.log("a e u i a e u i")}
}
])
RockBand
를function
으로 하지 않고class
로 하면 되지 않을까, 생각해보았습니다.
제가 아는 선에서 코드를 분석하자면,theOralCigarettes
에는RockBand
객체가 있습니다.
그 객체는name
과perform()
이라는 함수로 이루어진객체의 배열
입니다.
따라서function RockBand(members) {...}
에서members
에는 객체의 배열이 들어가게됩니다.
theOralCigarettes.perform()
을 실행시키면 당연히setTimeout
함수를 객체의 배열만큼 수행하는 줄 알았는데, 그렇지 않은 것을 보아 제 이해가 잘못됨을 알 수 있었습니다.
기각! 딴소리를 했네요.
맨 아래
theOralCigarettees.perform()
을 실행하는 게 빠졌습니다.
perform
함수 아래setTimeout
으로 인해 실행되는 함수의this
는RockBand
의this
가 아니기 때문에, 참조 오류가 발생
즉, setTimeout
함수 내에서 실행되는 함수에서 this
가 잘못 참조되었다는 뜻이였습니다.
function RockBand(members) {
var that = this;
this.members = members;
this.perform = function() {
setTimeout(function(){
that.members.forEach(function(member){ member.perform() })
}, 1000)
}
}
var theOralCigarettes = new RockBand([
{
name: 'takuya',
perform: function() { console.log('a e u i a e u i')}
}
])
theOralCigarettes.perform();
RockBand
함수의 this
를 변수에 저장하여 넘겨줘서 제대로 실행되게끔 해주게 수정하면 됩니다! :)
const numbers = [1, 2, 3, 4, 5];
for(var i = 0 ; i < numbers.length ; i++) {
setTimeout(function () {
console.log(`number index ${i}`)
}, 3000)
}
var
->let
으로 바꿉니다. 반복문 내에서var
가 아닌let
으로 선언해야합니다.
이유는 다음과 같습니다.
만약var
로 선언한다면,i
의 값은 계속 변합니다. 즉,i = 0
일때number index 0
이 3초 후에 출력되어야 하지만, 그 전에i
값은 계속 증가하니,hoisting
에 의해서 마지막 값인 5로 되어number index 5
만 5번 찍히게 됩니다.
var
가 아닌let
이라면,value hoisting
이 일어나지 않기 때문에 해당 문제점을 해결할 수 있습니다.
정답! 완벽하게 맞췄답니다 히히.
전형적인
closure
문제
setTimeout
이 실행되는 시점에는 루프가 이미 끝나있어서i
는 5가 들어가있어서 생기는 문제
i
를var
대신let
을 쓰는 걸로 해결할 수 있음
혹은setTimeout
을IIFE
로 감싸고, 파라메터로i
를 넘기는 것으로 해결 가능
type
이 "cat"
인 "name"
을 한 줄로 출력해주세요.const users = [
{
name : "roto",
type : "human"
},
{
name : "nana",
type : "cat"
},
{
name : "chai",
type : "cat"
}
]
function printCats() { let result = ""; users.filter(x => { if(x.type === "cat") { result += `${x.name}, ` } }) result = result.substring(0, result.length - 2); }
filter
함수를 사용해 원라는 값의 name
속성을 뽑아냈습니다.
function printCats() { const userNames = [] for(let i = 0; i < users.length; i++) { if (users[i].type === 'cat') { userNames.push(users[i].name); } } console.log(userNames.join('')); }
혹은, 아래의 방법이 가장 좋을것 같아요! 한줄로 딱 나오는게 dog 멋있어요.
function printCats() { console.log(users.filter(user => user.type === 'cat').map(user => user.name).join('')); }
매번 map
이랑 join
을 사용해서 한줄로 구현하는 것 한번 해보자 하는데, 생각보다 어렵네요 :(
var
, let
, const
의 차이점은?5번에서 잠깐 언급한것처럼,
선언 시기
에 따라 다른점이 존재합니다.
var
로 선언한 변수는 선언 전에 변수를 사용해도 무방합니다.
let
과const
는, 에러가 발생합니다.
이는var
는함수 레벨 스코프
이고,let
과const
는블럭 레벨 스코프
이기 때문입니다.
또한,var
는 변수를 또 선언하고 마음대로 지지고 볶을 수 있지만,let
과const
는 재선언시 에러가 발생합니다.
const
변수는 선언과 동시에 할당하며, 이 값은 변동 될 수 없습니다.
hoisting
개념을 빌려 설명을 했었습니다. 더 첨언하면, 아래 정답이 더 깔끔합니다!
var
:function level scope
를 가지며 이로 인해호이스팅
현상이 일어난다. 재할당 가능
let
:block level scope
를 가지며 재할당이 가능하다.
const
:block level scope
를 가지며 재할당이 불가능하다. 그러나 할당된 객체의 함수를 이용해 객체를 변경하는 일은 가능하다.
당연한 사실이지만, 나름 새롭네요! 아래와 같이 const
로 선언된 배열은 함수로 변경이 가능하답니다.
const arr1 = []; arr1 = [1,2]; // Error! arr1.push(1); // 가능 arr1.push(2); // 가능
클로저
는c++
과 약간은 비슷하다고 느껴졌습니다.
함수레벨 스코프
는전역변수
처럼 어디서나 접근가능한 범위를 말하며,블럭 레벨 스코프
는for
,if
,while
,function
내에서만 접근 가능한 범위를 말합니다.
호출 스택
과도 약간 연관이 있어보입니다.function play
안에let number
를 선언하고, 그 함수안에 또 다른function sum
이 있다면,sum
에서number
를 쓸순 있지만sum
함수에서 선언된 그 어떤 변수도play
함수에선 사용할 수 없습니다.
제가 기존에 다루던 언어인 C++
과 약간 개념이 비슷해서, 그를 활용해 답변했습니다.
자신의 scope 외부에 있는 것을 가져와 쓰는 것.
예시)var a = 1; function hello() { console.log(a); // a가 hello function scope에 없는데에도 접근 가능함. }
??? 당연한거 아닌가.. 싶네요! 뭐 정답은 맞춘 것 같습니다 :)
오늘은 이렇게 1월 20일
에 시작할 프론트엔드 개발을 위한 자바스크립트
소개겸, 사전 퀴즈를 정리해보았습니다!
이제부터 매 주 과제 정리하고 제가 진행현황을 정리해보려고 해요 :)
갑사합니다! 😍
스터디에서 코드리뷰 말고도 자바스크립트 문법 강의도 해주시나요?