[Javascript for web developers] 5장 reference type 정리

참조타입

  • 참조 값(객체)는 특정 ‘참조 타입’의 인스턴스!
  • 참조타입: 데이터와 기능을 그룹으로 묶는 구조
  • 참조타입을 클래스라 부르지 마세요.

Object 타입

  • 가장 많이 쓰임
//1 (잘 안씀)new연산자로 생성하기
var person = new Object();
person.name = "Lezhin";
//2 (많이 씀)객체 리터럴 표기
var person2 = {
    name : "Lezhin",
    age: 13 
};
person2.age2 = 14;
alert(person2[age2]); //대괄호 표기법. 프로퍼티 이름에 변수랑 공백 등 쓸 수 있다. 

Array 타입

//1(잘 안씀)Array 생성자로 생성
var colors = new Array();
//2(많이씀)배열 리터럴 표기법
var colors = ["red", "blue", "green"];
alert(colors[0]);

//굳이 배열 날리고 싶을때
colors.length = 0;
//배열 마지막에 데이터 추가
colors[colors.length] = "black";

//객체와 배열을 구분하기- 1. instanceof연산자
if(value instanceof Array) {...}; //근데 실행컨텍스트가 여러개 있다면 의도치않은 결과
//객체와 배열을 구분하기- 2. isArray()메서드
if(Array.isArray(value)) {...}; //이걸로 써랑!

//변환메서드
var colors = ["red", "blue", "green"];
alert(colors.toString());   //red, blue, green
alert(colors.valueOf());   //red, blue, green 위 두개는 명시적으로 배열의 각 슬롯을 쉼표로 구분한 문자열을 반환

//다른 구분자를 써서 배열을 문자열로 나타내기(꽤 유용히 쓴다)
alert(colors.join("||"));   //red||green||blue

//스택
colors.push("black", "olive");  //5
colors.pop();   //"olive"
//큐
colors.push("kakao");   //5
colors.shift()  //"red"

//정렬메서드
var values = [1, 2, 3, 4, 5];
values.reverse();   //5,4,3,2,1
var values = [0, 1, 5, 10, 15];
values.sort();  //0,1,10,15,5 예상대로 안나온다!->비교함수를 넘겨야함
function compare(a, b){
    if(a<b){
        return -1;
    } else if(a>b){
        return 1;
    } else {
        return 0;
    }
}   //거꾸로 하면 역순정렬
values.sort(compare);
//단순히 숫자형값 반환하는 객체에선 더 단순히 비교함수 만들 수 있다
function compare(val1, val2) {
    return val2-val1;
}

//조작 메서드
var lc = ["lezhin", "com"];
var lc2 = lc.concat("inc", ["good", "bravo"]);  //lezhin,com,inc,good,bravo의 새 배열 반환
var lc3 = lc.slice(1);  //com
var lc4 = lc2.slice(1, 3);  //com, inc
//강력한 메서드 splice(인덱스부터, 몇개를삭제, 삽입할데이터)
var nums = [1,2,3,4];
var removed = nums.splice(0,1); //nums는 2,3,4 removed는 1
removed = nums.splice(1,0,"a","b"); //nums는 2,a,b,3,4 removed는 빈 배열

//위치 메서드
var nums = [1,2,3,4,5,4,3,2,1];
alert(nums.indexOf(4)); //3
alert(nums.lastIndexOf(4)); //5

//반복 메서드 - 많이 쓴다 
var everyResult = nums.every(function(item, index, array) {
    return (item>2);
}); //false

var someResult = nums.some(function(item, index, array) {
    return (item>2);
}); //true

var filterResult = nums.filter(function(item, index, array) {
    return (item>2);
}); // [3,4,5,4,3]

var mapResult = nums.map(function(item, index, array) {
    return item*2;
}); // [2,4,6,8,10,8,6,5,2]

nums.forEach(function(item, index, array) {
    console.log(item);
}); //해당 배열에서 for문을 실행한 것과 마찬가지 

//감소 메서드(많이 쓴다) - 배열을 순회하며 콜백함수를 실행하고 값을 하나 만들어 반환
var values = [1,2,3,4,5];
var sum = values.reduce(function(prev,cur,index,array) {
    return prev + cur;
}); //15
  • 배열 길이보다 큰 인덱스 지정 -> 배열 길이가 자동으로 늘어남, 빈슬롯엔 undefined

Date 타입

var now = new Date(Date.parse("May 25, 2004"));//넘긴 문자열이 올바르지 않으면 NaN반환
var now = new Date("May 25, 2004");//사실 이면에서 Date.parse호출하므로 위에거랑 같음.

//코드의 프로파일링 작업 측정 
var start = Date.now(); //현재 시간을 밀리초로 반환. +new Date()해서 숫자로 변환도 가능
doSomething();
var stop = Date.now(), result = stop-start;
/*브라우저에 따라 각 메서드가 반환하는 형식에 상당한 차이 있다*/

//날짜 표시 메서드
toDateString(); //요일,월,일,년
toTimeString(); // 시, 분, 초, 타임존
toLocaleDateString()l
...

RegExp 타입

regular expression항목 참조

Function 타입

  • 함수가 사실 객체.
  • 모든 함수는 Function 타입의 인스턴스. 프로퍼티와 메서드가 있다.
  • js엔진은 코드를 평가할 때 제일 먼저 함수 선언을 찾은 다음 이들을 맨 위에 올린다.(hoisting)
  • 함수 내부에는 arguments, this라는 특별한 객체가 있다.
    • arguments : 배열과 비슷한 객체. 함수에 전달된 매개변수를 모두 포함.
      • callee: arguments객체의 소유자인 함수를 가리키는 포인터
  • 모든 함수에 공통인 프로퍼티:
    • length: 함수가 넘겨받을 것으로 예상하는 이름 붙은 매개변수의 숫자
    • prototype: 모든 참조 타입의 인스턴스 메서드가 존재하는 곳.
      • toString()이나 valueOf()같은 메서드 존재.
      • 열거할 수 없는 프로퍼티라 for-in문에 나타나지 않음.
  • 함수 메서드
    • apply(): 객체/배열 넘김
    • call(): 매개변수 각각 나열
    • 둘다 함수 내부에서 this객체의 값을 바꾸는 역할
    • bind(): 새 함수 인스턴스를 만드는데 그 this는 bind() dp wjsekfehls rkqt
//함수 선언
function sum(n1, n2) {
    return n1 + n2;
}
//함수 표현식
var sum = function(n1, n2) {
    return n1 + n2;
};

//이러면 에러남! 선언식으로 하면 안에러남
alert(sum(10, 10));
var sum = ....;

//함수가 함수를 반환 <<이 패턴 매우 유용
function createComparisonFunction(propertyName) {
    return function(obj1, obj2){
        var val1 = obj1[propertyName];
        var val2 = obj2[propertyName];

        if(val1<val2){
            return -1;
        } else if(val1>val2){
            return 1;
        } else {
            return 0;
        }
    };
}
var data = [{name: "Zake", age:28}, {name: "Nick", age:28=9}];
data.sort(createComparisonFunction("name"));
alert(data[0].name);    //Nick
data.sort(createComparisonFunction("age"));
alert(data[0].name);    //Zake

//함수의 내부 구조
return num * arguments.callee(num-1); //처럼 하면 재귀 함수가 함수 이름에 의존하는 약점 극복가능. strict mode에서는 에러남.

//apply(), call()
function sum(n1, n2){
    return n1+n2;
}

function callSum1(n1, n2){
    return sum.apply(this, arguments);  //arguments객채 넘김
}
function callSum2(n1, n2){
    return sum.apply(this, [n1, n2]);  //배열 넘김
}
function callSum3(n1, n2){
    return sum.call(this, n1, n2);
}

//this바꾸기
window.color = "red";
var o = {color:"blue"};

function sayColor(){alert(this.color)};
sayColor(); //red
sayColor.call(this);    //red
sayColor.call(window);    //red
sayColor.call(o);    //blue

var objectSayColor = sayColor.bind(o);
objectSayColor(); //blue

원시 래퍼 타입

//글자 메서드
var stringValue = "hello world";
stringValue.charAt(1); //e
stringValue[1]; //e

var result = stringValue.concat("js", "!"); //근데 사실 +연산자로 하는게 더 빠름.
alert(result);  //hello worldjs!

var stringValue2 = "      hello world       ";
stringValue2.trim(); //hello world

stringValue.toUpperCase();
stringValue.toLowerCase();

var pattern = /.llo/;
var matches = stringValue.match(pattern);   //배열 반환. pattern.exce(text)와 같다. 
matches[0]; //"hello"
var pos = stringValue.search(pattern);
alert(pos); //0

//문자열 일부 바꾸기
text.replace("at", "ond"); //첫번째 at을 찾아 ond로 바꿈. 정규표현 /at/g 쓰면 모두 바꿈.

//HTML에서 사용할 수 있도록 특수문자를 이스케이프
alert(hemlEscape("<p class="greeting">Hello world!</p>"));

//텍스트를 구분자를 기준으로 분리해서 배열에 담아 변환
var colorText = "red,blue,green";
var colors1 = colorText.split(","); //["red", "blue", "green"]
var colors2 = colorText.split(",", 1); //["red"]

내장된 싱글톤 객체

//Math 객체
Math.E;
Math.PI;
Math.sqrt(num);

Math.max(3,54,32);  //54
var values = [1,2,3,4,5];
var max = Math.max.apply(Math, values);

Math.ceil(25.6);    //26 올림
Math.floor(25.6);   //25 내림
Math.round(25.6);   //26 반올림

Math.random();  //0과 1사이 난수 반환. 0이나 1은 제외
number = Math.floor(Math.random() * total_number_of_choices + first_possible_value);    //원하는 범위의 정수 얻기
number = Math.floor(Math.random() * 9 + 2);    //2와 10 사이의 난수. 경우의 수는 9고 작은값은 2
var colors = ["red", "green", "blue", "yellow"];
var color = colors[selectFrom(0, colors.length-1)]; //가장 큰값과 작은값 난수얻기
Advertisements

jQuery .attr() vs .prop()

왜 .attr()을 .prop()으로 나누었나?

  • 원래 따로 사용해야할 문제였는데 버그 많아져버림
  • attr : HTML의 속성을 취급
  • prop : Javascript프로퍼티 취급

example 1

<a id="to_comments" href="#comments">코멘트 일람</a>
...
var $link = $('#to_comments');
$link.attr('href'); //#to_comment
$link.prop('href'); //#http://example.com/path/to/page#to_comment
  • 속성: HTML으로서 기록되어있는 속성의 내용
  • 프로퍼티: Javascript가 취급하는 정보.

example 2

<checkbox id="private" type="checkbox" checked />
...
var $checkbox = $('#private');
alert($checkbox.attr('checked')); //"checked"
alert($checkbox.prop('checked')); //true
//체크박스 해제하면?
alert($checkbox.attr('checked')); //"checked"
alert($checkbox.prop('checked')); //false

Reference

http://javascriptandjquerydev.blogspot.kr/2012/07/attr-prop.html

OKKY Javascript Fullstack Conference 강연노트

11079373_737723709673898_904060683853328553_n

김태곤

  • 서버와 클라이언트에서 동시에 사용하는 ReactJS
  • 김태곤
    • Fancy, Naver, 책번역, 한국어번역
    • taegon.kim, @taggon
  • ReactJS?
    • FB에서 개발
    • 정식 명칭은 React
    • 사용자 인터페이스를 만드는 자바스크립트 라이브러리
  • MVC
    • 여기서 컴포넌트를 통해 오직 View표현만 담당
    • 컴포넌트:
      • 재사용 가능한 UI구성단위
      • html5오면서 표준 됨
      • 컴포넌트는 어떤 기준으로 나눠야 하나? ->본인이 알아서 판단
  • JSX
    • Javascript XML
    • JS코드에 xml을 직접 표현 -> (JSXTransformer를 통해->JS코드로 컴파일
  • DOM
    • 일관성이 없다 – 브라우저마다 구현에 차이가 있다-렌더링 버그
    • 테스트하기 쉽지 않다 – JS만으로는 테스트가 어려워 반드시 브라우저가 필요
  • Virtual DOM
    • 일관성이 있다-브라우저에 의존적이지 않다
    • 테스트하기 쉽다 -순수 JS만으로 구현
    • 빠르다-메모리상에 DOM구성, DOM비교를 통해 업데이트된 부분만 갱신
      • 빠른걸로 성능향상시켜보까!!
      • Ember나 Angular보다 빠르다
    • 단방향 데이터 흐름
    • 이해하기 쉽다
  • 동형 자바스크립트(Isomorphic Javascript)(중요!)
    • 동형 = 같은 모양
    • 클라이언트와 서버가 같은 코드를 공유한다.
    • php-node.js렌더링 서버 구조
  • 이점
    • 반복 작업 제거
    • 서버사이드에서 렌더링 해야할때 반복 제거
    • 사용자 경험 향상
    • 검색 엔진 최적화(데이터가 포함되서 나오니까!)
  • React는 그 이상이댜!!!
    • React Native
      • React를 사용해 네이티브 모바일 앱 작성: eg)Facebook Groups
      • 모바일OS의 네이티브 UI를 JS로 조작
      • 별도 쓰레드에서 동작하는 JS와 비동기 통신
      • 컴포넌트 종류는 다르지만 쓰던 React 방식 그대로
      • 오 쩐다 디버깅을 크롬으로 해
    • React Canvas
      • 모든 돔 엘리먼트를 캔버스에 그려!
    • 리액트의 철학: Learn Once, Write Anywhere!
    • awsome ㅇㅇ라 치면 그 ㅇㅇ의 쩌는것들이 나온다!!(ex. awesome react)

고재도

  • PolymerJS
  • Web Compenet
    • 더 작은 코드, 덜 혼란스럽게!
    • Custom Elements(컴포넌트가 인터페이스를 가진 DOM Element 형태로 사용될 수 있도록)
    • Templates(z컴포넌트의 골격이 사용전까지 비활성화된 상태로 관리되도록)
    • Shadow Dom
    • HTML Imports
    • webcomponents.org 참고
  • 폴리머와 웹 컴포넌트 사용하기
    • 폴리머?
      • 라이브러리
      • 웹 컴포넌트 기반 어플리케이션을 쉽고, 빠르게 만들게 해준다.(jQuery가 javascript 쉽게 만들어준것처럼)
      • polymer.js : 더 편리하게 웹컴포넌트개발을 할 수 있게 해준다.
      • 정의한 엘리먼트들을 “이런식으로 쓸 수 있다.
      • template이란 태그 생김! =>나중에 렌더링
      • 앵귤러랑 비슷하넹… ng-repeat == repeat
  • Shadow DOM
    • light DOM 밑에 숨겨져있다
    • 브라우저에선 보이는데 소스상엔 안보
    • lightDOM : DOM조작 쉽게 가능
    • shadowDOM: 개발자만 알고있다아 접근하기 어려움(capsulation 된다!)(바깥이랑 차단되어있는 상황!)(의도적으로 찾아갈수는 있지만 실수로 부실수는 없다)
    • 폴리머는 기본적으로 shadow dom 적용!
  • core-elemens
    • 오오 시연해주시는데 싱기방기!

문추근(fallroot)

  • DRY – Don’t Repeat Yourself 이 철학을 가지고 임하
  • Grunt, Gulp
    • 프론트엔드 개발도구 using 노드 (자동화에 도움)
  • 앱엔진 + 자바
    • 실제 서비스 환경에서 작업하는 방법이 이상적
    • 수정-> 빌드-> 배포 과정이 번거로움
    • 실제 서비스 데이터를 사용할 수 없음
    • 데이터 CRUD가 불편
  • index.html
    • 간단
    • 단일 페이지에 작업
    • 문제: CORS <-Cross origin resource sharing
      • 원격 자원 접근 제한
      • 해결: JSONP <
      • 코드 분리/재활용 어려움
      • 복붙복붙
      • 수정시 같은작업 반복
      • 데이터베이스 사용 불가능
  • 정적 사이트 생성기
    • staticsitegenerator.net
    • 레이아웃 지원 -> HTML 분리/재활용
    • 마크다운 등 블로그 포스팅에 특화
  • 그래서 루비온레일즈 써봐라
    • 설치가 간단
    • 루비는 스크립트언어 -> 빌드/배포과정 필요없음
    • 기본 기능만으로도 유용
    • 추가 잼 설치로 기능 확장
  • 프리프로세서: 원래 언어의 부족한 문법 보완
  • Sprockets
    • Rack based asset packaging
    • 스타일시트/자바스크립트 파일관리
    • 다 주석으로 생김
  • 스캐폴드
    • 건축에 사용하는 임시 구조물
    • 작업시 편의 제공
  • 초기 데이터 구축
    • 시드: 루비 코드로 초기데이터 작성
  • Pow
    • 랙 기반 서버 관리
    • 웹 서버 포트 충돌 방지
    • Anvil: pow에 UI입힘
  • xip.io
  • 유용한 젬
    • RailsCsvFixtures
    • YamlDB
  • 실제 개발 절차

정병태

  • ebrain Lab
  • Service Worker를 이용한 Offline Web Application 구현
  • Service Worker
    • offline상태에서, 웹 어플리케이션의 준비 단계를 가로채는 방법을 제공하고, 지속적인 background 처리를 지원
  • 할수 있는(있을) 것들
    • Offline Cache
    • Task scheduler
    • Background Sync
    • Push notification
    • Geofencing
  • 근데 IE에서 안돼요 ^^ㅎㅎ…
    • 크롬이랑 오페라만 됨 아직까진

[ 일일코딩 ] 삼행시 짓기 (Javascript)

원본

http://www.codewars.com/kata/54530f75699b53e558002076/train/javascript

Question

In this kata, we’re going to create the function nato that takes a word and returns a string spells the word using the NATO phonetic alphabet.

There should be a space between each word in the returned string, and the first letter of each word should be capitalized.

For those of you that don’t want your fingers to bleed, this kata already has a dictionary typed out for you.

nato('hi') // --&gt; 'Hotel India'
nato('abc') // --&gt; 'Alpha Bravo Charlie'

My Answer

var nato = (function() {
  var letters =  {
    &quot;A&quot;: &quot;Alpha&quot;,  &quot;B&quot;: &quot;Bravo&quot;,   &quot;C&quot;: &quot;Charlie&quot;,
    &quot;D&quot;: &quot;Delta&quot;,  &quot;E&quot;: &quot;Echo&quot;,    &quot;F&quot;: &quot;Foxtrot&quot;,
    &quot;G&quot;: &quot;Golf&quot;,   &quot;H&quot;: &quot;Hotel&quot;,   &quot;I&quot;: &quot;India&quot;,
    &quot;J&quot;: &quot;Juliett&quot;,&quot;K&quot;: &quot;Kilo&quot;,    &quot;L&quot;: &quot;Lima&quot;,
    &quot;M&quot;: &quot;Mike&quot;,   &quot;N&quot;: &quot;November&quot;,&quot;O&quot;: &quot;Oscar&quot;,
    &quot;P&quot;: &quot;Papa&quot;,   &quot;Q&quot;: &quot;Quebec&quot;,  &quot;R&quot;: &quot;Romeo&quot;,
    &quot;S&quot;: &quot;Sierra&quot;, &quot;T&quot;: &quot;Tango&quot;,   &quot;U&quot;: &quot;Uniform&quot;,
    &quot;V&quot;: &quot;Victor&quot;, &quot;W&quot;: &quot;Whiskey&quot;, &quot;X&quot;: &quot;X-ray&quot;,
    &quot;Y&quot;: &quot;Yankee&quot;, &quot;Z&quot;: &quot;Zulu&quot;
  }

  return function(word) {
    var natoed = [];
    for(var i=0; i&lt;word.length; i++){
      var letter = word.toUpperCase()[i];
      natoed.push(letters[letter]);
    }
    return natoed.join(&quot; &quot;);
  }
})()

Clever Answer by @ColbyDauph

var nato = (function() {
  var letters =  {
    &quot;A&quot;: &quot;Alpha&quot;,  &quot;B&quot;: &quot;Bravo&quot;,   &quot;C&quot;: &quot;Charlie&quot;,
    &quot;D&quot;: &quot;Delta&quot;,  &quot;E&quot;: &quot;Echo&quot;,    &quot;F&quot;: &quot;Foxtrot&quot;,
    &quot;G&quot;: &quot;Golf&quot;,   &quot;H&quot;: &quot;Hotel&quot;,   &quot;I&quot;: &quot;India&quot;,
    &quot;J&quot;: &quot;Juliett&quot;,&quot;K&quot;: &quot;Kilo&quot;,    &quot;L&quot;: &quot;Lima&quot;,
    &quot;M&quot;: &quot;Mike&quot;,   &quot;N&quot;: &quot;November&quot;,&quot;O&quot;: &quot;Oscar&quot;,
    &quot;P&quot;: &quot;Papa&quot;,   &quot;Q&quot;: &quot;Quebec&quot;,  &quot;R&quot;: &quot;Romeo&quot;,
    &quot;S&quot;: &quot;Sierra&quot;, &quot;T&quot;: &quot;Tango&quot;,   &quot;U&quot;: &quot;Uniform&quot;,
    &quot;V&quot;: &quot;Victor&quot;, &quot;W&quot;: &quot;Whiskey&quot;, &quot;X&quot;: &quot;X-ray&quot;,
    &quot;Y&quot;: &quot;Yankee&quot;, &quot;Z&quot;: &quot;Zulu&quot;
  }

  return function(word) {
    return word.split('').map(function(v) {
      return letters[v.toUpperCase()]
    }).join(' ');
  }
})()

Javascript Regular Expression

정규표현식 생성- 1. 컴파일

//정규표현식 리터럴
var pattern = /a/;
//정규표현식 객체 생성자
var pattern2 = new regExp('a');

정규표현식 생성-2. 메서드 실행(execution)

console.log(pattern.exec('abcdef')); // ["a"]
console.log(pattern.exec('bc')); // null
console.log(pattern.test('abcdef')); // true

정규표현식 생성-3. 문자열 메서드 실행

console.log('abcdef'.match(pattern)); // ["a"]
console.log( 'abcdef'.replace(pattern, 'A')); // Abcdef

옵션

  • i: 대소문자 구별 안함(ex. var xi=/a/i;)
  • g: 끝까지 검색해서 모든 결과 리턴

Tip

  • s: 공백
  • 인덱스반환: text.search(re);

예제

var targetText = "http: vs https: or httpss:";
var natcges = targetText.match(/https?:/g);

console.log(matches);
>Array["http:", "https:"];

targetText = targetText.replace(/https?:/g, "protocol");
console.log(targetText);
>"protocol vs protocol or httpss:"

Reference

아기_토끼

안녕하세요, 수련중인 개발자입니다.
피드백이나 오류 정정을 해주시면 감사히 받겠습니다!

Javascript Prototype

Prototype기반 프로그래밍?

  • 객체의 원형인 프로토타입을 이용하여 새로운 객체를 만들어내는 프로그래밍 기법.
  • 이렇게 만들어진 객체 역시 자기 자신의 프로토타입을 갖는다.
  • 이런 구조로 객체를 확장하는 방식이 Prototype기반 프로그래밍
  • JS에선 class가 존재하지 않으므로 객체의 원형인 prototype을 이용한 클로닝과 객체특성을 확장해나가는 방식을 통해 새로운 객체를 생성.
  • JS 프로토타입 객체의 확장은 옵져버패턴 따른다.

자바스크립트의 Prototype

var foo = {name: "lezhin"};
foo.prototype.a = "comics";
console.log(foo.a); //syntax error
  • 왜 syntax error일까?
  • JS에서 사용되는 프로토타입이란 용어는 크게 두가지로 나뉜다.
    • Prototype Object
      • Prototype Property가 가리키고 있는 것
    • Prototype Link
      • 자기 자신을 만들어낸 객체의 원형
  • JS의 모든 객체는 자신을 생성한 객체 원형에 대한 숨겨진 연결을 갖는다.
  • 이때 자기 자신을 생성하기 위해 사용된 객체원형을 프로토타입이라 한다.
    • JS의 모든 객체는 Object객체의 프로토타입을 기반으로 확장되었기 때문에 이 연결의 끝은 Object객체의 프로토타입 Object이다.
  • 즉 어떤 객체가 만들어지기 위해 그 객체의 모태가 되는 녀석을 프로토타입이라 한다.

reference

https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain
http://insanehong.kr/post/javascript-prototype/
http://run2you.tistory.com/12

아기_토끼

안녕하세요, 수련중인 개발자입니다.
피드백이나 오류 정정을 해주시면 감사히 받겠습니다!

[ 일일코딩 ] 메인 프로모션 배너 위치 지정 2

Question

  • 외부 라이브러리 사용 금지
  • 0~2 중 무작위로 하나를 선택해 is-double 클래스를 추가하고 wide 이미지를 사용
  • 3~5, 6~8, 9~11 중 하나씩을 선택하고 square 이미지를 사용
  • 12~14, 15~17 중 하나씩을 선택해 is-half 클래스를 추가하고 wide 이미지를 사용
  • 어제 arrange 함수 결과를 data-pos 속성 값으로 사용
  • 이미지 경로는 http://cdn.lezhin.com/comics/:comicId/wide 또는 square 중에 선택해서 사용
  • 사용할 데이터는 아래와 같음
var comicIds = ['bad_boss', 'sm_tiger', 'she_is_young', 'her_dog', 'ccromance', 'milkpudding', 'woori', 'nanakarou', 'nicetomeetyou', 'leopard', 'moonlight_night', 'revatoon', 'encounter', 'gbpark', 'sinhontto', 'roomshare', '34mujik', 'desertisland'];

최종 결과물 예제

<!DOCTYPE html>
<html>
    <head>
        <title>프로모션 배너 배치 - 일일코딩</title>
        <style>
            body {
                background: #fff;
            }
            #promotion-list {
                background: #ccc;
                height: 200px;
                margin: 100px auto;
                position: relative;
                width: 400px;
            }
            img {
                display: block;
                height: 100px;
                left: 0;
                position: absolute;
                top: 0;
                width: 100px;
            }
            .is-double {
                height: 100px;
                width: 200px;
            }
            .is-half {
                height: 50px;
                width: 100px;
            }
            [data-pos="5"], [data-pos="6"], [data-pos="7"] {
                top: 100px;
            }
            [data-pos="2"], [data-pos="6"] {
                left: 100px;
            }
            [data-pos="3"], [data-pos="7"] {
                left: 200px;
            }
            .is-half:last-child {
                top: 50px;
            }
            .is-half[data-pos="5"]:last-child, .is-half[data-pos="6"]:last-child, .is-half[data-pos="7"]:last-child {
                top: 150px;
            }
        </style>
    </head>
    <body>
        <div id="promotion-list">
            <img class="is-double" src="http://cdn.lezhin.com/comics/bad_boss/images/wide" data-pos="1">
            <img src="http://cdn.lezhin.com/comics/sm_tiger/images/square" data-pos="3">
            <img src="http://cdn.lezhin.com/comics/she_is_young/images/square" data-pos="5">
            <img src="http://cdn.lezhin.com/comics/her_dog/images/square" data-pos="6">
            <img class="is-half" src="http://cdn.lezhin.com/comics/ccromance/images/wide" data-pos="7">
            <img class="is-half" src="http://cdn.lezhin.com/comics/milkpudding/images/wide" data-pos="7">
        </div>
    </body>
</html>

Answer

jayjin

<!DOCTYPE html>
<html>
    <head>
        <title>프로모션 배너 배치 - 일일코딩</title>
        <style>
            body {
                background: #fff;
            }
            #promotion-list {
                background: #ccc;
                height: 200px;
                margin: 100px auto;
                position: relative;
                width: 400px;
            }
            img {
                display: block;
                height: 100px;
                left: 0;
                position: absolute;
                top: 0;
                width: 100px;
            }
            .is-double {
                height: 100px;
                width: 200px;
            }
            .is-half {
                height: 50px;
                width: 100px;
            }
            [data-pos="5"], [data-pos="6"], [data-pos="7"] {
                top: 100px;
            }
            [data-pos="2"], [data-pos="6"] {
                left: 100px;
            }
            [data-pos="3"], [data-pos="7"] {
                left: 200px;
            }
            .is-half:last-child {
                top: 50px;
            }
            .is-half[data-pos="5"]:last-child, .is-half[data-pos="6"]:last-child, .is-half[data-pos="7"]:last-child {
                top: 150px;
            }
        </style>
    </head>
    <body>
        <div id="promotion-list">
        </div>
    </body>
    <script>
        var comicIds = ['bad_boss', 'sm_tiger', 'she_is_young', 'her_dog', 'ccromance', 'milkpudding', 'woori', 'nanakarou', 'nicetomeetyou', 'leopard', 'moonlight_night', 'revatoon', 'encounter', 'gbpark', 'sinhontto', 'roomshare', '34mujik', 'desertisland'];

        function random(min, max) {
            if (max === undefined) { max = min; min = 0; }
            return Math.floor(Math.random() * (max - min+1)) + min;
        }

        function arrange() {
            var positions = [1, 2, 3, 5, 6, 7];

            var double = [1, 2, 5, 6][random(3)];
            var doubleIndex = positions.indexOf(double);

            positions.splice(doubleIndex, 2);

            var half = positions[random(0, 3)];
            var halfIndex = positions.indexOf(half);
            positions.splice(halfIndex, 1);

            positions.unshift(double);
            positions.push(half);
            return positions;
        }

        function makeTag(comicId, pos, className, size) {
          var img = document.createElement('img');
          img.setAttribute("class", className);
          img.dataset.pos=pos;
          img.src = 'http://cdn.lezhin.com/comics/'+comicId+'/images/'+size;
          document.getElementById('promotion-list').appendChild(img);
      }

      window.onload = function() {
          var posArr = arrange();
          makeTag(comicIds[random(0, 2)], posArr[0], "is-double", "wide");
          makeTag(comicIds[random(3, 5)], posArr[1], "", "square");
          makeTag(comicIds[random(6, 8)], posArr[2], "", "square");
          makeTag(comicIds[random(9, 11)], posArr[3], "", "square");
          makeTag(comicIds[random(12, 14)], posArr[4], "is-half", "wide");
          makeTag(comicIds[random(15, 17)], posArr[4], "is-half", "wide");
      };
  </script>
</html>

feedback: “예상보다 훨 잘했네! 그리고 window.onload는 옛날스펙이니 다른거 써라”

tobyyun

<br /><br /><br /><br />        프로모션 배너 배치 - 일일코딩

            body {
                background: #fff;
            }
            #promotion-list {
                background: #ccc;
                height: 200px;
                margin: 100px auto;
                position: relative;
                width: 400px;
            }
            img {
                display: block;
                height: 100px;
                left: 0;
                position: absolute;
                top: 0;
                width: 100px;
            }
            .is-double {
                height: 100px;
                width: 200px;
            }
            .is-half {
                height: 50px;
                width: 100px;
            }
            [data-pos="5"], [data-pos="6"], [data-pos="7"] {
                top: 100px;
            }
            [data-pos="2"], [data-pos="6"] {
                left: 100px;
            }
            [data-pos="3"], [data-pos="7"] {
                left: 200px;
            }
            .is-half:last-child {
                top: 50px;
            }
            .is-half[data-pos="5"]:last-child, .is-half[data-pos="6"]:last-child, .is-half[data-pos="7"]:last-child {
                top: 150px;
            }




<div id="promotion-list"></div>


    <img class="is-double" src="http://cdn.lezhin.com/comics/{{double}}/images/wide">
    <img src="http://cdn.lezhin.com/comics/{{square1}}/images/square">
    <img src="http://cdn.lezhin.com/comics/{{square2}}/images/square">
    <img src="http://cdn.lezhin.com/comics/{{square3}}/images/square">
    <img class="is-half" src="http://cdn.lezhin.com/comics/{{half1}}/images/wide">
    <img class="is-half" src="http://cdn.lezhin.com/comics/{{half2}}/images/wide">



function arrange() {
    var positions = [1,2,3,5,6,7];
    var double, half;
    double = random(1,5); // double은 1,2,5,6 4가지 케이스 중 하나임
    if(double > 2) {
        double += 2; // 3,4 인경우 5,6 으로 만들어줌
    }
    positions.splice(positions.indexOf(double),2); // double 이라서 2개 뺌

    half = positions[random(0,4)]; // half 는 남는 4개 셀 중 하나
    positions.splice(positions.indexOf(half),1);

    console.log('double:', double);
    console.log('single:', positions.join(','));
    console.log('half:', half);

    setPromotion(double, half, positions);
}
function random(min, max) {
    if (max === undefined) { max = min; min = 0; }
    return Math.floor(Math.random() * (max - min)) + min;
}
function setPromotion(double, half, positions) {
/*
- 0~2 중 무작위로 하나를 선택해 is-double 클래스를 추가하고 wide 이미지를 사용
- 3~5, 6~8, 9~11 중 하나씩을 선택하고 square 이미지를 사용
- 12~14, 15~17 중 하나씩을 선택해 is-half 클래스를 추가하고 wide 이미지를 사용
- 어제 arrange 함수 결과를 data-pos 속성 값으로 사용
*/
    var comicIds = ['bad_boss', 'sm_tiger', 'she_is_young', 'her_dog', 'ccromance', 'milkpudding', 'woori', 'nanakarou', 'nicetomeetyou', 'leopard', 'moonlight_night', 'revatoon', 'encounter', 'gbpark', 'sinhontto', 'roomshare', '34mujik', 'desertisland'];
    var promotionList = document.getElementById('promotion-list');
    var promotionHtml = document.getElementById('promotion-template').innerHTML;

    promotionHtml = promotionHtml
        .replace("{{double}}", comicIds[random(3)])
        .replace("{{square1}}", comicIds[random(3,6)])
        .replace("{{square2}}", comicIds[random(6,9)])
        .replace("{{square3}}", comicIds[random(9,12)])
        .replace("{{half1}}", comicIds[random(12,15)])
        .replace("{{half2}}", comicIds[random(15,18)])
        .replace("{{D}}", double)
        .replace("{{S1}}", positions[0])
        .replace("{{S2}}", positions[1])
        .replace("{{S3}}", positions[2])
        .replace(/{{H}}/gi, half);

    promotionList.innerHTML = promotionHtml;
}
arrange();