Koans는 불교에서 유래된 단어로, 결론을 내리기 전에 이게 왜 맞는지 깊게 고민한다는 의미를 가지고 있습니다.
JavaScript Koans는 부트캠프에서 하게 된 자바스크립트를 전체적으로 공부하고 되돌아보며 문제를 푸는 시스템입니다.
부트캠프에서 처음 해보는건 아니였지만 아직 익숙하지 않은 환경이라 적응하는
데 시간이 꽤 걸렸다.
❖ 호이스팅:
expect(typeof funcDeclared).to.equal('function');
expect(typeof funcExpressed).to.equal('string');
function funcDeclared() {
return 'this is a function declaration';
}
funcExpressed = function () {
return 'this is a function expression';
};
함수 선언문으로 정의된 함수는 호이스팅이 일어난다.
함수 표현식으로 작성된 함수는 호이스팅이 일어나지 않는다.
함수 표현식을 사용할 것을 권장한다.
❖ 변수 호이스팅: JavaScirpt에서 모든 변수는 undefined
실행하는 과저에서 재할당하는 방식으로 코드가 동작하는데
console.log(vari);// undefined
var vari = 'vari'
console.log(variable)
let variable= 'variable' // cannot acces 'variable'
호이스팅 일어나지 않도록하는게 좋음 변수 선언하기전에 console.log했을때 오류 나는게 좋음
it('lexical scope에 대해서 확인합니다.', function () {
let message = 'Outer';
function getMessage() {
//함수 내부에 message가 없으니 외부에서 참조
return message;
}
function shadowGlobal() {
let message = 'Inner';
return message;
//함수 내부에 message가 있으니 내부에서 참조
}
function shadowGlobal2(message) {
return message;
//함수 내부에 message 매개변수가 있기때문에 있다고봄(매개변수 참조)
}
function shadowParameter(message) {
message = 'Do not use parameters like this!';
return message;
// 재할당, 외부 변수에 재할당, 파라미터 이런식으로 쓰지마라
}
expect(getMessage()).to.equal('Outer');
expect(shadowGlobal()).to.equal('Inner');
expect(shadowGlobal2('Parameter')).to.equal('Parameter');
expect(shadowParameter('Parameter')).to.equal('Do not use parameters like this!');
expect(message).to.equal('Outer');
});
const increase = function(){
let num = 0;
return ++num;
클로저활용
const increase = function(){
let num = 0;
return function (){ //이 내부함수의 렉시컬환경은 함수가 선언된 장소(increas함수 전체) 외부에서 num이라는 변수 참조할 수 없음
return ++num;
};
}
const increase = function(){
let num = 0;
return{
plus: function() {return ++num},
minus: function() {return --num},
current: function() {return num}
}
}
const increase1 = increase(){
console.log(increase1.plus());//1
console.log(increase1.plus());//2
console.log(increase1.plus());//3
console.log(increase1.minus());//2
console.log(increase1.current());//2
const increae1 = increase();외부에서 외부함수의 실행결과를 변수에 할당하면 increse1이라는게 이 함수의 이름이 된거처럼 되고 이 걸 사용하면 내부에 있는 변수에 접근 가능하게된다.
클로저 조건
it('클로저(closure)에 대해 확인합니다.', function () {
function increaseBy(increaseByAmount) {
return function (numberToIncrease) {
return numberToIncrease + increaseByAmount;
};
}
const increaseBy3 = increaseBy(3);
const increaseBy5 = increaseBy(5);
expect(increaseBy3(10)).to.equal(13);
expect(increaseBy5(10)).to.equal(15);
expect(increaseBy(8)(6) + increaseBy(5)(9)).to.equal(28);
increaseBy3
은 다음과 동일한 의미
function increaeBy3 (numberToincreae){
return numberToIncrease +3;
it('lexical scope와 closure에 대해 다시 확인합니다.', function () {
let age = 27;
let name = 'jin'; // 'jimin'
let height = 179;
function outerFn() {
let age = 24; //26
name = 'jimin'; //'jimin'재할당, 내부에는 name없으니 jin ->jimin
let height = 178;
function innerFn() {
age = 26; // innerFn함수 내부에 age가 없음 27->26
let name = 'suga'; //innerFn내부에서만 'suga'
return height;
}
innerFn();
expect(age).to.equal(26);
expect(name).to.equal('jimin');
return innerFn;
}
const innerFn = outerFn(); //변수 InnerFn은 OuterFn 내부에 있는 InnerFn함수와 동일하게 동작
expect(age).to.equal(27);// outerFn밖에서 참조할때
expect(name).to.equal('jimin');
expect(innerFn()).to.equal(178); // innerFn실행 height없기 때문에 외부의 height참조해서 178
});
});
outerfn의 리턴값을 innerfn에 저장, innerfn의 리턴은 이 함 수 자체
it('Object를 함수의 전달인자로 전달할 경우, reference가 전달됩니다.', function () {
const obj = {
mastermind: 'Joker',
henchwoman: 'Harley',
relations: ['Anarky', 'Duela Dent', 'Lucy'],
twins: {
'Jared Leto': 'Suicide Squad',
'Joaquin Phoenix': 'Joker',
'Heath Ledger': 'The Dark Knight',
'Jack Nicholson': 'Tim Burton Batman',
},
};
function passedByReference(refObj) {
refObj.henchwoman = 'Adam West'; //refObj로 전달된 henchwoman을 'Adam West'로 변경
}
passedByReference(obj);
expect(obj.henchwoman).to.equal('Adam West');
const assignedObj = obj; //객체가 할당된 변수를 다른 변수에 할당했을때 -> 같은 주소를 참조한다.
assignedObj['relations'] = [1, 2, 3];
expect(obj['relations']).to.deep.equal([1,2,3]); //같은주소 참조하고있으니 변경하면 원본도 변경(복사는 x)
const copiedObj = Object.assign({}, obj); //배열로 치면 arr.slice()
copiedObj.mastermind = 'James Wood';
expect(obj.mastermind).to.equal('Joker'); //copied만 바뀜
obj.henchwoman = 'Harley';
expect(copiedObj.henchwoman).to.equal("Adam West"); //원본만 바꾼거임
delete obj.twins['Jared Leto'];
expect('Jared Leto' in copiedObj.twins).to.equal(false); //같은 주소 참조해서 삭제된다
});
});