I have a web application with a UIController module, which gets user input from the DOM, a CBController module, which outputs processed user input to the Clipboard, and an appController module, which processes the user input for output to the Clipboard. The appController module has an Appobj object which is scoped to the appController module and stores the state and values for each UI element. So far so good.
But here's the issue - I just wrote the Appobj object to the Firefox Developer Edition console from an appController public function and although the console lists all its properties as expected, the object evaluates to empty. That is, Object.keys returns an empty array with no length and for/in fails silently, i.e. any console actions within the for/in are ignored, and the object's properties can't be accessed, i.e. return undefined. The only difference between this Appobj object and an Appobj object that behaves normally (i.e. has length and returns a non-empty array with Object.keys) is that in the Firefox console, the 'empty' Appobj object shows no ellipses between the curly brackets while the populated Appobj object (when called from an appController private function) shows ellipses, as shown:
Empty Appobj with properties:
Normal Appobj:
Both objects appear to have identical prototypes. Object.hasOwnProperties didn't help. What's worse, in Chrome both these are identical in the console, that is, there are no ellipses to distinguish them, so if I was using Chrome I'd not been to determine any difference between them at all except that one of them is functionally empty.
I've worked around it so it's not mission-critical, but I'd be grateful if someone could help me understand this, since I did lose a couple hours on it.
Code snippet is included, but note that the SO console shows Appobj as empty while FF and Chrome show it as having properties even though it is functionally empty. As in the screenshots above, FF shows no ellipses within the curly brackets. To get the ellipses, uncomment the line as described in the code.
var MyApp = (function () {
var UIController = (function() {
return {
initUI: function() {
appController.getAppobj();
appController.initmyAppControllerFunction();
},
writeCurImgToDOM: function(Appobj) {
document.querySelector('#cur-img').style.width = Appobj.imgNW + 'px';
document.querySelector('#cur-img').style.height = Appobj.imgNH + 'px';
},
populateAppobj: function (Appobj) {
let curImg;
function populateAppProperties(Appobj) {
// !VA Get the current image
curImg = document.querySelector('#cur-img');
Appobj.imgNW = curImg.naturalWidth;
Appobj.imgNH = curImg.naturalHeight;
}
populateAppProperties(Appobj);
},
};
})();
var appController = (function(UICtrl) {
let Appobj = {};
function myAppControllerFunction() {
UIController.populateAppobj(Appobj);
UIController.writeCurImgToDOM(Appobj);
}
return {
getAppobj: function() {
// Uncomment the line below to make Appobj a 'normal' object
// UIController.populateAppobj(Appobj);
console.log('Appobj is: ');
console.dir(Appobj);
Object.keys(Appobj).length === 0 ? console.log('getAppobj NO LENGTH') : console.log('getAppobj HAS LENGTH');
},
initmyAppControllerFunction: function() {
myAppControllerFunction(true);
},
// !VA appController public
init: function(){
console.log('App initialized.');
// !VA Initialize the UI
UICtrl.initUI();
}
};
})(UIController);
appController.init();
})();
body {
background: #000000;
}
#main-image {
position: relative;
display: block;
}
#cur-img {
display: block;
margin: 0 auto;
}
<!DOCTYPE html>
<html lang="en" dir="ltr" itemscope itemtype="http://schema.org/Article">
<head>
<meta charset="utf-8">
<link rel="stylesheet" media="all" href="css/scrap.css">
</head>
<body>
<div id="main-image">
<div id="cur-img-container">
<img src="http://vanocular.com/public/_200X150.png" id="cur-img" alt="">
</div>
</div>
</body>
</html>