Experiment: extending a native object - javascript

I was reading up on some discussions about extending native objects in javascript. Extending native objects in current browsers seem to have much less disadvantages than they used to. Certainly considering we have more control about how objects are extended through methods such as:
Object.defineProperty(<some parameters...>)
A big risk that however remains is that of collision between different code/libraries, resulting in unexpected behavior.
Risks of naming collision (and global clobbering) can be reduced by namespacing your own functions. So I thought why do we not do this if we extend the native object? Of course execution context is a problem but we can fix that with bind(), making native functions of that object available in our extended functionality. So i created the following to extend the Element object:
// Define the extend function
Object.defineProperty(Element.prototype, 'extend', { value: function(namespace, object) {
var cache = {};
// Create the namespace and make sure on invocation the Element is bound
Object.defineProperty(Element.prototype, namespace, { value: function() {
var objectCheck = typeof cache[Element.prototype.constructor.name] !== 'undefined';
if(objectCheck && typeof cache[Element.prototype.constructor.name][namespace] !== 'undefined'){
console.log('cache used');
return cache[Element.prototype.constructor.name][namespace];
} else {
var extended = Element.prototype[namespace].extended;
for (var e in extended) {
extended[e] = extended[e].bind(this);
}
if(!objectCheck)
cache[Element.prototype.constructor.name] = {};
cache[Element.prototype.constructor.name][namespace] = extended;
}
return extended;
}});
this[namespace].extended = object;
return this;
}});
// Extend the Element prototype with an attr function in
// the namespace 'namespace' or ofcourse whatever function
Element.prototype.extend('namespace',{
attr: function(name, value) {
if(arguments.length === 1) {
return this.getAttribute(name);
} else {
this.setAttribute(name, value);
return this;
}
}
});
It all looks good when check it out on an actual element, the namespace is there and inside it we find our 'attr' function. We can invoke it like this:
document.querySelector('.a-css-class').namespace().attr('class')
// returns 'a-css-class'
The code could be refactored further to dynamically extend all sorts of objects. However I'm curious, what could this mean for performance, does this experiment make sense? The main question, is this any better than extending directly?
EDIT (based on Bergi's comments regarding performance):
It would be possible to cache the created function in the outer function. Let's see if I can come up with an implementation.
EDIT 2:
Added a simple caching function to make sure not all namespaced methods are create each en every invocation.
EDIT 3:
The updated code. In an attempt to make extending native object safer, the following code was produced. It might prevent naming collision. Thanks #Bergi:
/**
* Extend a (NATIVE) object with a namespace. See below for an example
*/
Object.defineProperty(Object.prototype, 'extend', { value: function(namespace, object) {
function Wrapper(that) {
this.that = that;
}
Wrapper.prototype = object;
Object.defineProperty(Object.prototype, namespace, { value: function() {
return new Wrapper(this);
}});
}});
// This example uses the Element object, but it could be any object
Element.prototype.extend('namespace',{
attr: function(name, value) {
if(arguments.length === 1) {
return this.that.getAttribute(name);
} else {
this.that.setAttribute(name, value);
return this;
}
}
});

However I'm curious, what could this mean for performance
Your current code means that whenever you call namespace(), you create a new object and lots of bound functions, which will impact performance quite heavily for large namespaces.
I would recommend to let your namespace method return a wrapper object with an element: this property, which inherits all the methods that can be called on it. You'd use this.element.getAttribute then instead of this.getAttribute:
Element.prototype.extend = function(namespace, object) {
function Wrapper(el) {
this.element = el;
}
Wrapper.prototype = object;
Element.prototype[namespace] = function() {
return new Wrapper(this);
};
};
The main question, is this any better than extending directly?
Not much. You still are defining extend and namespace properties on the Element.prototype, and for these two properties all the arguments against extending the DOM are still valid. You might lower the risk of collisions with more common names (attr), but it's not better than just defining a namespace_attr method.

Related

Prototype sub objects this doesn't refer to base object

I was trying to make my code more readable and ran into an oddity with my build and events objects that I attached to the prototype. Is there a way to do this?
function Something(){
this.$container = $('<div>');
return this;
}
Something.prototype.build = {
list: function(){
this.$container.append(...);
}
}
Currently what happens is when build.list calls this, this refers to the build object, not the Something object.
I can't quite figure out another way of using it this way without renaming everything to buildList, buildComponentArray, and etc. Semantics maybe.
This is a possible solution
function Something(){
this.$container = "<div></div>";
//this creates a new object in the prototype chain for every instance
this.build = Object.create(this.build);
for (var prop in this.build) {
if (this.build.hasOwnProperty(prop) && typeof this.build[prop] === "function") {
this.build[prop] = this.build[prop].bind(this);
}
}
return this;
}
Something.prototype.build = {
list: function(){
console.log(this.$container);
}
}
Basically you'll bind every function in your this.build object to a function bound to this. You could extract this in a utility function and then bind all nested object you need to this. I suppose it must be possible too by manipulating/build the prototype chain but I haven't found it.
I know most of you recommend refactoring, but I thought to put this out there just so you have a complete set of solutions.
Edit
As pointed out, you need to move the build interface to your constructor in order to have this bound correctly. This solution is just a way to do this without having to move your code.
solution without using Object.create
This one is cleaner and more explicitly states what it does without messing with prototypes.
function Something(){
this.$container = "<div></div>";
var build = this.build;
this.build = {};
for (var prop in build) {
if (build.hasOwnProperty(prop) && typeof build[prop] === "function") {
this.build[prop] = build[prop].bind(this);
}
}
return this;
}
Something.prototype.build = {
list: function(){
console.log(this.$container);
}
}

update instance of a class that contains an onclick function [duplicate]

I'm not sure of the best approach for handling scoping of "this" in TypeScript.
Here's an example of a common pattern in the code I am converting over to TypeScript:
class DemonstrateScopingProblems {
private status = "blah";
public run() {
alert(this.status);
}
}
var thisTest = new DemonstrateScopingProblems();
// works as expected, displays "blah":
thisTest.run();
// doesn't work; this is scoped to be the document so this.status is undefined:
$(document).ready(thisTest.run);
Now, I could change the call to...
$(document).ready(thisTest.run.bind(thisTest));
...which does work. But it's kinda horrible. It means that code can all compile and work fine in some circumstances, but if we forget to bind the scope it will break.
I would like a way to do it within the class, so that when using the class we don't need to worry about what "this" is scoped to.
Any suggestions?
Update
Another approach that works is using the fat arrow:
class DemonstrateScopingProblems {
private status = "blah";
public run = () => {
alert(this.status);
}
}
Is that a valid approach?
You have a few options here, each with its own trade-offs. Unfortunately there is no obvious best solution and it will really depend on the application.
Automatic Class Binding
As shown in your question:
class DemonstrateScopingProblems {
private status = "blah";
public run = () => {
alert(this.status);
}
}
Good/bad: This creates an additional closure per method per instance of your class. If this method is usually only used in regular method calls, this is overkill. However, if it's used a lot in callback positions, it's more efficient for the class instance to capture the this context instead of each call site creating a new closure upon invoke.
Good: Impossible for external callers to forget to handle this context
Good: Typesafe in TypeScript
Good: No extra work if the function has parameters
Bad: Derived classes can't call base class methods written this way using super.
Bad: The exact semantics of which methods are "pre-bound" and which aren't create an additional non-typesafe contract between your class and its consumers.
Function.bind
Also as shown:
$(document).ready(thisTest.run.bind(thisTest));
Good/bad: Opposite memory/performance trade-off compared to the first method
Good: No extra work if the function has parameters
Bad: In TypeScript, this currently has no type safety
Bad: Only available in ECMAScript 5, if that matters to you
Bad: You have to type the instance name twice
Fat arrow
In TypeScript (shown here with some dummy parameters for explanatory reasons):
$(document).ready((n, m) => thisTest.run(n, m));
Good/bad: Opposite memory/performance trade-off compared to the first method
Good: In TypeScript, this has 100% type safety
Good: Works in ECMAScript 3
Good: You only have to type the instance name once
Bad: You'll have to type the parameters twice
Bad: Doesn't work with variadic parameters
Another solution that requires some initial setup but pays off with its invincibly light, literally one-word syntax is using Method Decorators to JIT-bind methods through getters.
I've created a repo on GitHub to showcase an implementation of this idea (it's a bit lengthy to fit into an answer with its 40 lines of code, including comments), that you would use as simply as:
class DemonstrateScopingProblems {
private status = "blah";
#bound public run() {
alert(this.status);
}
}
I haven't seen this mentioned anywhere yet, but it works flawlessly. Also, there is no notable downside to this approach: the implementation of this decorator -- including some type-checking for runtime type-safety -- is trivial and straightforward, and comes with essentially zero overhead after the initial method call.
The essential part is defining the following getter on the class prototype, which is executed immediately before the first call:
get: function () {
// Create bound override on object instance. This will hide the original method on the prototype, and instead yield a bound version from the
// instance itself. The original method will no longer be accessible. Inside a getter, 'this' will refer to the instance.
var instance = this;
Object.defineProperty(instance, propKey.toString(), {
value: function () {
// This is effectively a lightweight bind() that skips many (here unnecessary) checks found in native implementations.
return originalMethod.apply(instance, arguments);
}
});
// The first invocation (per instance) will return the bound method from here. Subsequent calls will never reach this point, due to the way
// JavaScript runtimes look up properties on objects; the bound method, defined on the instance, will effectively hide it.
return instance[propKey];
}
Full source
The idea can be also taken one step further, by doing this in a class decorator instead, iterating over methods and defining the above property descriptor for each of them in one pass.
Necromancing.
There's an obvious simple solution that doesn't require arrow-functions (arrow-functions are 30% slower), or JIT-methods through getters.
That solution is to bind the this-context in the constructor.
class DemonstrateScopingProblems
{
constructor()
{
this.run = this.run.bind(this);
}
private status = "blah";
public run() {
alert(this.status);
}
}
You can write an autobind method to automatically bind all functions in the constructor of the class:
class DemonstrateScopingProblems
{
constructor()
{
this.autoBind(this);
}
[...]
}
export function autoBind(self)
{
for (const key of Object.getOwnPropertyNames(self.constructor.prototype))
{
const val = self[key];
if (key !== 'constructor' && typeof val === 'function')
{
// console.log(key);
self[key] = val.bind(self);
} // End if (key !== 'constructor' && typeof val === 'function')
} // Next key
return self;
} // End Function autoBind
Note that if you don't put the autobind-function into the same class as a member function, it's just autoBind(this); and not this.autoBind(this);
And also, the above autoBind function is dumbed down, to show the principle.
If you want this to work reliably, you need to test if the function is a getter/setter of a property as well, because otherwise - boom - if your class contains properties, that is.
Like this:
export function autoBind(self)
{
for (const key of Object.getOwnPropertyNames(self.constructor.prototype))
{
if (key !== 'constructor')
{
// console.log(key);
let desc = Object.getOwnPropertyDescriptor(self.constructor.prototype, key);
if (desc != null)
{
if (!desc.configurable) {
console.log("AUTOBIND-WARNING: Property \"" + key + "\" not configurable ! (" + self.constructor.name + ")");
continue;
}
let g = desc.get != null;
let s = desc.set != null;
if (g || s)
{
var newGetter = null;
var newSetter = null;
if (g)
newGetter = desc.get.bind(self);
if (s)
newSetter = desc.set.bind(self);
if (newGetter != null && newSetter == null) {
Object.defineProperty(self, key, {
get: newGetter,
enumerable: desc.enumerable,
configurable: desc.configurable
});
}
else if (newSetter != null && newGetter == null) {
Object.defineProperty(self, key, {
set: newSetter,
enumerable: desc.enumerable,
configurable: desc.configurable
});
}
else {
Object.defineProperty(self, key, {
get: newGetter,
set: newSetter,
enumerable: desc.enumerable,
configurable: desc.configurable
});
}
continue; // if it's a property, it can't be a function
} // End if (g || s)
} // End if (desc != null)
if (typeof (self[key]) === 'function')
{
let val = self[key];
self[key] = val.bind(self);
} // End if (typeof (self[key]) === 'function')
} // End if (key !== 'constructor')
} // Next key
return self;
} // End Function autoBind
In your code, have you tried just changing the last line as follows?
$(document).ready(() => thisTest.run());

In MooTools, what's the difference between .implement and .prototype

implement change prototype, so why not just directory change it with 'some class'.prototype..., It seems very useless or palaver
There are two aspects to implement. In a Class context and on Objects (Types/Natives).
Common benefits
Common between them is, they are API. Because it's API, MooTools can add ways that ensure that you don't (accidentally) overwrite prototype methods that are protected on various Native types. See this bit which forces protection for many native methods: https://github.com/mootools/mootools-core/blob/master/Source/Core/Core.js#L238-282
Also, implement is overloaded - which means you can pass on an object that implements more than one method at the same time, rather than break and have a new line for each prototype call.
Function Methods in Classes are wrapped.
These decorators are available:
Function.implement({
hide: function(){
this.$hidden = true;
return this;
},
protect: function(){
this.$protected = true;
return this;
}
});
This means you can do
Obj.implement({
foo: foo.hide(),
bar: bar.protect()
});
This allows you to have non-wrapped methods via .hide() to add properties that are not wrapped:
Number.prototype.$family = function(){
return isFinite(this) ? 'number' : 'null';
}.hide();
.protect() is used by Class, see below.
This does not mean you can't do Number.prototype.$family = somethingElse - you can.
Specifics to Class
When using implement on a class constructor, notice reference to $hidden and call to wrap():
var implement = function(key, value, retain){
if (Class.Mutators.hasOwnProperty(key)){
value = Class.Mutators[key].call(this, value);
if (value == null) return this;
}
if (typeOf(value) == 'function'){
if (value.$hidden) return this;
this.prototype[key] = (retain) ? value : wrap(this, key, value);
} else {
Object.merge(this.prototype, key, value);
}
return this;
};
This means when you pass a function, it will get wrapped automatically - wrapping enables you to have private methods via the .protect() decorator or special ones via .hide()
It also supports Class Mutators - you should check this but it's ability to define special keys that can modify the constructor, as opposed to just add to the prototype.
Once again, you can easily do:
ClassConstructor.prototype.foo = someFn;
And this will work.
// but:
ClassConstructor.prototype.foo = someFn.protect();
// however...
instanceOfClassconstructor.foo(); // works also.
see this:
// generic method.
var foo = function() {
console.log('hi');
};
var ClassConstructor = new Class({});
// implement the foo method as private.
ClassConstructor.implement({
foo: foo.protect()
});
var instance = new ClassConstructor();
// try to call it, will throw.
try {
instance.foo();
}
catch(e) {
console.warn(e);
}
// do it directly on the prototype
ClassConstructor.prototype.foo = foo.protect();
var instance2 = new ClassConstructor();
instance2.foo(); // works.
You can look at MooTools source or inspect a MooTools object in your console to see what it is doing under the hood when implement() is called.
In MooTools 1.4.5, it's doing this:
function (key, value){
if ($type(key) == 'object'){
for (var p in key) this.implement(p, key[p]);
return this;
}
var mutator = Class.Mutators[key];
if (mutator){
value = mutator.call(this, value);
if (value == null) return this;
}
var proto = this.prototype;
switch ($type(value)){
case 'function':
if (value._hidden) return this;
proto[key] = Class.wrap(this, key, value);
break;
case 'object':
var previous = proto[key];
if ($type(previous) == 'object') $mixin(previous, value);
else proto[key] = $unlink(value);
break;
case 'array':
proto[key] = $unlink(value);
break;
default: proto[key] = value;
}
return this;
}
As you can see, there is definitely some extra logic in there. For example, it seems that you can pass objects with corresponding property names for key and value to have it implement add multiple things to the object prototype in one call.
I would use implement() and avoid adding things directly to the prototype chain unless you are very sure you know what you're doing. That extra stuff is there for a reason, no doubt.

Javascript library development scopes and namespaces

we currently learn some Javascript stuff in a course at the university.
For that we implement a library for common tasks like show(), hide(), write and such things.
Currently im running with an implementation like:
var myLib_maker = function () {
/*
private scope
*/
var debuggingMode=true;
var currentElement=null;
/*
end private scope
*/
return {
getElement: function (id) {
var o;
if (typeof id === 'string') { o = document.getElementById(id); }
if (!!(o && o.nodeType !== 1)) {
throw {
name: 'Type Error',
message: 'Wrong node type at id: '+id
}
}
currentElement=o;
return this;
},
getCurrentElement: function() {
console.log(currentElement)
return currentElement;
},
isVisible: function () {
return this.getCurrentElement().style.display.toLowerCase() === "block";
},
show: function () {
this.debug("show "+this.getCurrentElement())
this.getCurrentElement().style.display = "block";
return this;
},
hide: function () {
this.debug("hide "+this.getCurrentElement())
this.getCurrentElement().style.display = "none";
return this;
},
toggle: function() {
this.debug("toggle "+this.getCurrentElement())
this.isVisible() ? this.hide(): this.show();
return this;
},
write: function (content){
this.debug("write to"+this.getCurrentElement().id);
var tg = this.getCurrentElement().tagName.toLowerCase();
if (tg === 'input' || tg === 'textarea') {
currentElement.value = content;
} else {
currentElement.innerHTML = content;
}
return this
},
debug: function (what) {
if (debuggingMode===true){
console.log("[DEBUG] "+what);
}
return this;
}
};
}
var myLib=myLib_maker();
Than I have an external function (for testing) to switch 2 textareas contents.
function switchEditors(id1, id2){
c1=myLib.getElement(id1).getCurrentElement().value;
c2=myLib.getElement(id2).getCurrentElement().value;
myLib.getElement(id1).write(c2)
myLib.getElement(id2).write(c1)
}
I first tried with the following code, which obviously does not work, cause I overwrite my private currentElement and so I write always to id2
function switchEditors(id1, id2){
tmp=myLib.getElement(id1).getCurrentElement().value
myLib.getElement(id1).write(myLib.getElement(id2).getCurrentElement().value)
myLib.getElement(id2).write(tmp)
}
But what I really wanted initially was not using a private currentElement variable.
The first implementation of the write method extended the Element Object
Element.prototype.write= function (content){
var tg = this.tagName.toLowerCase();
if (tg === 'input' || tg === 'textarea') {
this.value = content;
} else {
this.innerHTML = content;
}
return this;
}
and such the getElement function returned
document.getElementById(id)
I want cascading (I hope this is the right word -> I mean the myLib.getElement("myid").show().hide() concatenation thing) and getting direct access to
all Element attributes but we must not use global scope for our library, so I have to encapsulate my library in any way.
So is there an elegant way to use the cascading thing and be able to get a direct access to all attributes on an element object without implementing each method within the global element scope?
Or is my lib desing completely wrong and has to be done totally different.
If so, just tell me, I appreciate any help.
(I tried to figure out how jQuery actually implement these things, but didn't get a real clue how it is done ... too much code ... :) )
I hope I described my wishes and requirements. If not please ask for more specific details.
As you've figured out, the currentElement is shared between calls to getElement. Instead you could create a new instance of myLib-object with Object.create and bind currentElement to that.
getElement: function (id) {
var o, self = Object.create(this);
/* ... */
self.currentElement = o;
return self;
}
And use this.currentElement throughout so that each call uses its own current element.
While Magnar's solution will work with this (singleton) pattern, it is a better idea to avoid creating a whole new object each time you call getElement. There is a reason for creating "classes" instead of singletons.
You can do it like this:
var MyLib_Maker = (function () { // I capitalized the class as a helpful
// convention recommended by Douglas Crockford
// Private static vars
var debuggingMode = true;
var currentElement = null;
// Private static methods
function _myMethod (x, y) { // call below by _myMethod(3,4);
return x * y;
}
// Private instance methods (but only if called properly:
// invoke below by _instMethod.call(this, 3, 4); )
function _instMethod (x, y) {
return this.anInstanceNumber * x * y;
}
// Private instance properties (quite cumbersome but doable if you
// absolutely must--e.g., for classes whose objects need to be clean when iterated)
// See http://brettz9.blogspot.com/2009/02/true-private-instance-variables-in.html
// and http://brettz9.blogspot.com/2009/02/further-relator-enhancements.html
// (put the Relator inside the closure if you don't want it reusable (and public),
// but then your extending classes must be inside the closure too)
function MyLib_Maker (arg1, arg2) {
// I recommend the following check to allow your class to be
// instantiated without the 'new' keyword (as in jQuery/$):
if (!(this instanceof MyLib_Maker)) {
return new MyLib_Maker(arg1, arg2);
}
// Other constructor code here
// ...
}
// Methods added on the prototype benefit from merely
// providing a low-memory reference across all instances;
// this will avoid adding a whole new object unnecessarily
// into memory
MyLib_Maker.prototype.getElement = function () {
// ....
return this; // Keep the chain going (if not public
// properties, you could add a method which also avoids
// extending the chain, like $(el).get() in jQuery
};
return MyLib_Maker;
}()); // We can invoke immediately to wrap up the closure
// Usage example:
var mlm = MyLib_Maker(2, 3).getElement().doSomething();
By the way, what you describe is called chaining; cascading is used in the likes of CSS to indicate that like different waves out of a waterfall, one may write over the other, as you can do by writing rules which override prior ones in CSS.
And it is good you moved away from overriding the Element object because, whatever the browser incompatibilities, this is the worst kind of global namespace pollution because it affects all elements, increasing the chance that another library which depends on that method (or which is careless in overriding the built-in prototypes itself) may get you unexpected results.

OO Javascript: good way to combine prototypal inheritance with private vars?

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());

Categories