es6에서의 객체

ES6 이전 자바스크립트에서 클래스를 만드는 건 직관적이지 않고 번거로웠음.
ES6에서는 클래스를 만드는 간편한 새 문법을 도입

1
2
3
4
5
6
class Car{ //새 클래스 Car를 만듦
//아직 인스턴스는 만들어지지 않았지만 언제든 만들 수 있음
constructor(){
}
}

인스턴스를 만들 때는 new키워드 사용

1
2
const car1 = new Car();
const car2 = new Car();

이제 Car클래스의 인스턴스가 두개 생김.
제조사(make), 모델 데이터, 변속(shift)기능을 추가해보자

1
2
3
4
5
6
7
8
9
10
11
12
13
class car{
constructor(make, model){
this.make = make;
this.model = model;
this.userGears = ['p','n','r','d'];
this.userGear = this.userGears[0];
}
shift(gear){
if(this.userGears.indexOf(gear)<0)
throw new Error(`Invalid gear:${gear}`);
this.userGear = gear;
}
}

이 클래스를 실제로 사용하면 다음과 같이 사용할 수 있다.

1
2
3
4
5
6
7
8
9
const car1 = new car("kia", "chacha");
const car2 = new car("honda", "molla");
car1.shift('d');
car2.shift('r');
car1.userGear //"d"
car2.userGear //"r"
car1.make; //"kia"
car1.model; //"chacha"

공유하기 댓글

객체와 객체지향 프로그래밍

배열과 자바스크립트 객체의 다른점

  • 배열은 값을 가지며 각 값에는 숫자형 인덱스가 있음.
  • 객체는 프로퍼티를 가지며, 프로퍼티는 키와 값을로 구성.
  • 배열은 순서가 있지만 객체에는 없음

객체의 가장 큰 특징은 키를 통해 프로퍼티에 접근 할 수 있다는 점

프로퍼티의 나열

객체 프로퍼티에는 순서가 없음

for…in

객체 프로퍼티 나열할 때…

1
2
3
4
5
6
7
8
9
10
const obj = Symbol();
const o = {a:1, b:2, c:3, [obj]:4};
for(let prop in o){
if(!o.hasOwnProperty(prop)) continue;
console.log(`${prop}: ${o[prop]}`);
}
//a: 1
//b: 2
//c: 3

for...in 루프에는 키가 심볼인 프로퍼티는 포함되지 않음
(obj는 Symbol()로 되어 있음)

Object.keys

Object.keys는 객체에서 나열 가능한 문자열 프로퍼티를 배열로 반환

1
2
3
4
5
6
7
const SYM = Symbol();
const o = {a:1, b:2, c:3, [SYM]:4};
Object.keys(o).forEach(prop=>console.log(`${prop}: ${o[prop]}`));
//a: 1
//b: 2
//c: 3

객체의 프로퍼티 키를 배열로 가져와야 할 때는 Object.keys가 편함
예를 들어 객체에서 x로 시작하는 프로퍼티를 모두 가져온다면 다음과 같이 할 수 있음

1
2
3
4
5
const o = {apple:1, xochitl:2, balloon:3, guitar:4, xylophone:5};
Object.keys(o).filter(prop=>prop.match(/^x/)).forEach(prop=>console.log(`${prop}: ${o[prop]}`));
//xochitl: 2
//xylophone: 5

프로토타입

클래스의 인스턴스에서 사용할 수 있는 메서드 = 프로토타입
예를들어 car의 인스턴스에서 사용할 수 있는 shift메서드는 프로토타입 메서드.

프로토타입 메서드는 Car.prototype.shit처럼 표기할 때가 많음.
최근에는 프로토타입 메서드를 #으로 표시하는 표기법이 쓰임.
Car.protoptype.shift를 Car#shift로 씀. 또한 객체 생성자, 즉 클래스는 Car처럼 항상 첫 글자를 대문자로 표기.

공유하기 댓글

자바스크립트 array

배열의 기초

  • 배열은 객체와 달리 순서가 있는 집합, 0으로 시작하는 숫자형 인덱스 사용
  • 한 배열의 요소가 모두 같은 타입일 필요는 없음
  • 배열 리터럴은 대괄호로 만들고 배열요소에 인덱스로 접근할 때도 대괄호를 사용
  • 배열에 요소가 몇개 있는지 나타내는 length프로퍼티가 있음
  • 배열 길이보다 큰 인덱스를 사용하여 요소를 할당하면 배열은 자동적으로 인덱스에 맞게 늘어남. 빈자리는 undefined로 채워짐
  • array생성자로 배열을 만들 수 있지만 그렇게 해야하는 경우는 별로 없음

배열 처음이나 끝에서 요소 하나를 추가하거나 빼기

push, pop, unshift, shift

1
2
3
4
5
6
const arr = ["b", "c", "d"];
undefined
arr.push("e"); // (4) ["b", "c", "d", "e"]
arr.pop(); //"e", (3) ["b", "c", "d"]
arr. unshift("a"); //(4) ["a", "b", "c", "d"]
arr.shift(); //"a", (3) ["b", "c", "d"]


배열 끝에 여러 요소 추가하기

concat
concat메서드는 배열 끝에 료소를 추가한 사본을 반환

1
2
3
const arr = [1, 2, 3];
arr.concat(4, 5, 6); //(6) [1, 2, 3, 4, 5, 6]
//arr는 바뀌지 않음


배열 일부 가져오기

slice
slice는 두개의 매개변수를 받는다. 첫번째 매개변수는 어디서부터 가져올지, 두번째는 어디까지 가져올지. 매개 변수로 음수 인덱스를 쓸 수 있고 음수 인덱스를 쓰면 배열의 끝에서 부터 요소를 센다.
arr는 바뀌지 않는다

1
2
3
4
5
6
const arr=[1,2,3,4,5];
arr.slice(3); //[4, 5]
arr.slice(2,4); //[3, 4]
arr.slice(-2); //[4, 5]
arr.slice(1, -2); //[2, 3]
arr.slice(-2,-1); //[4]


임의의 위치에 요소 추가하거나 제거하기

splice
첫번쨰 매개변수는 수정을 시작할 인덱스, 두번쩨 인덱스는 제어할 요소 갯수. 나머지 매개변수는 배열에 추가될 요소.

1
2
3
4
5
const arr = [1,5,7];
arr.splice(1,0,2,3,4); //[], (6) [1, 2, 3, 4, 5, 7]
arr.splice(5,0,6); //[], (7) [1, 2, 3, 4, 5, 6, 7]
arr.splice(1,2); //[2,3], (5) [1, 4, 5, 6, 7]
arr.splice(2,1,'a','b'); //[5], (6) [1, 4, "a", "b", 6, 7]


배열 안에서 요소 교체하기

copyWithin
배열 요소를 복사해서 다른 위치에 붙여두고, 기존의 요소를 덮어씀
첫번째 매개변수는 복사한 요소를 붙여넣을 위치, 두번째 매개변수는 복사를 시작할 위치, 세번째는 복사를 끝낼 위치. 음수 인덱스를 사용하면 배열의 끝에서부터 셈

1
2
3
4
5
const arr = [1,2,3,4];
undefined
arr.copyWithin(1,2); //(4) [1, 3, 4, 4]
arr.copyWithin(2,0,2); //(4) [1, 3, 1, 3]
arr.copyWithin(0,-3,-1); //(4) [3, 1, 1, 3]


특정 값으로 배열 채우기

fill

1
2
3
4
5
6
7
const arr = new Array(5).fill(1); //(5) [1, 1, 1, 1, 1]
arr.fill("a"); //(5) ["a", "a", "a", "a", "a"]
arr.fill("b", 1); //(5) ["a", "b", "b", "b", "b"]
arr.fill("c", 2,4); //(5) ["a", "b", "c", "c", "b"]
arr.fill(5,5,-4); //(5) ["a", "b", "c", "c", "b"]
arr.fill(5.5,-4); //(5) ["a", 5.5, 5.5, 5.5, 5.5]
arr.fill(0,-3,-1); //(5) ["a", 5.5, 0, 0, 5.5]


배열 정렬과 역순 정렬

reverce, sort

1
2
3
const arr = [1,2,3,4,5];
arr.reverse(); //(5) [5, 4, 3, 2, 1]
arr.sort(); //(5) [1, 2, 3, 4, 5]

sort는 정렬 함수를 받을 수 있음. 일반적으로는 객체가 들어있는 배열을 정렬할 수 없지만 정렬함수를 사용하면 가능.

1
2
3
4
5
6
7
8
const arr = [{name:"shin"},{name:"hollo"},{name:"ha"},{name:"ahmad"}];
arr.sort(); //arr에 변화 없음
arr.sort((a,b)=> a.name > b.name);
//{name: "ahmad"},{name: "ha"},{name: "hollo"},{name: "shin"}
//name프로퍼티의 알파벳 순으로 정렬
arr.sort((a,b) => a.name[1] < b.name[1]);
// {name: "hollo"},{name: "ahmad"},{name: "shin"},{name: "ha"}
//name 프로퍼티 두번째 글자의 알파벳 역순으로 정렬

배열검색

indexOf, lastIndexOf
찾고자 하는 것과 정확히 일치(===)하는 첫번째 요소의 인덱스를 반환.
lastIndexOf는 배열의 끝에서 부터 검색.
일치하는 것을 찾지 못하면 -1을 반환한다.

1
2
3
4
5
const o = {name:"Jerry"};
const arr = [1,5,"a",o,true,5,[1,2],"9"];
arr.indexOf(5); //1
arr.lastIndexOf(5); //5
arr.indexOf({name:"Jerry"}); //-1

findIndex
indexOf와 비슷하지만 보조함수를 써서 검색조건을 지정할 수 있음

1
2
3
4
const arr=[{id:5, name:"shin"},{id:7, name:"hollol"}];
undefined
arr.findIndex(o => o.id ===5); //0
arr.findIndex(o=>o.name==="hollol"); //1

find
조건에 맞는 요소의 인덱스가 아니라 요소 자체를 원할 때는 find를 사용
findIndex와 마찬가지로 검색 조건을 함수로 전달할 수 있음

1
2
const arr=[{id:5, name:"shin"},{id:7, name:"hollol"}];
arr.find(o => o.id ===5); //{id: 5, name: "shin"}

some, every
some은 조건에 맞는 요소를 찾으면 즉시 true반환 찾지 못하면 false반환

1
2
3
const arr=[5,7,12,15,17];
arr.some(x=> x%2 === 0); //true, 12가 짝수이기 때문
arr.every(x=> x%2 === 0); //false


map, filter

map
map은 배열 요소를 변형

1
2
3
4
5
6
7
const cart = [{name:"book", price:123.5},{name:"tea", price:56.7}];
const names = cart.map(x=>x.name); //(2) ["book", "tea"]
const items = ["candy","choco"];
const price = [2.25, 7.3];
const list = items.map((x, i) => ({name: x, price:price[i]}));
//list : [{name: "candy", price: 2.25},{name: "choco", price: 7.3}]

filter
배열에서 필요한 것들만 남김


reduce

map이 배열 각 요소를 변형한다면 reduce는 배열 자체를 변형. reduce라는 이름은 이 메서드가 보통 배열을 값 하나로 줄이는데 쓰이기 때문에 붙여짐.

1
2
3
const arr = [5,7,2,4];
const sum = arr.reduce((a,x) => a += x, 0); //18
//0은 초기값, a의 초기값은 0이 된다.

문자열 병합

join
매개변수가 생략 될 때는 기본값 쉼표(,)
문자열 요소를 합칠 때 정의되지 않은 요소, 삭제된 요소, null, undefined는 모두 빈 문자열로 취급

1
2
3
4
5
6
const arr = [1, null, "hello", "world", true, undefined];
delete arr[3];
arr.join(); //"1,,hello,,true,"
arr.join("-"); //"1--hello--true-"
const html = '<ul><li>' + arr.join('</li><li>')+'</li><ul>';
// html : "<ul><li>1</li><li></li><li>hello</li><li></li><li>true</li><li></li><ul>"

공유하기 댓글

jquery로 퍼센트를 표시해보자!

발단

스터디에서 스터디 하시는 분이 소개팅 어플을 개발하고 계신데 거기에서 상대 매칭율을 이쁘고 아름답게 구현하심. 나도 해보고 싶었음. 하지만 쉽지 않았음.


SVG로 원을 그려보자

일단 우리에게는 원이 필요하다. svg로 원을 그려보자!

1
2
3
4
5
<div id = "cont">
<svg viewPort="0 0 320 320" width="320" height="320" id="svg" xmlns="http://www.w3.org/2000/svg">
<circle id="path" cx="160" cy="160" r="100" stroke="#000000" fill="none" stroke-width="10" stroke-linecap="round"></circle>
</svg>
</div>

See the Pen NaoyoY by shin (@hololloy) on CodePen.

그럼 이렇게 이쁜 원이 그려지는 것을 볼 수 있다.
다음단계에서는 어떻게 원에 애니메이션을 주느냐인데 여기에서 알아야 할 CSS속성이 있다.


stroke-dasharray, stroke-dashoffset

stroke-dasharray

dasharray는 점의 길이와 간격 속성을 부여한다. dasharray에 대한 설명은 여기에서 자세히 볼 수 있다.

stroke-dashoffset

specifies the distance into the dash pattern to start the dash

즉, 대시를 시작하기 위해 대시 패턴으로의 거리를 지정하는 것. 모르겠다 이건…어디 블로그에서는 점으로 만들어주는 속성이라고 하는데….얼렁뚱땅 다음 단계로 넘어가보자!


본격적인 애니메이션 작업

stroke-dasharray와 stroke-dashoffset을 설정하기 위해서는 일단 원의 둘레 길이를 알아야한다. 우리는 위에서 r(반지름)이 100인 원을 그렸는데 이 원의 둘레는 빠밤

2πr = 628.3185307179587

이렇게 나오는데 이 속성값을 클래스 cir에 넣어줘야 한다.
(자바스크립트에서 π는 Math.PI로 계산 할 수 있다.)

1
2
3
4
#svg .cir{
stroke-dasharray: 628.3185307179587;
stroke-dashoffset:0;
}

이렇게 하면 아무 변화가 없는데 여기에 애니메이션을 넣는다.

1
2
stroke-dashoffset: 628.3185307179587;
transition: stroke-dashoffset 1s linear;

그러면 원이 세시 방향에서부터 사라지는 것을 볼 수 있다.
이건 svg circle의 특성으로 작업을 용이하게 하기 위해서 시계 반대방향으로 90도 돌려주자.

1
2
3
#svg {
transform: rotate(-90deg);
}

이렇게 하면 offset수치 변화에 따른 애니메이션을 본 것이다. 포스팅을 하면서 알게된 것은 변화가 있을 때에만 애니메이션을 볼 수 있다는 것(당연한 것을…)
자, 이제 우리의 시작점은 12시에 숨어있을 것이다. 데이터를 변수 val에 입력하여 그것이 애니메이션으로 나타나게 작업을 진행해보자.

작업의 순서는 다음과 같다
특정 값 지정->값에 따른 호의 길이 계산-> css에 입력

1
2
3
4
5
6
7
8
9
10
11
$(document).ready(function(){
var val = 50; //특정 값 입력(퍼센트 계산이기 때문에 0~100 사이의 값 입력)
var $circle = $('#svg .cir');
var r = $circle.attr('r'); //
var per = ((100 - val) / 100) * Math.PI *r * 2; //호의 길이 계산
$circle.css(
strokeDashoffset: per
); //css에 offset 수치 입력
});

이렇게 하면 다음과 같은 결과가 나온다.

See the Pen QqYmjZ by shin (@hololloy) on CodePen.

$(document).ready(function(){});이 함수로 한번 더 감싸주지 않아서 자꾸 오류가 생겼는데 여기에 넣으니 해결. 오늘은 여기까지 그럼 안녕~

안녕~ 이제 힘들어~

공유하기 댓글

lenovo-ideapad-510s ram upgrade

lenovo-ideapad-510s

이번년도 들어서 스터디를 위해 산 노트북.
가성비 끝판왕 이라는 타이틀이 있는 노트북으로 현재 자바스크립트 스터디를 위해서 사용하고 있는데 나쁘지 않다. 사실 전에 사용하던 노트북이 엄청 무겁고 느려서 이정도도 엄청 좋다고 생각하는 중이다. 완전 좋아.

내가 돌리는 프로그램은 포토샵, 일러스트, VS-code, Visual Studio 2017 정도. 회사에서는 데스크탑을 사용하기 때문에 밖에 나가서 필요하면 사용한다. 무게는 1.45kg정도이지만…..사실 1키로 넘어가면 다들 무겁게 느껴지잖아요?

램교체

처음 살때는 나중에 램 교체할 생각으로 4기가 짜리 램을 샀는데….아 이 노트북은 램을 교체하라고 만든 노트북이 아님…. 아직 안사신 분들은 애초에 좀 큰 용량의 램을 처음에 살때 추가옵션으로 선택하십쇼….나 이거 교체하다가 울뻔했네 진짜….

램은 저 깡통 안에
1.일단 이 노트북은 램을 교체하기 위한 뚜껑? 이 따로 존재하지 않습니다. 뒷면의 나사를 다 풀어야 하는데 풀고 나서 약간의 힘을 줘서 뚜껑을 열면 뭐 하나 부셔지는 소리와 함께 저 모습을 볼 수 있습니다.

깡통을 뜯자
2.램 위를 덮고있는 덮개는 몇개의 집게가 지탱하고 있습니다. 이 녀석들을 다 풀어줘야 합니다. 바깥으로 연다고 생각하시고 하나씩 풀어주시면 됩니다. 도구는…저는 마이너스 드라이버를 사용하려고 했지만 틈이 너무 좁아서 들어가지가 않아 칼을 사용했습니다. 일반 문구용 커터칼은 부러질 것 같아 맥가이버 칼에 들어있는 칼을 사용했습니다.

램
3.덮개를 제거했으면 램을 뽑아봅시다. 사진에 표시된 저 부분은 누르면 램이 푝하고 튀어 오릅니다. 그럼 램을 교체한 다음 다시 눌러서 넣어 줍니다.

4.그리고 덮개를 잡아주던 집게를 다시 오무린 다음 뚜껑을 덮고 마무리 해주시면 됩니다.

램을 교체할때에는 전원이 완전히 나갔는지 확인하시는거 잊지 마시고, 뚜껑 다시 열기 어려우니 뚜껑 닫기 전에 전원 켜서 정상적으로 작동하는지 확인하신 하시는 것이 좋을 것 같습니다.

참고가 되었던 유튜브도 공유해 드립니다.

0

공유하기 댓글

es6에서 추가된 함수 기능

es6에서 추가된 함수의 기능을 살펴보기 전에 함수의 기본을 알고 가도록 하겠다!

함수는 기본적으로 이렇게 쓰인다.

1
2
3
4
function hello(){
return "Hello world!";
}
hello(); //"Hello world!"

자바스크립트는 함수를 호출하지 않고 다른 값과 마찬가지로 참조하기만 할 수 있다는 특징을 가지고 있는 유연한 언어. 그렇기 때문에 함수를 변수에 할당하여 다른 이름으로 함수를 호출할 수도 있다.

1
2
const f = hello;
f(); //"Hello world!"

또한 함수를 객체 프로퍼티나 배열요소에도 할당 할 수 있다.


함수를 호출하면서 정보를 전달 할 떄, 즉 함수에 정보를 전달하려면 매개변수를 이용한다. 매개변수는 함수가 호출되기 전에는 존재하지 않는다는 점을 제외하면 일반적인 변수와 마찮가지.

1
2
3
4
function avg(a, b){
return (a+b)/2;
}
avg(5, 10); //7.5

자바스크립트에서는 다른 함수들 과는 다르게 매개변수 갯수와 상관없이 몇개의 매개변수를 전달해도 됨. 정해진 매개 변수에 값을 제공하지 않으면 암시적으로 undefined가 할당된다

1
2
3
4
function f(x){
return `f: x=${x}`;
}
f(); //"f: x=undefined"

ES6에 추가된 매개변수 기본값 지정하기

일반적으로 매개변수 값을 지정하지 않으면 위에처럼 undefined가 값으로 할당된다. ES6에서는 기본값을 지정 할 수 있게 되었다.

1
2
3
4
5
6
7
function f(a,b = "blabla",c=3){
return `${a} - ${b} - ${c}`;
}
f(5, 6, 7); //"5 - 6 - 7"
f(5, 6); //"5 - 6 - 3"
f(5); //"5 - blabla - 3"
f(); //"undefined - blabla - 3"

화살표 함수

ES6에서 새로만든 화살표 표기법은 function이라는 단어와 중괄호 숫자를 줄이려고 고안된 단축 문법입니다.

화살표 문법은 다음과 같은 특징을 가진다.

  1. function을 생략해도 됨
  2. 함수에 매개변수가 단 하나 뿐이라면 괄호(())도 생략할 수 있음
  3. 함수 바디가 표현식 하나라면 중괄호와 return문도 생략할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
const f1 = fuction() {return "hello";}
//또는
const f1 = () => "hello";
const f2 = function(name) {return `Hello, ${name}!`;}
//또는
const f2 = name => `Hello, ${name}!`;
const f3 = function(a, b) {return a+b};
//또는
const f3 = (a, b) => a+b;

화살표 함수는 항상 익명함수이다. 만약 이름 붙인 함수가 필요하다면 평소에 하던 방식으로 함수를 만들면 된다.

화살표 함수는 위의 특징 말고도

  1. this가 다른 변수와 마찬가지로 정적으로 묶인다.
  2. 객체사용자로 사용할 수 없다.
  3. arguments변수도 사용할 수 없다. 확산 연산자가 ES6에서 생겼으니 필요없다고 하기도 한다.

처음에 만들었던 함수를 화살표 함수로 바꾸어 보장

1
2
3
4
5
6
7
8
9
function avg(a, b){
return (a+b)/2;
}
avg(5, 10); //7.5
const avg = (a, b) => {
return (a+b)/2
};
avg(5, 10); //7.5

공유하기 댓글

해체할당

해체 할당

이 기능은 객체나 배열을 변수로 ‘해체’할 수 있다.
일단 다짜고짜 객체 해체부터 시작

1
2
3
4
5
6
7
8
9
//객체선언
const obj = {b:2, c:3, d:4};
//해체할당
const {a, b, c} = obj;
a; //undefined : obj에는 a프로퍼티가 없음
b; //2
c; //3
d; //ReferenceError : d는 정의되지 않음

객체를 해체 때에는 반드시 변수 이름과 프로퍼티 이름이 일치해야 한다
이 예제에서는 선언과 할당을 같은 문에서 실행. 객체해체는 할당만으로도 이루어질 수 있지만 그렇게 하려면 반드시 괄호를 써야함. 괄호를 쓰지 않으면자바스클립트는 표현식 좌변을 블록으로 해석함(???)

1
2
3
4
5
const obj = {b:2, c:3, d:4};
let a, b, c;
{a, b, c} = obj; //에러염
({a, b, c} = obj); //동작함...??

배열을 해체 할 때엔 배열 요소에 대응할 변수를 마음대로 쓸 수 있음. 이들은 배열 순서대로 대응한다.

1
2
3
4
5
6
const arr = [1,2,3];
let[x,y] = arr;
x; //1
y; //2
z; //ReferenceError

x, y요소에 값이 할당되고 그 뒤의 배열요소는 모두 버려지는데 확산 연산자를 사용하면 남은 요소를 새 배열에 할당할 수 있다.

1
2
3
4
5
6
const arr = [1, 2, 3, 4, 5];
let [x,y, ...rest] = arr;
x; //1
y; //2
rest; //[3,4,5]

배열 해체를 활용하면 변수의 값을 서로 바꿀 수도 있음. 해체를 사용하지 않으면 임시변수가 필수적인 작업이라고 함

1
2
3
4
let a = 5, b = 10;
[a, b] = [b, a];
a; //10
b; //5
공유하기 댓글

자바스크립트 숫자 비교할때 주의할 부분

NaN은 무엇과도 같지 않음

NaN값은 그 자신을 포함하여 무엇과도 같지 않다.

1
2
NaN === NaN //false
NaN == NaN //false

그럼 어떻게 숫자가 NaN인지 알아보느냐!
inNaN(x)함수를 사용하면 된다. isNaN 함수는 x가 NaN일때 true를 반환한다.

1
2
let NotNaN = "string";
isNaN(NotNan); //true

소수 비교하기

자바스크립트의 숫자는 모두 더블형식
더블형식은 실수를 말하는데 실수는 0.3000000000000000000000004처럼 작은 값을 포함하기도 한다. 그렇기 때문에 실수를 비교할 때에는 Number.EPSILON의 숫자형 상수를 이용하여 비교한다고 한다.

MDN에서는

Number.EPSILON 속성(property)은 Number 형으로 표현될 수 있는 1과 1보다 큰 값 중에서 가장 작은 값의, 차입니다.

라고 설명하고 있다. 두개의 더블(실수)형식이 같다고 할 수 있을 만큼 가까운 숫자인지 판단할때 일반적으로 사용하는 방법이라고 하니 걍 익혀두는게 좋을 듯

아래 예시로 좀 더 자시헤 보도록 할까…

1
2
3
4
5
6
let n = 0;
while(true){
n += 0.1;
if(n === 0.3) break;
}
console.log(`Stopped at ${n}`);

이렇게 하면 0.3에 멈출거라고 생각하지만 컴퓨터는 값을 내놓지 못하고 끝없이 돌아갔다. 창 멈춤…ㄷㄷㄷ

ㅎㄷㄷ

그래서 Number.EPSILON과 관계연산식을 써서 느슨하게 비교해야함.

1
2
3
4
5
6
let n = 0;
while(true){
n += 0.1;
if(Math.abs(n-0.3) < Number.EPSILON) break;
}
console.log(`Stopped at ${n}`); //Stopped at0.30000000000000004
공유하기 댓글

js pattern 01

제어문에서의 유용한 자바스크립트 패턴

continue 이용하여 조건 중첩 줄이기

반복문 안에 조건문을 쓸 경우, 즉 특정 조건에서만 반복문을 써야 하는데 그때 continue 문을 써서 구조를 간결하게 할 수 있음

1
2
3
4
5
6
7
8
while(funds > 1 && funds < 100){
let total = rand(1, funds);
if(total === 13) {
console.log("Unlucky! Skip this round....");
continue;
}
//플레이 구문
}

break, return 문으로 불필요한 연산 줄이기

뭔가를 찾기 위해서 루프를 실행했다면, 찾고 난 후에는 계속 실행할 필요가 없음

1
2
3
4
5
6
7
8
9
10
11
et arr = [1,2,3,4,5,6,7,8,9,10];
for(let n of arr){
if(n === 5){
break;
}
console.log(n);
}
//1
//2
//3
//4

루프를 완료한 뒤 인덱스 값 사용하기

break문을 써서 루프를 일찍 종료했는데 인덱스 변수의 값이 필요할 때

1
2
3
4
5
6
7
8
9
10
let i = 0;
const arr = [1,2,3,4,5,6,7,8,9];
for(; i<arr.length; i++){
if(arr[i] === 5) break;
}
if(i === arr.length) console.log('뭔지 모르겠다');
else console.log(`루프를 돌아서 마지막에 멈춘 수의 포지션은 ${i}입니다. `);
//루프를 돌아서 마지막에 멈춘 수의 포지션은 4입니다.

이건 break문을 써서 루프를 끝내도록 해야만 사용할 수 있다고 한다.


배열을 수정할 때 감소하는 인덱스 사용하기

1
2
3
for (let i = arr.length-1; i>=0; i--){
if(isPrime(arr[i])) arr.splice(i, 1);
}

그 이외에 for루프를 좀 더 효율적으로 쓰기위한 패턴

이건 예전에 잠깐 패턴 공부할 때 나온적이 있는데 다시 살펴보도록 하겠음

1
2
3
4
var myArr = [1,2,3,4,5]
for (var i=0; i< myArr.length; i++){
console.log(myArr[i]);
}
보통의 for루프

이 패턴의 문제점은 루프 순회시 마다 배열의 length 에 접근한다는 점이다.
myArr이 배열이 아니라 HTMLCollection 이라면 이 때문에 코드가 느려질 수 있다.
HTMLCollection 의 length 속성에 접근할 때마다 실제 DOM 에 질의를 요청하는 것과 같으며 일반적으로 DOM접근은 비용이 크다.
따라서 이러한 비용을 줄이기 위해 배열의 length를 캐시하면 된다.

1
2
3
for (var i=0, max = myArr.length; i<max; i++){
console.log(myArr[i]);
}

또한 i– 를 이용한 패턴이 있음

1
2
3
4
for(; var i = myArr.length; i--;){
console.log(myArr[i]);
}

공유하기 댓글

es6-02

for…in 루프

for...in루프는 객체의 프로퍼티에 루프를 실행하도록 설계된 루프

1
2
for(variable in object)
statement

이건 es6에 새로 추가된 문법은 아니지만 내가 몰랐었으니 추가

1
2
3
4
5
const player = { name : 'Thomas', rank : 'Midshipman', age:25}
for(let prop in player){
if(!player.hasOwnProperty(prop)) continue;
console.log(prop + ':' + player[prop]);
}

결과는

1
2
3
"name:Thomas"
"rank:Midshipman"
"age:25"

여기에서 player.hasOwnProperty를 호출할 필요는 없지만 이 메서드를 생략하면 에러가 생기기 쉽다고 한다. 나중에 다시 보는걸로…

for…of 루프

for…of 루프는 ES6에 새로생긴 반복문.
컬렉션 요소에 루프를 실행한다고 한다. 배열은 물론 이터러블(iterable)객체에 모두 사용이 가능하다.

1
2
for(variable of object)
statement
1
2
3
4
const hand = [randFace(), randFace(), randFace()];
for(let face of hand)
console.log(`you rolled...${face}!`);
//

for…of는 배열에 루프를 실행해야 하지만 각 요소의 인덱스를 알 필요는 없을때 알맞음. 인덱스를 알아야 하면 일반적인 for루프를 이용하는 것으로

1
2
3
const hand = [randFace(), randFace(), randFace()];
for (let i=0; i<hand.length; i++)
console.log(`ROLL ${i+1} : ${hand[i]}`);

책에서는 이렇게 나왔는데 이론적으로 나와서 잘 이해가 되지 않는다.
예제를 찾아보자.

1
2
3
4
5
6
7
8
let iterable = [10, 20, 30];
for (let value of iterable) {
console.log(value);
}
// 10
// 20
// 30
1
2
3
4
5
6
7
8
let iterable = "boo";
for (let value of iterable) {
console.log(value);
}
// "b"
// "o"
// "o"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);
for (let entry of iterable) {
console.log(entry);
}
// [a, 1]
// [b, 2]
// [c, 3]
for (let [key, value] of iterable) {
console.log(value);
}
// 1
// 2
// 3

등등 다양하게 쓸 수 있다고 한다. 더 많은 예제는 아래 링크에서 볼 수 있다.
MDN

공유하기 댓글