-
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가 어려운 것 같아서 여러번 봐야겠다.
'Javascript' 카테고리의 다른 글
Javascript30 - CSS + JS CLOCK (0) 2021.06.17 Javascript30 - DRUM KIT (0) 2021.06.16 미니프로젝트 - 캘린더, 베이스볼게임 (0) 2021.06.04 투두리스트 마무리, 미니프로젝트 background changer, carousel (0) 2021.06.03 노마드코더 투두리스트 날씨 클론코딩 4 (0) 2021.06.02