[Section1] JavaScript_koans

정호·2023년 3월 6일
0

코드스테이츠

목록 보기
16/49

JavaScript_koans란

Koans는 불교에서 유래된 단어로, 결론을 내리기 전에 이게 왜 맞는지 깊게 고민한다는 의미를 가지고 있습니다.
JavaScript Koans는 부트캠프에서 하게 된 자바스크립트를 전체적으로 공부하고 되돌아보며 문제를 푸는 시스템입니다.

부트캠프에서 처음 해보는건 아니였지만 아직 익숙하지 않은 환경이라 적응하는
데 시간이 꽤 걸렸다.


알게된 부분

Scope

❖ 호이스팅:

    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;

클로저_2

  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의 리턴은 이 함 수 자체


Object

  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); //같은 주소 참조해서 삭제된다
  });
});


profile
열심히 기록할 예정🙃

0개의 댓글