
특강이 왜 이리 많은지....
특강은 그냥 새로 배운거나 유의미한 것만 노트한걸로
justify-content: space-between (양옆으로 퍼지도록)
position: absolute (특정 위치에 고정)
position: fixed (화면상 고정)
sticky // (사이드바) aside // 히어로 섹션
... 그리고 노트가 이게 정말 다였다고 한다.
어제부터 들은 내용까지 포함하여 요약을 하려고 했더니
복습은 잘 되지만 머리도 같이 멍해졌다.
데이터 타입
데이터 타입의 종류는 크게 기본형(Primitive type)와 참조형(Reference type)으로 나뉜다. 그리고 이 둘을 나누는 기준은 값을 저장하는 방식과 불변성 여부이다.
이를 변수 선언과 할당의 방식을 보며 무슨 뜻인지 더 자세히 배우게 되었다.
변수 선언과 데이터 할당
여기서 키포인트는 값을 바로 변수에 저장하는 것이 아닌 데이터를 저장한 주소값을 따로 저장하는 것. 이 방법의 이유는
C도 비슷한 방식으로 메모리를 저장 관리하기 때문에 강의 보면서 많이 유사하다는 것을 느꼈다. 차이가 있다면 JS는 garbage collector가 있어서 C처럼 개발자가 일일이 메모리를 관리할 필요는 없다는 점이다.
기본형과 참조형 데이터
메모리에 대해 더 자세히 알아보면 변수와 상수 그리고 불변하다의 개념이 중요하다는 것을 알게된다.
기본형은 따라서 불변하다고 할때, 데이터가 바뀔때 아래의 방법을 따른다.
// a라는 변수가 abc에서 abcdef가 되는 과정
// 'abc'라는 값이 데이터영역의 @5002라는 주소에 들어갔다고 가정
var a = 'abc';
// 'def'라는 값이 @5002라는 주소에 추가되는 것이 아닌
// 새로운 주소 @5003에 별도로 'abcdef'라는 값이 생기는 것
// 그 다음에 a의 주소를 @5003으로 바꾸는 방식
// 즉, "변수 a는 불변하다." 라고 할 수 있습니다.
// 이 때, @5002는 더 이상 사용 X ->가비지컬렉터의 수거 대상
a = a + 'def';
참조형 데이터는 이와 다르게 가변성을 띈다. 그런데 이것이 복제할때 문제로 이어진다. 그리고 이를 해결하기 위해서는 불변 객체가 필요한 것이다. 이를 위해 알아두어야 하는 것이 얕은 복사와 깊은 복사이다.
얕은 복사 VS 깊은 복사
가변성에 따른 문제점 (복제시)
// user 객체를 생성
var user = {
name: 'Gamja',
gender: 'NaN',
};
// 이름을 변경하는 함수, 'changeName'을 정의
// 입력값 : 변경대상 user 객체, 변경하고자 하는 이름
// 출력값 : 새로운 user 객체
// 특징 : 객체의 속성에 접근해서 이름을 변경 -> 가변
var changeName = function (user, newName) {
var newUser = user;
newUser.name = newName;
return newUser;
};
// 변경한 user정보를 user2로 저장
var user2 = changeName(user, 'Gamja2');
// 유저와 유저2의 정보가 일치 하지 않을때 실행
// 하지만 실행되지 못함
if (user !== user2) {
console.log('유저 정보가 변경되었습니다.');
}
console.log(user.name, user2.name); // Gamja2 Gamja2
console.log(user === user2); // true
우리는 새로운 객체 user2의 이름만 바꾸고 싶었지만 기존에 있던 유저 정보까지 바뀌는 문제점을 확인 할 수 있다. 따라서 새로운 객체에 데이터만 복제하는 방식이 필요하다. 위 예시에 대입해볼 수 있는 방법은 아래와 같다.
// 얕은 복사
var copyObject = function (target) {
var result = {};
for (var prop in target) {
result[prop] = target[prop];
}
return result;
}
위 코드를 보면 데이터만 복제하고 객체는 새로 만들어진 result가 되는 것을 볼 수 있다.
var user2 = copyObject(user);
user2.name = 'Gamja2';
if (user !== user2) {
console.log('유저 정보가 변경되었습니다.');
}
그러면 user2의 속성인 name의 정보를 바꾸었을 때 새로운 데이터의 주소값이 생겨서 바뀌므로 user의 정보는 바뀌지 않는다!
그런데 만약에 객체가 기본형 데이터만으로 이루어져있지 않다면?
var user = {
name: 'Gamja',
urls: {
portfolio: 'http://github.com/Gamja',
blog: 'http://blog.com/@Gamja',
facebook: 'http://facebook.com/Gamja',
}
};
그러면 얕은 복사로도 결국에는 같은 문제가 발행한다. 따라서 필요한 것이 깊은 복사이다. 재귀적 함수를 만들면 이를 해결 할 수 있다.
// 깊은 복사
var copyObjectDeep = function(target) {
var result = {};
if (typeof target === 'object' && target !== null) {
for (var prop in target) {
result[prop] = copyObjectDeep(target[prop]);
}
} else {
result = target;
}
return result;
}
여기에 더해 JSON을 이용한 방법도 있지만 얕은 복사의 개념이라고 생각하고 쓰는 것이 좋을 듯하다. 이는 JSON이 객체에 undefined나 함수와 같은 속성을 복사하지 못하기 때문이다.
결론은 객체의 구조가 복잡하지 않다면 얕은 복사 혹은 JSON의 방법을 사용해도 무방하며, 확실하게 복사 하고 싶은 경우에는 깊은 복사를 활용하는 것이 실용적이다.
null, undefined
null은 없음을 명시적으로 쓸때 사용한다. JS에서는 typeof null이 object로 뜨는 유명한 버그가 있다.
undefined: 사용자(=개발자)가 직접 지정할 수도 있지만 일반적으로는 자바스크립트 엔진에서 값이 있어야 할 것 같은데 없는 경우, 자동으로 부여합니다.

챗GPT가 요약해준 내용:
In short, undefined means "no value assigned yet," and null means "intentionally empty."
실행 컨텍스트
실행할 코드에 제공할 환경 정보를 모아놓은 객체를 실행 컨텍스트라고 한다. 그리고 이 객제 안에는 3가지로 이루어져있다.
작동방식은 LIFO를 따르는 call stack 형식이다
VE, LE
그 중 VE와 LE는 완벽히 똑같지만 하나가 다르다. LE가 변경사항을 계속해서 반영하고 스냅샷을 유지 않는다는 것. VE는 스냅샷을 유지한다.
따라서 실행컨텍스트가 생성될때 VE를 먼저 만들고 그대로 복사한것이 LE가 된다.
그리고 LE는 dkfo 2가지 정보를 가지고 있다
Record & Hoisting
순서대로 수집 (실행 아님)하는 것을 Hoisting이라고 하며 이는 가상 개념이다. 법칙은 2가지
그리고 함수는 선언문 대신 표현식을 사용하는 것이 hoisting 때 생기는 예상치 못한 버그를 예방할 수 있다.
사실 이 부분은 아직 완벽히 이해가 덜 되서 주말에 따로 더 보거나 시간이 나면 계속해서 강의를 돌려봐야할 것 같다. 이게 Python이랑 작동 방식이 너무 다른것 같은데 머리가 어질어질하다ㅠㅠ.
스코프, 스코프 체인
이 부분을 강의 보면서 같이 푼 예시가 있다.
// 아래 코드를 여러분이 직접 call stack을 그려가며 scope 관점에서 변수에 접근해보세요!
// 어려우신 분들은 강의를 한번 더 돌려보시기를 권장드려요 :)
var a = 1;
var outer = function() {
var inner = function() {
console.log(a); // 이 값은 뭐가 나올지 예상해보세요! 이유는 뭐죠? scope 관점에서!
var a = 3;
};
inner();
console.log(a); // 이 값은 또 뭐가 나올까요? 이유는요? scope 관점에서!
};
outer();
console.log(a); // 이 값은 뭐가 나올까요? 마찬가지로 이유도!
내 예상 답안은 1, 1, 1었는데
정답은 undefined, 1, 1이다.
해설) inner 안의 a가 선언되어있는데 hoisting 되면서 올라오며, 변수가 아직 할당 되기 전에 console.log가 먼저 오기 때문에 이 때 아직 값이 없으므로 undefined가 나오게 된다. outer는 따로 a선언이 없으므로 전역에 선언되어있던 a=1 값을 이용하게 되어서 1이 잘 나온다.
잊지 말자, 실행컨텍스에 원래 ThisBinding까지 포함되어 있다.
상황에 따르는
this
this는 함수를 호출할 때 결정된다. 따라서 런타임과 환경이 중요한데
노드에선 global, 브라우저에서는 이가 window이다.
추가 노트) 함수 VS 메소드
함수는 호출의 주체가 없어서 this->전역객체, 메소드는 this->호출의 객체
함수에서의 this
그럼 만약에 함수 내에서 this는 무엇인가? 지정되지 않는다. 따라서 이 경우에는 전역 객체가 된다. "함수로서 독립적으로 호줄할 때는 this는 항상 전역 객체"
var obj1 = {
outer: function () {
console.log("Testing(outer) =>", this); // (1) outer
var innerFunc = function () {
console.log("Testing(innerFunc) =>", this); // (2) 전역객체, (3) obj2
};
innerFunc();
var obj2 = {
innerMethod: innerFunc,
};
obj2.innerMethod();
},
};
obj1.outer();
이러한 this의 특징을 알아보았는데 그럼 어떻게 활용하는가
ㅇㅅㅇ... 이제부터 알아보시죠
우회!
this를 별도의 변수에 할당해서 사용하기this를 바인딩하지 않는 함수이다. 따라서 this가 상위값으로 유지가 된다 (일반 함수와의 가장 큰 차이이기도 하다!)var obj = {
outer: function() {
console.log(this); // (1) obj
var innerFunc = () => {
console.log(this); // (2) obj 전역객체가 아님!
};
innerFunc();
}
}
obj.outer();
이제 그럼 유의할 점이 없나 싶지만 우리에겐 callback 함수가 남아있다
콜백 함수도 함수다!
따라서 콜백함수 내의 this는 전역객체를 바라볼 수 밖에 없다. 단, 예외가 있다. 이는 콜백 함수에 별도의 this를 지정한 경우.
마지막으로 생성자 함수 내부에서의 this 가 남아있다.
다만 여기서는 생성하고 있는 객체를 가르키는 것으로 아래 예시를 보자
var Cat = function (name, age) {
this.bark = '야옹';
this.name = name;
this.age = age;
};
var choco = new Cat('초코', 7); //this : choco
var nabi = new Cat('나비', 5); //this : nabi
이 예시에서의 this는 각각의 choco와 nabi가 되는 것!
명시적 this바인딩
코딩을 하다보면, 이 this의 규칙을 깨고 별도의 값을 저장하는 방법이 필요하다. 크게 세가지와 화살표 함수가 있다.
이 특강도 그냥 노트만 하기로 하였다. 왜냐 난 감자니까
(이때부터 정신 놓은 듯, 출간하면서 보는데 이 모양이네)
뽑고 싶은 개발자
문제 해결 능력
-> 문제를 인식하는 능력, 이를 해결하기 위해 무슨 시도를 해야하는지, 이러한 문제를 남들에게도 표현할 수 있는 사람
커뮤니케이션이 불편하지 않은 사람? 나는 소통이 잘 된다를 어떻게 잘 표현하는가??
1. 동문서답을 하지 않기
기술적인 요구사항이 아닌 자질이나 성향을 바라보는 이유
중요한건 협업(Communication, Soft Skill)과 기술적인 고민(Hard skill)
Hard Skill
1. 로직과 코드에 대한 의도를 생각하기
2. 구현하는 기술, 스택에 목적과 근거 가지기
3. 더 좋은 방법이 있는지 고민하기
Soft Skill
1. 예쁘게 말하기: 피드백은 고심 그리고 킥은 대안
2. 전달하고자 하는 바를 명확하게 말하기 (동문서답 안하도록 노력하기!) -> 두괄식!!
3. 데이터 또는 기술적인 근거를 바탕으로 소통하기
"옳은 말을 기분 좋게 하라 당해낼 자가 없다"
알고리즘은 그저 연습 연습 연습! 오늘 같이 푼 문제
Brute Force Algorithm: 모든 경우의 수를 확인 하는 알고리즘
가장 기본적인 찾기 알고리즘이자, 데이터가 많아질 수록 비효율적인 알고리즘이기도 하다.
문제1)
정수로 이루어진 정렬된 배열과 목표 숫자가 주어졌을 때, 목표 숫자가 배열에 존재하는지 확인하고 그 인덱스를 반환하는 문제입니다. 목표 숫자가 배열에 없다면 -1을 반환합니다. (단, 배열 메서드를 쓰지 않고 loop문을 통해 구현해주세요. []를 통해 배열 값에 접근 하는 것은 가능합니다.)
function linearSearch(arr, target) {
// 내 답안
for (let i = 0; i < arr.length; i++) {
if (arr[i] === target) {
return i;
}
}
return -1;
}
그리고 다행히도 이번 문제는 모범답안과 일치했다.ㅎㅎ
감자 여기 눕다...
이해하기 좋게 이미지도 잘 찾아오셨네요! til 읽는데 너무 재미있었습니다. 많은 것을 제공 드리려고 하는 저희 내배캠의 욕심(?)이 조금 벅차게 느껴 졌을 지도 모르겠내요 하지만 정말 이 캠프 다니는 동안 쭈욱 캐어 할 예정이라 후후 익숙해 지도록 합시다 ( ̄y▽, ̄)╭