How to make Static member inside a function public inside namespace
var myNamespace= new function()
{
this.myClass= function Page()
{
this.MyStaticVar = "myValue";
}
}
$("#block").html(myNamespace.myClass.MyStaticVar);
http://jsfiddle.net/DSs6r/97/
Please try it there...
The "namespace" shouldn’t be a function, and this isn’t right in either case.
var myNamespace = {
myClass: function Page() {
}
};
myNamespace.myClass.MyStaticVar = "myValue";
(Updated jsFiddle)
Like this:
var ns = {
Class: {
myStaticVar: 'myValue'
}
};
The main, only really, issue here was that you used a named function instead of an anonymous one (function Page()). Without the name, your code works just fine:
var myNamespace = new function()
{
this.myClass = new function()
{
this.MyStaticVar = "myValue";
};
};
Here is a jsfiddle showing the code working: http://jsfiddle.net/DSs6r/101/
More than likely, you were looking for a setup like this:
var myNamespace = new function()
{
var Page = function(){
var MyStaticVar = "myValue";
var MyDynamicVar = "";
function SetDynamicVar(val){
MyDynamicVar = val;
};
function GetDynamicVar(){
return MyDynamicVar;
}
return{
MyStaticVar: MyStaticVar,
SetDynamicVar: SetDynamicVar,
GetDynamicVar: GetDynamicVar
};
};
this.myClass = new Page();
};
Which would allow stuff like this:
myNamespace.myClass.SetDynamicVar("someValue")
$("#block").html(myNamespace.myClass.GetDynamicVar());
and:
$("#block").html(myNamespace.myClass.MyStaticVar);
Here is the working fiddle: http://jsfiddle.net/DSs6r/102/
Related
Inspired from angular service method declaration, I am using plain javascript file and write function in the below way (I don't know what this approach is called)
test.js
var MyService = function() {
var base;
var service = {
init: function (formdata) {
base.name = formdata.name;
console.log('calling init');
},
other: function () {
console.log('caling other');
}
}
return service;
}
Now in HTML I want to call it like MyService.init(formdata);
<html>
<head>
<title>Scratchpad</title>
<script src="test.js"></script>
<script>
var formdata = {};
function generateData() {
var form = document.getElementById('Myform');
formdata.name = 'Alpha';
console.log(formdata);
MyService.init(formdata);
}
</script>
</head>
<body>
<form id="Myform" role="form" method="post">
<button type="button" onclick="generateData()">Generate Data</button>
</form>
</body>
</html>
but it produces the following error
uncaught ReferenceError: MyService is not defined
Can't we achieve this way in plain javascript?
MyService is a function not an object which has properties, you need to invoke as
MyService().init(formdata);
also base is undefined, so it has to be initialized as
var base = {};
Complete example
var MyService = function() {
var base = {};
var service = {
init: function (formdata) {
base.name = formdata.name;
console.log('calling init');
},
other: function () {
console.log('caling other');
}
}
return service;
}
MyService().init({name:"2"}) ; //outputs 'calling init'
The right way is to use prototype. This is intended for creating SDK designs. If you encounter any JavaScript SDK, you will see a similar pattern. That doesn't mean you can't use, though, I personally use it in all my projects.
You should enclose MyService in a private scope to avoid conflict with other namespaces, and return only MyService.
(function(){
// move all variables to here
var base;
var _service = function(){
// this is the constructor function, the initial functions can be run from here
}
_service.prototype = {
init: function (formdata) {
base.name = formdata.name;
console.log('calling init');
},
other: function () {
console.log('caling other');
}
}
// invoke _service as myService in global scope
window.MyService = new _service();
})();
Now you can access all function of MyService with
MyService.init({name:'James'}); // calling init
MyService.other(); // caling other
Try this
function MyService() {
this.base = "some thing";
}
MyService.prototype.init = function(formdata) {
console.log('calling init =>'+this.base);
}
MyService.prototype.other = function(formdata) {
console.log('caling other');
}
var myser = new MyService();
myser.init(1);
myser.other();
try this.
function generateVPC() {
var form = document.getElementById('Myform');
formdata.name = 'Alpha';
console.log(formdata);
var myservice = new MyService();
myservice.init(formdata);
}
and base is also giving error so define base as
var base = {};
I am new to IIFE and trying to implement namespace in JavaScript on a Siungleton JavaScript class:
I have a JavaScript class (say main class):
var myIIFE = (function () {
var x = null;
//constructor function
var myIIFE = function() {
var a = new IIFE.InsideIIFE(); //says not a constructor
}
myIIFE.prototype = {
//some methods
}
function createIstance() {
return new myIIFE();
}
return {
getInstance: function() {
if (!this.instance) {
this.instance = createInstance();
}
return this.instance;
}
};
})();
Then I have another JavaScript namespaced class:
myIIFE.InsideIIFE = (function() {
var inside = function() {}
inside.prototype = { //some methods }
return inside;
});
I want to create an object of myIIFE.InsideIIFE in myIIFE, and this is throwing me an error:
myIIFE.InsideIIFE is not a constructor
Am I doing something wrong? Or if this is a correct approach then what changes I should make.
I tried using new this.InsideIIFE() and just InsideIIFE, but non of them worked.
edit:
From my analysis, I understand that myIIFE (the parent) is an object as it return an object at:
return {
getInstance: function() {
//method body
}
}
There are many issues with this code, let's try to run it in our heads, from the start:
var myIIFE = (function () {
....
})();
This results in myIIFE being an object, to be precise, this object:
{
getInstance: function() {
if (!this.instance) {
this.instance = createInstance();
}
return this.instance;
}
}
So, then I assume, you do
myIIFE.getInstance()
Which tries to return new myIIFE();
It runs into myIIFE() and tries to do this:
new IIFE.InsideIIFE();
I assume you meant to write
new myIIFE.InsideIIFE();
because IIFE is not defined it anywhere in the code you provided.
Let's see what is myIIFE.insideIIFE
var myIIFE.InsideIIFE = (function() {
var inside = function() {}
inside.prototype = { //some methods }
return inside;
});
First of all you start with var, which is wrong, because myIIFE is already defined and you are just adding a new property to it. so it should be simply
myIIFE.InsideIIFE = (function() {
var inside = function() {}
inside.prototype = { //some methods }
return inside;
});
and it should work.
In general, it seems by your code, like you have not grasped the whole "constructor function" concept very well. I would suggest you take look at the following links, they should help.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
When defining a class in Javascript, how can I call one method from another one?
exports.myClass = function () {
this.init = function() {
myInternalMethod();
}
this.myInternalMethod = function() {
//Do something
}
}
The code above gives me the following error when executing it:
ReferenceError: myInternalMethod is not defined
I also tried this.myInternalMethod and self.myInternalMethod, but both lead to errors.
What's the right way to do this?
I have created this fiddle http://jsfiddle.net/VFKkC/ Here you can call myInternalMedod()
var myClass = function () {
this.init = function() {
this.myInternalMethod();
}
this.myInternalMethod = function() {
console.log("internal");
}
}
var c = new myClass();
c.init();
this.myInternalMethod() does seem to work, though:
var exports = {};
exports.myClass = function () {
this.init = function() {
this.myInternalMethod();
}
this.myInternalMethod = function() {
//Do something
}
}
var x = new exports.myClass();
x.init();
Is it a private member?
exports.myClass = function () {
this.init = function() {
myInternalMethod();
}
function myInternalMethod() {
//Do something
}
}
How to maintain a reference to an instance, when using the setTimeout callback? E.G:
In my ViewModel (using Knockout)
var MyVM = function () {
this.myFunc = function () {
setTimeout("this.myCallback()", 2000);
};
this.myCallback = function() { this.myObservable(true); }
}
This fails.
You can add a private field :
var MyVM = function () {
var self = this;
this.myFunc = function () {
setTimeout(self.myCallback, 2000);
};
this.myCallback = function() { self.myObservable(true); }
}
var vm = new MyVM();
Have a look at the RP Niemeyer's answer.
I hope it helps.
Is it possible to have private properties in a model? Like the locally declared variables in a (constructor) function, not attached to this, but declared locally and visible only by whatever is defined in the (constructor)function.
Example without BB View:
function MyView(aModel){
var $internalInput = $('<input>');
this.render: function($where){
$internalInput.val(aModel.get('SomeProperty'));
$where.append($('<div class="inputWraper">').append($internalInput));
};
this.toggleReadonly: function() {
toggle $internalInputs readonly attribute
}
...
+ Code to bind input.val to some aModel property(ies) and setup events
...
}
Note that internalInput is not accessible to outside world and aModel is also not accessible (through MyView at least).
So if I want to use Backbone.View to implement the above MyView, how would i do it and keep $internalInput 'private'?
You should be able to achieve private data by passing an IIFE to extend when defining your Backbone objects, rather than just a plain object. For example:
var Thing = Backbone.Model.extend((function () {
var foo = "Private data!";
return {
bar: function () {
console.log(foo);
}
};
})());
You'd better off with
var Thing = Backbone.Model.extend(
{
constructor : function ()
{
var _value = "Private data!";
this.getValue = function ()
{
return _value;
};
this.setValue = function (value)
{
_value = value;
};
}
});
Javascript is fun!
var Thing = (function () {
var number_of_things = 0;
return function (options) {
var value = "Private data!";
return new ( Backbone.Model.extend({
constructor: function constructor () {
number_of_things += 1;
},
getValue: function getValue () {
return value;
}
}) )();
};
}());
I'm a little concerned by the fact that every instance of this "Thing" is also a subclass, in the OOP lingo.
In the context of using Broserify.js with Backbone (and really any above medium project) I found the following way to have private vars and functions:
myView.js
'use strict';
var config = require('../config.js'),
private_var = 'private variable',
my_private_fn = function() {
...
};
module.exports = Backbone.Model.extend({
initialize: function() {
this.my_public = 'public variable');
console.log('This is my' + this.my_public);
console.log('This is my' + my_private);
},
});
The idea to take here is go with Browserify :P
The simplest way is the following:
...
initialize:function(properites){
// Init the logic with private and public methods/variable
this.logic.initFirst(this);
// Use public methods
this.logic.doSomething();
},
logic:{
initFirst:function(modelOrView){
// Do not continue if already initiated
if( this.instance !== undefined ) return;
// Write all logic here
this.instance = (function(logic, modelOrView){
// Private variables
var private = "private";
// Public methods
logic.doSomething = function(){
console.log(private, modelOrView);
};
// Private methods
function hidden(){
}
}(this, modelOrView));
}
},