2016-07-26 6 views
0

약간 아름다운 JS를 만들기 위해 Revealing Module 패턴을 생성자 패턴과 함께 사용하려고합니다! 나는이 같은 "카운트 다운"만약 여러 인스턴스를 만들 수 있도록하려면 :this가 모듈 패턴으로 정의되지 않았습니다.

var c1 = new Countdown(); 
c1.init(); 
var c2 = new Countdown(); 
c2.init(); 

이 독립적이어야한다. 따라서 변수를 "var"로 선언하는 대신 프로토 타입에 "this"를 사용합니다. 함수 내에서 "this"를 참조하지만 정의되지는 않았습니다. "this"에 어떻게 액세스 할 수 있습니까? 당신이 당신 때문에 setInterval

function init() { 
    // day 
    this.d1 = doc.createElement('div'); 
    this.d1.setAttribute('class', 'day-1 elem'); 

    var update = updateView.bind(this); // you need to bind updateView context 
    setInterval(function() { 
     var time = ??? 
     update(time); // `this` will be current instance 
    }, 1000) 
} 

UPDupdateView를 호출하는 것

"use strict"; 

var Countdown = function() { 
    //this.self = this; 
}; 

Countdown.prototype = (function(doc) { 

    return { 
     initialize: initialize 
    }; 

    function createElements() { 
     var countdown = doc.createElement('div'); 
     countdown.setAttribute('class', 'countdown'); 

     var heading = doc.createElement('h2'); 
     heading.textContent = 'Countdown'; 
     countdown.appendChild(heading); 
     document.body.appendChild(countdown); 



     // day 
     var wrapDay = doc.createElement('div'); 
     wrapDay.setAttribute('class', 'wrap-day'); 
     countdown.appendChild(wrapDay); 

     this.d1 = doc.createElement('div'); 
     this.d1.setAttribute('class', 'day-1 elem'); 
     wrapDay.appendChild(this.d1); 

     this.d2 = doc.createElement('div'); 
     this.d2.setAttribute('class', 'day-2 elem'); 
     wrapDay.appendChild(this.d2); 

     var lblDay = doc.createTextNode('dage'); 
     wrapDay.appendChild(lblDay); 

     var sepDay = doc.createElement('div'); 
     sepDay.setAttribute('class', 'separator'); 
     sepDay.textContent = ':'; 
     countdown.appendChild(sepDay); 



     // hour 
     var wrapHour = doc.createElement('div'); 
     wrapHour.setAttribute('class', 'wrap-hour'); 
     countdown.appendChild(wrapHour); 

     this.h1 = doc.createElement('div'); 
     this.h1.setAttribute('class', 'hour-1 elem'); 
     wrapHour.appendChild(this.h1); 

     this.h2 = doc.createElement('div'); 
     this.h2.setAttribute('class', 'hour-2 elem'); 
     wrapHour.appendChild(this.h2); 

     var lblHour = doc.createTextNode('timer'); 
     wrapHour.appendChild(lblHour); 

     var sepHour = doc.createElement('div'); 
     sepHour.setAttribute('class', 'separator'); 
     sepHour.textContent = ':'; 
     countdown.appendChild(sepHour); 



     // min 
     var wrapMin = doc.createElement('div'); 
     wrapMin.setAttribute('class', 'wrap-min'); 
     countdown.appendChild(wrapMin); 

     this.m1 = doc.createElement('div'); 
     this.m1.setAttribute('class', 'min-1 elem'); 
     wrapMin.appendChild(this.m1); 

     this.m2 = doc.createElement('div'); 
     this.m2.setAttribute('class', 'min-2 elem'); 
     wrapMin.appendChild(this.m2); 

     var lblMin = doc.createTextNode('minutter'); 
     wrapMin.appendChild(lblMin); 

     var sepMin = doc.createElement('div'); 
     sepMin.setAttribute('class', 'separator'); 
     sepMin.textContent = ':'; 
     countdown.appendChild(sepMin); 



     // sec 
     var wrapSec = doc.createElement('div'); 
     wrapSec.setAttribute('class', 'wrap-sec'); 
     countdown.appendChild(wrapSec); 

     this.s1 = doc.createElement('div'); 
     this.s1.setAttribute('class', 'sec-1 elem'); 
     wrapSec.appendChild(this.s1); 

     this.s2 = doc.createElement('div'); 
     this.s2.setAttribute('class', 'sec-2 elem'); 
     wrapSec.appendChild(this.s2); 

     var lblSec = doc.createTextNode('sekunder'); 
     wrapSec.appendChild(lblSec); 
    } 

    function initialize() { 
     domReady(function() { 

      // create DOM 
      createElements(); 

      // get time 
      var now = new Date(); 
      var year = now.getFullYear(); 
      var month = now.getMonth(); 
      var dateFinal = new Date(year, month + 1, 1, 0, 0, 0); // first day next month 
      var seconds = getSecsLeft(dateFinal); 
      var time = getTimeLeftObject(seconds); 

      // update view every second 
      setInterval(function() { 
       seconds = getSecsLeft(dateFinal); 
       time = getTimeLeftObject(seconds); 
       updateView(time); 
      }, 1000); 

      // first time 
      updateView(time); 
     }); 
    } 

    function updateView(time) { 
     var days = zeroPadding(time.days); 
     var hours = zeroPadding(time.hours); 
     var mins = zeroPadding(time.mins); 
     var secs = zeroPadding(time.secs); 

     this.d1.textContent = days[0]; 
     this.d2.textContent = days[1]; 

     this.h1.textContent = hours[0]; 
     this.h2.textContent = hours[1]; 

     this.m1.textContent = mins[0]; 
     this.m2.textContent = mins[1]; 

     this.s1.textContent = secs[0]; 
     this.s2.textContent = secs[1]; 
    } 

    function getDays(secs) { 
     var result = 0; 
     if (secs > 0) { 
      result = secs/(60 * 60 * 24); 
     } 

     return Math.floor(result); 
    } 
    function getHours(secs) { 
     var result = 0; 
     if (secs > 0) { 
      result = (secs/(60*60)) % 24; 
      result = result === 24 ? 0 : result; 
     } 

     return Math.floor(result); 
    } 
    function getMins(secs) { 
     var result = 0; 
     if (secs > 0) { 
      result = (secs/60) % 60; 
      result = result === 60 ? 0 : result; 
     } 

     return Math.floor(result); 
    } 
    function getSecs(secs) { 
     var result = 0; 
     if (secs > 0) { 
      result = secs % 60; 
      result = result === 60 ? 0 : result; 
     } 

     return Math.floor(result); 
    } 

    function zeroPadding(num) { 
     var result; 
     result = num < 10 ? "0" + num : num; 

     return new String(result); 
    } 

    function getTimeLeftObject(seconds) { 
     var secs = getSecs(seconds); 
     var mins = getMins(seconds); 
     var hours = getHours(seconds); 
     var days = getDays(seconds); 

     return { 
      days: days, 
      hours: hours, 
      mins: mins, 
      secs: secs 
     }; 
    } 

    function getSecsLeft(dateFinal) { 
     var result = (dateFinal - new Date())/1000; 
     return result < 0 ? 0 : result; 
    } 

    function domReady(callback) { 
     document.readyState === "interactive" || document.readyState === "complete" ? callback() : document.addEventListener("DOMContentLoaded", callback); 
    } 

})(document); 
+0

당신이'init' 함수 내에서'updateView'를 호출 할 의미합니까? 'updateView.call (this, 100)'을 사용하는 경우 –

+0

간격 타이머 (코드 생략)로 매초마다 텍스트를 업데이트합니다. – olefrank

+0

Countdown 생성자에서 this.init() 만 호출하면됩니다. 나는 당신이 성취하고자하는 것에 대해 확신하지 못한다. 왜냐하면 나에게 이것은 정의되어야하고, 나는 그것을 테스트하고 작동한다. ... –

답변

4

:

var Countdown = function() {}; 

Countdown.prototype = (function(doc) { 

    return { 
     init: init 
    }; 

    function init() { 
     // day 
     this.d1 = doc.createElement('div'); 
     this.d1.setAttribute('class', 'day-1 elem'); 

     // ... more elements left out here 
    } 

    function updateView(time) { 
     this.d1.textContent = getDays(secs)[0]; 
    } 

    function getDays(secs) { 
     var result = 0; 
     if (secs > 0) { 
      result = secs/(60 * 60 * 24); 
     } 

     return Math.floor(result); 
    } 

})(document); 

은 ---

여기 내 전체 코드 편집입니다 ---에서 설정 간격콜백 콜백 자체를 바인딩하거나 updateView을 직접 바인딩해야합니다.

function initialize() { 
    domReady(function() { 

     // create DOM 
     createElements.call(this); // call with current context 

     // get time 
     var now = new Date(); 
     var year = now.getFullYear(); 
     var month = now.getMonth(); 
     var dateFinal = new Date(year, month + 1, 1, 0, 0, 0); // first day next month 
     var seconds = getSecsLeft(dateFinal); 
     var time = getTimeLeftObject(seconds); 

     var update = updateView.bind(this); 

     // update view every second 
     setInterval(function() { 
      seconds = getSecsLeft(dateFinal); 
      time = getTimeLeftObject(seconds); 
      update(time); 
     }, 1000); 

     // first time 
     update(time); 
    }.bind(this)); //bind callback 
} 

또는

function initialize() { 
    var update = updateView.bind(this), 
     create = createElements.bind(this); // prebind functions that use this 
    domReady(function() { 

     // create DOM 
     create(); //call prebinded function 

     // get time 
     var now = new Date(); 
     var year = now.getFullYear(); 
     var month = now.getMonth(); 
     var dateFinal = new Date(year, month + 1, 1, 0, 0, 0); // first day next month 
     var seconds = getSecsLeft(dateFinal); 
     var time = getTimeLeftObject(seconds); 

     // update view every second 
     setInterval(function() { 
      seconds = getSecsLeft(dateFinal); 
      time = getTimeLeftObject(seconds); 
      update(time); 
     }, 1000); 

     // first time 
     update(time); 
    }); 
} 
+0

잘 (잘, 이해 - 그것은 질문에 단지 코멘트가 아니었다!) – Jamiec

+0

오우 오케이 지금 나는 질문을 이해한다! Nice;) –

+0

내 관심사를 위해서, 왜'this'를'updateView' 함수에 바인딩해야합니까? – LeDoc