Using a constructor on a JavaScript static instance - javascript

I'm writing a JavaScript library in which I want some methods and properties public and other private. The following seems a great way of doing this whilst wrapping everything up into a single object.
(function (window) {
var Thing = function() {
// private var
var variable = "value";
return {
// public method
method:function() {
alert(variable);
}
}
}();
window.Thing = Thing;
})(window);
Thing.method();
Which is great. (Mostly grabbed from here).
However, I'd still like to be able to use the constructor of Thing to pass in some arguments.
Is there anyway I can provide a constructor in the return statement, or use prototype to override the constructor? So I can call:
Thing(stuff);
Right now, if I try that it causes:
Uncaught TypeError: Property 'Thing' of object [object DOMWindow] is not a function
Which makes sense as it's not returning itself, but ideally it'd be possible to call a constructor.
OR, is this just baaaad and I should steer clear of some or all of this?

To accomplish what you are asking, do something like this:
(function (window) {
var thingMaker= function(stuff) {
// private var
var variable = "value";
return {
// public method
method:function() {
alert(variable);
}
alertStuff:function() {
alert(stuff);
}
}
};
window.thingMaker= thingMaker;
})(window);
var myThing = window.thingMaker(stuff);
myThing.alertStuff()
More information can be found by searching the googlenets for Douglas Crockford. Some great and very informative videos by him are available on yui theater. But I would have to ask, why create another framework when there are already so many great ones out there (jquery,prototype,yui,dojo to name a few)

Thing is already created, so you are always going to be too late to call a 'constructor'.
You could pass variables in like this:
(function (window, var1, var2) {
var Thing = function() {
// private var
var variable = "value";
return {
// public method
method:function() {
alert(variable);
}
}
}();
window.Thing = Thing;
})(window, var1, var2);

Thing is an Object with one method called method:
{
// public method
method:function() {
alert(variable);
}
}
Thing.method(); // alerts "value"
You could return instead:
function () {
alert(arguments)
}
Then
Thing(6,5,4); // alerts 6,5,4

Related

module reveal prototype pattern - private variables

I am using the module reveal prototype pattern (https://weblogs.asp.net/dwahlin/techniques-strategies-and-patterns-for-structuring-javascript-code-revealing-prototype-pattern), and am having trouble accessing my this variable in my prototype functions. I have this code:
myapp.ConfirmationWindow = function (temptype) {
this._type = temptype;
};
myapp.ConfirmationWindow.prototype = function () {
this._showConfirmationWindow = function (message) {
var a = this._type; //valid
return _showWindow("hello");
}
this._showWindow = function (message) {
var a= this._type; //invalid
}
return {
showConfirmationWindow: _showConfirmationWindow
};
}();
I am able to access this._type in _showConfirmationWindow(), but am not able to access this._type in _showWindow. The different is that the prototype is setting _showConfirmationWindow() as public and _showWindow as private, but why doesn't _showWindow get access to this._type. Why is this the case.
One solution I found is to pass this as an extra parameter in _showWindow
_showWindow don't have a this reference to your instance because it's not part of ConfirmationWindow prototype because by returning only showConfirmationWindow, it never gets assigned to the prototype. You could use call to invoke your private functions like:
_showWindow.call(this, "hello")
Or adding a second argument to _showWindow like and pass the this reference when you invoke it:
_showWindow(message, self)
But i would prefer the first one.

What is the basic use of calling the private function inside the public function?

What is the perpose of calling privateMethod from the publicMethod?
Can't we just define the content of privateMethod inside the public method and do the same thing ?
var basketModule = (function() {
var basket = [];
function privateMethod() {
console.log(basket);
}
return {
publicMethod: function(){
privateMethod();
}
};
})());
basketModule.publicMethod();
In your simple example, there is not really a reason for privateMethod to exist because all publicMethod does is call it, but in a more real-world example, the private methods would do things that you don't want other modules calling on their own.
For example, this is a snippet of code that I worked on today, reduced to make it a good example:
(function(){
function _renderTreeLevel() { ... }
function _backfillAllSelectedStates() { ... }
function _updateSelectedCount() { ... }
return {
render: function() {
var expandCollapse = new ExpandCollapse();
expandCollapse.render();
_renderTreeLevel(0, this.ui.treeRegion, this.treeData);
_backfillAllSelectedStates();
_updateSelectedCount((this.options.selected || []).length);
$('.collapse').collapse();
}
};
})();
The 3 "private" function that start with '_' are just functions that I put code into for refactoring and making the code cleaner and more reusable. They are not functions that I want someone to be able to call.
Users of this module should call render() only.
The reasoning is the same as any other language that has public and private members built-in, like C# or Java, but since JavaScript doesn't provide that concept, this is the pattern that people follow to provide a similar behavior.

Accessing "private" members within an anonymous function outside scope

Basically what I am trying to do, is to provide access to "private" functions/variables for an anonymous function. I need some opinions about two ways I achieve this and possible better alternatives to these approaches. Fiddle
Observe the following snippet.
function Something()
{
/*private*/ var _someVariable = 1;
/*private*/ function _someFunction() {
alert('_someFunction');
}
/*public*/this.SomeDelegate1 = function(codeblock) {
var members = $.extend({
_someVariable : _someVariable,
_someFunction:_someFunction
}, this);
codeblock.apply(members);
}
/*public*/this.SomeDelegate2 = function(codeblock) {
var caller = eval('(' + codeblock + ')');
caller.apply(this);
}
}
In SomeDelegate1, I convert my private members to instance members and pass it as context to the
anonymous function like seen below.
var someInstance = new Something();
someInstance.SomeDelegate1(
function() {
this._someFunction();
alert(this._someVariable);
}
);
I like the fact that one can specify which members you would like to expose, but it can potentially get quite clunky e.g. when you need to update "private" variables for example.
I can obviously write all members as instance members, but I would rather prefer them to stay "private", only allowing access within scope of the callback function.
In SomeDelegate2, I use an eval (yes I am aware of all the evils and witchcraft associated with this).
var someInstance = new Something();
someInstance.SomeDelegate2(
function() {
_someFunction();
alert(_someVariable);
}
);
Since I am injecting code into the function, the "privately" scoped members are automatically available, so I don't need to do any copying of members etc and not a lot of work needs to be done otherwise.
Is there fundamental problems with this approach?
Do you have better alternatives/approaches to achieve this?
As I said in my comment, I would make everything public and prefix "private" property names with an underscore. This is how I would restructure your code:
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
var Something = defclass({
constructor: function () {
this._someVariable = 1;
},
_someFunction: function () {
alert("someFunction");
},
someDelegate1: function (f) {
f.apply(this);
},
someDelegate2: function (f) {
f.call(this, this._someVariable, this._someFunction);
}
});
var someInstance = new Something;
someInstance.someDelegate1(function () {
this._someFunction();
alert(this._someVariable);
});
someInstance.someDelegate2(function (someVariable, someFunction) {
someFunction();
alert(someVariable);
});
However that's just my opinion. I don't really see the point of having private variables. Even if somebody messes with your private variables, it's their problem and not yours. It'll break their code and not yours.

Defining a jQuery ajax callback parameter as an existing object type

I admit this question is getting to the limits of what I know of JavaScript & jQuery, and there is probably a more proper way to state my question (which would help in finding an existing solution), but if you can bear with me, this is what I'm after.
I have an existing object class I've defined. I'm making a jQuery ajax call using getJSON, and I want my callback parameter (which is an object) to be classed as my custom object, so that I can access that class' methods from it.
So I have some object class
function Boo() {
this.param1;
this.param2;
this.yah = function() {
...
}
}
and then I have something elsewhere of the sort
$.getJSON(url,function(new_instance) {
//from my php source this passed object is already loaded with param1, param2...
alert(new_instance.param1); //no probs
//but i want to be able to then call
new_instance.yah();
});
In other words, I want new_instance to be considered an instance of Boo(). I know in stuff like ActionScript you have to class the incoming parameters for exactly this reason, dunno what flexibility I have in JS.
I thought maybe about having an intermediate function that takes in the incoming object and creates/populates a new instance of Boo() but not sure if there is a more clever method.
Many thanks!!
Do not define methods in the constructor function, you are
defining them over and over again every time the costructor
is called. Move them over to the prototype:
Boo.prototype = {
yah: function() {
},
bah: function() {
}
...
};
a little helper function:
function coerceTo( proto, values ) {
var r = Object.create( proto );
for( var key in values ) {
r[key] = values[key];
}
return r;
}
Depending on browser, Object.create might not be available, so:
if (!Object.create) {
Object.create = function (o) {
if (arguments.length > 1) {
throw new Error('Object.create implementation only accepts the first parameter.');
}
function F() {}
F.prototype = o;
return new F();
};
}
Usage:
new_instance = coerceTo( Boo.prototype, new_instance );
new_instance instanceof Boo //true
new_instance.yah();
What you can do:
$.getJSON(url,function(newObjData) {
var newObj = $.extend(new Boo(), newObjData);
newObj.yah();
});
Also consider moving your Boo methods to object prototype so the methods don't get recreated for each Boo instance:
var Boo = function() {
this.param1;
this.param2;
}
Boo.prototype.yah = function() {
console.log(this.param1);
}

Call a JavaScript function name using a string?

How can I hook up an event to a function name I have defined as a string?
I'm using Prototype.js, although this is not Prototype-speficic.
$(inputId).observe('click', formData.fields[x].onclick);
This would result in JavaScript complaining that my handler is not a function. I would prefer not us use eval().
Property accessors can be used to access any object's properties or functions.
If the function is in the global scope, you can get it using the window object:
var myFunc = window[myFuncName];
This also works within the this scope:
var myFunc = this[myFuncName];
I have worked on this problem, as I needed a function like this. Here is my sandbox code, not thoroughly tested, but can be a startpoint for others.
Note that there is one eval() in the code as I couldn't figure out how to bypass that step, maybe a javascript quirk and cannot be done in any other way. Let me know if there is a way to get rid of eval() here!
executeFunctionByName = function(functionName)
{
var args = Array.prototype.slice.call(arguments).splice(1);
//debug
console.log('args:', args);
var namespaces = functionName.split(".");
//debug
console.log('namespaces:', namespaces);
var func = namespaces.pop();
//debug
console.log('func:', func);
ns = namespaces.join('.');
//debug
console.log('namespace:', ns);
if(ns == '')
{
ns = 'window';
}
ns = eval(ns);
//debug
console.log('evaled namespace:', ns);
return ns[func].apply(ns, args);
}
core = {
paragraph: {
titlebar: {
user: "ddd",
getUser: function(name)
{
this.user = name;
return this.user;
}
}
}
}
var testf = function()
{
alert('dkdkdkd');
}
var x = executeFunctionByName('core.paragraph.titlebar.getUser', 'Ikon');
executeFunctionByName('testf');
... or this[myFuncName];
Perhaps?
setTimeout ( "myFunc()", 1 );
Just an eval would do the job
var call = eval("method_name").call(args);
Looks like formData.fields[x].onclick holds the name of a global function? If so try:
$(inputId).observe('click', window[formData.fields[x].onclick]);
window.myFunction === window["myFunction"]
Do you know what the onclick property contains or what type it is? I assume this is prototype specific stuff, as "fields" does not exist in DOM forms.
If you need to call a string function with arguments, do this:
window[stringFunctionName].apply( window, arrayOfArguments )
You can use scope in place of window if preferred
update:---
use ES6 export and import
a.js
const fn = {
aaa: function() {
//code
},
bbb: function() {
//code
},
//codes ....
nnn: function() {
//code
}
}
export default fn
b.js
import someFn from './a'
//eg
const str1='aaa'
const str2 = 'bbb'
someFn[str1]()
eval('str') (obsolete feature https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Deprecated_and_obsolete_features )
setTimeout('str') setInterval('str')
window['str'] (but...sometimes,global object is not window)
new Function('str')
These methods above always not be recommend by some reasons, but they are really convenient to use.
These methods below are safe, but really not conveninet to use.
switch...case (or if...else)
switch(str){
case 'str1':
fn1()
break
case 'str2':
fn2
//and so on
}
put functions in a object
const fn={
str1:fn1,
str2:fn2
//and so on
}
fn[str1] //call function

Categories