ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • koan 풀기
    Javascript 2021. 6. 6. 22:16

    koan은 자바스크립트 기본 프로그래밍을 퀴즈 형식의 문제를 풀며 이해하는 방식으로 진행된다.

    https://github.com/mrdavidlaing/javascript-koans

     

    mrdavidlaing/javascript-koans

    Koans to learn Javascript. Contribute to mrdavidlaing/javascript-koans development by creating an account on GitHub.

    github.com

     

    1. Thinking About Expects

    등호를 배워보자

    10=='10': a와 b의 값이 같다.

    10===10: a와b는 값에다가 데이터 타입까지 같다.

     

    2. Thinking About Arrays

    배열을 배워보자

    하나의 배열에는 여러 타입의 원소가 들어갈 수 있다. ( 값,함수,문자열,객체,배열 등등)

    array.push(a): array의 마지막에 새로운 원소로 a를 추가한다.

    array.push(a,b): a와 b는 각각 array의 새로운 원소이며 인덱스가 +2 된다.

    var emptyArray = new Array(10): 길이가 10인 배열 emptyArray 생성 방법

    array.slice(a,b): array의 a번째 인덱스 원소부터 b-1번째 원소까지를 잘라서 새로운 배열로 리턴한다.

    array.pop(): array의 마지막 원소를 삭제하고 이를 리턴한다.

    array.unshift(a): array의 맨 처음에 a를 넣고 새로운 배열의 길이를 리턴한다.

     

    3. Thinking About Functions

    함수를 배워보자

     

    var variable = "top-level";
    
    function parentfunction() {
      var variable = "local";
      function childfunction() {
        return variable;
      }
      return childfunction();
    }
        

    --> 전역변수 variable과 parentfunction함수 내에 지역변수 variable 이 있다.

    parentfunction함수 내의 childfunction함수는 variable변수를 리턴하는데 이 값은 지역변수 variable이다. 

     

     

        function returnFirstArg(firstArg) {
          return firstArg;
        }
    
        expect(returnFirstArg("first", "second", "third")).toBe('first');
    
        function returnSecondArg(firstArg, secondArg) {
          return secondArg;
        }
    
        expect(returnSecondArg("only give first arg")).toBe(undefined);

    -->하나의 인자를 갖는 함수 function firstArg(first)는 firstArg(a,b,c);를 했을 때 a만을 인자로 갖는다.

    인자가 정해지지 않은 함수 function returnAllArgs()는 returnAllArgs(a,b,c);를 했을 때 a,b,c 모두 인자로 갖는다.

     

     

        var appendRules = function (name) {
          return name + " rules!";
        };
    
        var praiseSinger = { givePraise: appendRules };
        expect(praiseSinger.givePraise("John")).toBe('John rules!');

    --> 함수를 변수에 저장하면 변수명을 가지고도 이용할 수 있다.

     

    4. Thinking About Objects

    객체를 배워보자

        var megalomaniac = {
          mastermind : "Brain",
          henchman: "Pinky",
          battleCry: function (noOfBrains) {
            return "They are " + this.henchman + " and the" +
              Array(noOfBrains + 1).join(" " + this.mastermind);
          }
        };
    
        var battleCry = megalomaniac.battleCry(4);
        expect(battleCry).toMatch('They are Pinky and the Brain');

    --> megalomaniac 객체는 mastermind, henchman, battleCry 프로퍼티를 가지고 있고 이중 battleCry는 함수이다.

    객체 내 함수는 객체가 가지고 있는 변수를 사용하고 싶을 때 this.변수명으로 사용할 수 있다.

     

        var megalomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };
    
        expect("secretary" in megalomaniac).toBe(false);
    
        megalomaniac.secretary = "Agent Smith";
        expect("secretary" in megalomaniac).toBe(true);

    --> 이미 만들어진 객체에도 프로퍼티를 추가할 수 있다.

     

     

          function Circle(radius)
          {
            this.radius = radius;
          }
    
          var simpleCircle = new Circle(10);
          var colouredCircle = new Circle(5);
          colouredCircle.colour = "red";
    
          expect(simpleCircle.colour).toBe(undefined);
          expect(colouredCircle.colour).toBe('red');
    
          Circle.prototype.describe = function () {
            return "This circle has a radius of: " + this.radius;
          }; // 프로토타입에 메서드 넣으면 모든 객체에서 사용가능
    
          expect(simpleCircle.describe()).toBe('This circle has a radius of: 10');
          expect(colouredCircle.describe()).toBe('This circle has a radius of: 5');

     --> 모든 객체에 적용하고 싶다면 prototype에다가 넣어라.

     

    5. Think About Mutability

        var aPerson = {firstname: "John", lastname: "Smith" };
        aPerson.firstname = "Alan";
    
        expect(aPerson.firstname).toBe('Alan');

    --> 객체의 프로퍼티는 public,mutable 라서 값을 바꿀 수 있다.

     

        function Person(firstname, lastname)
        {
          var fullName = firstname + " " + lastname;
    
          this.getFirstName = function () { return firstname; };
          this.getLastName = function () { return lastname; };
          this.getFullName = function () { return fullName; };
        }
        var aPerson = new Person ("John", "Smith");
    
        aPerson.firstname = "Penny"; // aPerson에 firstname이라는 변수가 들어갔고 인자firstname이랑은 다르다.
        aPerson.lastname = "Andrews";
        aPerson.fullName = "Penny Andrews";
    
        expect(aPerson.getFirstName()).toBe('John');
        expect(aPerson.getLastName()).toBe('Smith');
        expect(aPerson.getFullName()).toBe('John Smith');
        console.log(aPerson);
        aPerson.getFullName = function () {
          return aPerson.lastname + ", " + aPerson.firstname;
        };
    
        expect(aPerson.getFullName()).toBe('Andrews, Penny');

    --> 구조체 내부 변수와 구조체 인자는 private이다. aPerson.fullName과 aPerson.getFullName()의 값은 다르다.

     

    6. Thinking About Higher Order Functions

    filter, map, reduce, forEach, all, any, range, flatten, chain, value

     

    1. filter

    function () {
        var numbers = [1,2,3];
        var odd = _(numbers).filter(function (x) { return x % 2 !== 0 });
    
        expect(odd).toEqual([1,3]);
        expect(odd.length).toBe(2);
        expect(numbers.length).toBe(3);
    }

    --> numbers배열 안의 모든 원소에 대해서 return값이 true인 원소만을 odd에 저장한다.

     

    2. map

    function () {
        var numbers = [1, 2, 3];
        var numbersPlus1 = _(numbers).map(function(x) { return x + 1 });
    
        expect(numbersPlus1).toEqual([2,3,4]);
        expect(numbers).toEqual([1,2,3]);
    }

    --> numbers배열 안의 모든 원소에 x+1을 적용한 값을 numbersPlus1에 저장한다.

     

    3. reduce

    function () {
        var numbers = [1, 2, 3];
        var reduction = _(numbers).reduce(
                function(/* result from last call */ memo, /* current */ x) { return memo + x }, /* initial */ 0); // 배열.reduce((누적값,현재값,인덱스) => {return 결과}, 초기값);
    
        expect(reduction).toBe(6);
        expect(numbers).toEqual([1,2,3]);
    }

    -->reduce는 배열 내의 모든 원소의 합을 구할때 자주 쓰이며, reduce(function(누적값,더할값) {return 누적값+더할값},0) 의 문법을 따른다.0은 누적값의 초기값이다.

     

    4. forEach

    function () {
        var numbers = [1,2,3];
        var msg = "";
        var isEven = function (item) {
          msg += (item % 2) === 0;
        };
    
        _(numbers).forEach(isEven);
    
        expect(msg).toEqual('falsetruefalse');
        expect(numbers).toEqual([1,2,3]);
    }

    --> forEach(function)는 원소 각각에 특정 함수를 적용할때 쓰인다.

     

    7. Thinking About Inheritance

    function Muppet(age, hobby) {
      this.age = age;
      this.hobby = hobby;
    
      this.answerNanny = function(){
    	return "Everything's cool!";
      }
    }
    
    function SwedishChef(age, hobby, mood) {
      Muppet.call(this, age, hobby);
      this.mood = mood;
    
      this.cook = function() {
        return "Mmmm soup!";
      }
    }
    
    SwedishChef.prototype = new Muppet();
    
    function() {
      beforeEach(function(){
        this.muppet = new Muppet(2, "coding");
    	this.swedishChef = new SwedishChef(2, "cooking", "chillin");
    }
    
    expect(this.swedishChef.cook()).toEqual('Mmmm soup!');
    expect(this.swedishChef.answerNanny()).toEqual("Everything's cool!");
    
    

    --> SwedishChef.prototype = new Muppet();을 통해서 상속이 일어났고 swedishChef는 answerNanny 프로퍼티를 사용할 수 있게 된다.

     

    8. Thinking About Applying What We Have Learnt

    지금까지 배운 기본 개념을 써먹어보자.

        var sum = 0; 
        var numArr = _.range(1000).filter(function(x) {if (x%3===0 || x%5===0) {return x; }})
        sum = numArr.reduce(function(accum,curr) {return accum+curr},0);
        
        console.log(sum);
        expect(233168).toBe(sum);
    

    --> range(1000)으로 0부터 999까지 만든 다음 3이나 5로 나눠지는 수만 numArr에 넣는다. reduce를 이용해서 그 숫ㅈ들을 다 더한다.

     

      var products;
    
      beforeEach(function () {
        products = [
           { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
           { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
           { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
           { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
           { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
        ];
      }
    
    function () {
        var ingredientCount = { "{ingredient name}": 0 };
    
        for (i = 0; i < products.length; i++) {
            for (j = 0; j < products[i].ingredients.length; j++) {
                ingredientCount[products[i].ingredients[j]] = (ingredientCount[products[i].ingredients[j]] || 0) + 1;
            }
        }
        console.log(ingredientCount);
        expect(ingredientCount['mushrooms']).toBe(2);
    }

    --> product 배열은 음식 객체가 원소로 이루어져 있고, 함수는 이 음식에 어떤 재료가 몇번 들어갔는지 알아내는 함수이다. 

    객체의 길이로 for문을 돌리고 그 안에서 ingredient의 길이로 for문을 돌려서 ingredientCount객체에 성분명과 개수를 삽입하는 과정을 거친다.

     

    배열과 객체를 사용해서 코드 작성하는 법을 배웠는데 아직 어떤 작성법이 더 좋은지를 모르기 때문에 좋은게 맞나 하는 생각이 든다. 객체, 메서드, this가 어려운 것 같아서 여러번 봐야겠다.

Designed by Tistory.