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.
Related
The below code snippet I found on one blogs to avoid if-else statement. This code is very modular and can be easily extended. But I am not able to get this to work.
CatModel.prototype.makeWords = function () {
console.log('inside catmodel')
this.setWord('meow')
this.sayIt()
}
DogModel.prototype.makeWords = function () {
console.log('inside dogmodel')
this.setWord('bark')
this.saySomething()
}
// somewhere else
var makeWords = function (type) {
var model = namespace[type + 'Model']
model.makeWords()
}
makeWords('cat')
Presumably the CatModel and DogModel functions are declared somewhere and setWord and sayIt are also set up on their prototype object.
You'd need to put CatModel and DogModel in an object and refer to it from namespace (which I'd recommend not calling namespace):
var namespace = {
CatModel: CatModel,
DogModel: DogModel
};
Then when creating an instance, use new (you always use new with constructor functions). I'd also put the () on the call even though strictly speaking they're optional if you don't have parameters to pass:
var makeWords = function (type) {
var model = new namespace[type + 'Model']()
// ---------^^^--------------------------^^
model.makeWords()
}
When creating an object to use JS in an OO manner, is there any difference within a JS engine between (with the exception of being able to define a constructor:
var Uploader = Uploader || {};
and
var Uploader = function() {
}
and
function Uploader() {
}
Especially when later, you wish to do something along the lines of
Uploader.DOM = {
Create: function(file) {
}
};
Is it all down to personal preference? Or is there a real difference?
Objects:
var MyObj = {
myArr: [1,2,3],
find: function(/*some arguments*/) {
//some logic that finds something in this.myArr
}
}
In MyObj.find function this keyword will point to MyObj (which somewhat resembles how this works in languages those have classes). You can use this functionality to do mix-ins:
var MyObj2 = {
myArr: [4,2,6]
}
MyObj2.find = MyObj.find;
In MyObj2.find function this keyword will point to MyObj2.
Also objects support getters and setters (works on IE9+ and all good browsers):
var MyObj = {
myArr: [1,2,3],
find: function(/*some arguments*/) {
//some logic that finds something in this.myArr
},
get maxValue() {
return Math.max.apply(null, this.myArr);// maxValue is calculated on the fly
},
a_: null,
get a () {
return this.a_;
},
set a (val) {
//fire a change event, do input validation
this.a_ = val;
}
}
Now max value in the array can be accessed like this: MyObj.maxValue. I also added a property a_. It can't be named the same as its getter and setter so appended an underscore. Appending or prepending underscores is a naming convention for private variables which should not be accessed directly.
var qwe = MyObj.a // get a_
MyObj.a = 'something'; //set a_
Functions:
var u = new Uploader(); // will throw an exception
var Uploader = function() { }
Uploader is defined in runtime here. It does not exist yet when I try to instantiate it.
var u = new Uploader(); //will work
function Uploader() {}
Uploader is defined in compilation time here so it will work.
Functions can be used with revealing pattern to conceal some members. Functions don't support getters and setters but you can put objects inside functions.
function myFunc() {
function privateFunc() {};
function publicFunc() {};
var obj = {
//members, getters, setters
};
return {
publicFunc: publicFunc,
obj: obj
}
}
You can call muFunc.publicFunc() outside of myFunc because it is returned. But you can not use privateFunc outside because it is not returned.
Revealing pattern functions are not meant to be instantiated usually. This is because when you instantiate it everything inside will be copied to a new instance. So it will use up more memory than if you would add functions using prototype.
myFunc.prototype.someFunc = function() {};
Like this all instances of myFunc will share the same instance of someFunc.
Conclusion: with functions you can simulate a private access modifier but in objects the this keyword acts somewhat similar of what you'd expect in a language that have classes. But you always can use call, apply and bind to change the context (i.e. what 'this' keyword will be) of the function.
I've put these together with the help of others and several resources. I've made a fiddle of everything, and the stripped down code is posted below.
Basically I've learned how to use each of these patterns but I'm curious about the more fundamental differences between these approaches. Downstream code is practically identical with any of these patterns, but is there a reason why one should use one over another, beyond personal preference? Also though I've tried to gather up the most common patterns, please suggest your own if it's better.
Pattern 1 (Object Based):
var mouseDiff = {
"startPoint" : {"x" :0, "y" : 0},
"hypotenuse" : function(a,b) {
// do something
},
"init" : function(){
// do something
}
}
mouseDiff.init();
Pattern 2 (Most traditional as far as I know):
function MouseDiff() {
this.startPoint = {"x" :0, "y" : 0};
}
MouseDiff.prototype.hypotenuse = function(a,b) {
// do something
}
MouseDiff.prototype.init = function() {
// do something
}
var myMouse = new MouseDiff;
myMouse.init();
Pattern 3 (Making use of closure):
var MouseDiff2 = (function() {
var startPoint = {"x" :0, "y" : 0};
var hypotenuse = function(a,b) {
// do something
};
return {
hypotenuse: hypotenuse,
init : function(){
// do something
}
};
}());
MouseDiff2.init();
Pattern 1 is a singleton. If you only need one such object, it's just fine.
Pattern 2 builds new objects, and takes advantage of the prototype object so that when a new MouseDiff object is created, it will not create new copies of the functions (which are themselves data in JavaScript).
Pattern 3 requires more memory in comparison to a regular singleton but it offers static privacy.
I like the following pattern, as it covers various features, though it is really a combination of the constructor (pattern 2) and closure (pattern 3):
var MouseDiff = (function () {
var aStaticVariable = 'Woohoo!';
// And if you really need 100% truly private instance
// variables which are not methods and which can be
// shared between methods (and don't mind the rather
// big hassle they require), see
// http://brettz9.blogspot.com/search?q=relator
// (see also the new plans for a Map/WeakMap in ECMAScript)
function _APrivateStaticMethod () {
alert(aStaticVariable);
}
// An instance method meant to be called on the
// particular object as via ".call(this)" below
function _APrivateInstanceMethod () {
alert(this.startPoint.x);
}
// Begin Constructor
function MouseDiff() {
this.startPoint = {"x" :0, "y" : 0};
}
MouseDiff.prototype.hypotenuse = function(a,b) {
// do something
};
MouseDiff.prototype.init = function() {
// do something
_APrivateStaticMethod(); // alerts 'Woohoo!'
_APrivateInstanceMethod.call(this); // alerts 0 (but if not
// called with this, _APrivateInstanceMethod's internal
// "this" will refer (potentially dangerously) to the
// global object, as in the window in the browser unless
// this class was defined within 'strict' mode in which
// case "this" would be undefined)
};
return MouseDiff;
}());
var myMouse = new MouseDiff;
myMouse.init();
I do not know enough about JavaScript to tell you what if any performance differences exist between these approaches. Here are just two differences between these I noticed. I'm sure there are others.
Pattern 1 creates one object with those properties, including attached methods. Pattern 2 allows us to easily create many objects with the same methods attached, without rewriting them.
Pattern 3 is like a factory. Instead of relying on prototype to automatically attach these methods, the factory just creates them anew and returns the object. The usage of a closure allows us to hide the "member variables" of the object. There is no way to access startPoint or hypotenuse() except through the "public" interface returned.
Whenever I answer these types of theoretical JavaScript questions, I always fear there is some technical detail I am forgetting or overlooking. If so, let me know, and I will fix the answer.
Pattern two is my personally preference because it is the closest to traditional object oriented programming and allows for easy inheritance.
This post by John Resig (the guy behind JQuery) uses that method...
http://ejohn.org/blog/simple-javascript-inheritance/
[edit]
In fact, I don't think methods 1 or 3 have any benefits. 1 is, as someone else said, a singleton and does not allow multiple instances and 3... I don't know where to start with 3.
There is one more possible way to do this.
var MouseDiff = {};
(function(context) {
var privateVarialble = 0;
context.hypotenuse = function() {
//code here
};
context.int = function() {
//code here
}
})(MouseDiff);
Here we simply pass the namespace as an argument to a self-invoking function. The privateVarialble variable is private because it does not get assigned to the context.
We can even set the context to the global object (with a one word change!). Inside brackets (MouseDiff) make it (this). This is a big asset for library vendors – who can wrap their features in a self-invoking function and leave it to the user to decide whether they should be global or not.
http://www.jsoops.net/ is quite good for oop in Js. If provide private, protected, public variable and function, and also Inheritance feature. Example Code:
var ClassA = JsOops(function (pri, pro, pub)
{// pri = private, pro = protected, pub = public
pri.className = "I am A ";
this.init = function (var1)// constructor
{
pri.className += var1;
}
pub.getData = function ()
{
return "ClassA(Top=" + pro.getClassName() + ", This=" + pri.getClassName()
+ ", ID=" + pro.getClassId() + ")";
}
pri.getClassName = function () { return pri.className; }
pro.getClassName = function () { return pri.className; }
pro.getClassId = function () { return 1; }
});
var newA = new ClassA("Class");
//***Access public function
console.log(typeof (newA.getData));
// function
console.log(newA.getData());
// ClassA(Top=I am A Class, This=I am A Class, ID=1)
//***You can not access constructor, private and protected function
console.log(typeof (newA.init)); // undefined
console.log(typeof (newA.className)); // undefined
console.log(typeof (newA.pro)); // undefined
console.log(typeof (newA.getClassName)); // undefined
This has been answered elsewhere many times before but just to offer up some variety. ds.oop is a nice way to declare classes with constructors in javascript. It supports every possible type of inheritance (Including 1 type that even c# does not support) as well as Interfaces which is nice.
var Color = ds.make.class({
type: 'Color',
constructor: function (r,g,b) {
this.r = r; /* now r,g, and b are available to */
this.g = g; /* other methods in the Color class */
this.b = b;
}
});
var red = new Color(255,0,0); // using the new keyword to instantiate the class
I'm new to javascript namespaces, and I found myself kinda deep within a namespace, but unable to find a way to navigate from within the namespace to another object in the same general namespace. It's best described by the code below:
$.fileUploading = {
images: {
settings: {
// How do you do this?
bing_bong: find.a.way.to.functionOne
},
functionOne: function() { return "Rock!"; }
}
}
Is there a way to do that?
Because namespaces are just properties on objects, there's no way to find out what object a property belongs to, from the property. A simple reason is that an identical property can appear in multiple objects.
Namespaces are supposed to be stable and constant, so there's nothing wrong with referencing the entire thing. However, if you need to access the same names a ton of times, you could make it a bit easier for yourself by assigning it to a variable.
var my_ns = $.fileUploading;
This would work:
$.fileUploading = {
images: {
settings: {},
functionOne: function() { return "Rock!"; }
}
};
$.fileUploading.images.settings.bing_bong = $.fileUploading.images.functionOne;
This also:
function f() { return "Rock!"; }
$.fileUploading = {
images: {
settings: {
// How do you do this?
bing_bong: f
},
functionOne: f
}
};
(function(){
var yourNameSpace={
publicProp1:publicFn1,
publicProp2:publicFn2,
publicProp3:publicFn3
};
window.yourNameSpace = yourNameSpace;
//private variable
var _privateVar1,_privateVar2,_privateVar3;
//privatefns
function _privateFn1(){}
function _privateFn2(){}
function _privateFn3(){}
function _privateFn4(){}
//public functions can access private fns
function publicFn1(){}
function publicFn2(){}
function publicFn3(){}
}(undefined);
In OO Javascript constructor pattern: neo-classical vs prototypal, I learned that constructors using prototypal inheritance can be 10x faster (or more) than constructors using the so-called neo-classical pattern with closures as proposed by Crockford in his "Good Parts" book and presentations.
For that reason it seems like preferring prototypal inheritance seems like the right thing, in general.
Question Is there a way to combine prototypal inheritance with the module pattern to allow private variables when necessary?
What I am thinking is:
// makeClass method - By John Resig (MIT Licensed)
function makeClass(){
return function(args){
if ( this instanceof arguments.callee ) {
if ( typeof this.init == "function" )
this.init.apply( this, args.callee ? args : arguments );
} else
return new arguments.callee( arguments );
};
}
// =======================================================
var User = makeClass();
// convention; define an init method and attach to the prototype
User.prototype.init = function(first, last){
this.name = first + " " + last;
};
User.prototype.doWork = function (a,b,c) {/* ... */ };
User.prototype.method2= (function (a,b,c) {
// this code is run once per class
return function(a,b,c) {
// this code gets run with each call into the method
var _v2 = 0;
function inc() {
_v2++;
}
var dummy = function(a,b,c) {
/* ... */
inc();
WScript.echo("doOtherWork(" + this.name + ") v2= " + _v2);
return _v2;
};
var x = dummy(a,b,c);
this.method2 = dummy; // replace self
return x;
};
})();
That isn't quite right. But it illustrates the point.
Is there a way to do this and is it worth it?
preferring prototypal inheritance seems like the right thing, in general
Well... it's the more natural, native-feeling thing to do in JavaScript, certainly. But so much JavaScript does is wrong that this isn't necessarily a compliment!
Certainly when performance isn't an issue, objects that get their own bound copies of each method are easier to cope with than objects that share their methods, because you can just pass on a reference to object.method without having to make a closure-delegate or function.bind.
Is there a way to combine prototypal inheritance with the module pattern to allow private variables when necessary?
What do you want from private variables? If it's some Java-style idea of security by encapsulation, I'd give that up and just do it the Python way: put an underline on the start of the member name and anyone who wants to use from the outside will be suitably warned that it's unsupported and may screw up. There is never a security boundary inside JavaScript code executing on the same page that would warrant keeping your privates really private.
If what you want is to avoid having to locate the right copy of this when the method is called, you could manually bind methods methods in the initialiser:
var Thing= makeClass();
Thing.prototype.init= function(a) {
this._a= a;
this.showA= this.showA.bind(this);
};
Thing.prototype.showA= function() {
alert(this._a);
};
thing= new Thing(3);
setTimeout(thing.showA, 1000); // will work as `thing` has its own bound copy of `showA`
(function.bind is future-JavaScript that you can hack into the Function.prototype now until browsers support it.)
This naturally loses some of the lightweight nature of prototype-based objects, but at least you can still have them share members that aren't methods, and methods that are never going to be used as delegates, as long as it's clear and you can always remember which methods are the ones that you can use this way.
If you simply want to be able to type a private variable name without having to put this. all the time then, yeah, you'd have to do it with a closure. Your example world maybe be a little clearer called from the initialiser rather than using the first-time-self-writing:
var User= makeClass();
User.prototype.init= function(first, last){
this.name= first+' '+last;
this.method2= this._method2factory();
};
User.prototype._method2factory= function() {
var _v2= 0;
function inc() {
_v2++;
}
return function method2(a,b,c) {
/* ... */
inc();
WScript.echo('doOtherWork('+this.name+') v2= '+_v2);
return _v2;
};
};
But I'm not really sure this gets you much in comparison to just writing this._v2 and this._inc().
I'm not totally sure I understand your question. But going from what I think I do understand...
function Foo () { /*constructor*/
var counter = 0; /* private variable */
this.incrementCounter=function () { /*privileged function */
counter++
}
this.getCounter=function () { /*privileged function */
return counter;
}
}
/*public functions. Note: this pattern destroys constructor property.
Lesson: Don't depend on the constructor property! */
Foo.prototype = {
toString: function () {
var string = "";
var count = this.getCounter();
while(count--) {
string+="*"
}
return string;
}
}
var bar = new Foo();
bar.incrementCounter();
bar.incrementCounter();
bar.toString(); /* in theory, this returns "**".. haven't tested code */
You may take a look at
https://github.com/riga/jclass
I think that's what you're looking for.
Personally, I prefer the following syntax :
var keyValueStore = (function() {
// Singleton private properties
var count = 0;
var kvs = function() {
// Instance private / privileged properties
count++;
};
kvs.prototype = {
// Instance public properties
'data' : {},
'get' : function(key) { return this.data[key]; },
'set' : function(key, value) { this.data[key] = value; },
'delete' : function(key) { delete this.data[key]; },
'getLength' : function() {
var l = 0;
for (p in this.data) l++;
return l;
}
};
return {
// Singleton public properties
'create' : function() { return new kvs(); },
'count' : function() { return count; }
};
})();
With this syntax, you have a singleton object, the possibility to create instances with prototype inheritance and the possibility to define private properties at several levels.
You use it like this :
kvs = keyValueStore.create();
kvs.set('Tom', "Baker");
kvs.set('Daisy', "Hostess");
var profession_of_daisy = kvs.get('Daisy');
kvs.delete('Daisy');
console.log(keyValueStore.count());