我试图将Revealing Module模式与Constructor模式一起使用来创建一些漂亮的JS!我希望能够创建多个实例,如果" Countdown"像这样:
var c1 = new Countdown();
c1.init();
var c2 = new Countdown();
c2.init();
这些应该是独立的。因此,我没有使用" var"来声明变量,而是使用"这个"在原型上。我引用了这个"这个"在函数内部,但它未定义。我怎样才能访问"这个"?
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);
---编辑---
这是我的完整代码:
"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 :(得分:4)
您似乎在updateView
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)
}
UPD 由于您要在domReady
回调中设置间隔,因此您需要先绑定回调本身或预先绑定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);
});
}