Javascript closure and "this" - javascript

My question is... in CallMeLaterTestObj function in the TestObj the "this" is the window object and not TestObj. How can I restructure this so that within the CallMeLater function I don't have to wrap the call function() { v.CallMeLaterTestObj(); } in a closure or using the bind function since it has limited support to newer browsers. Two objectives:
Keeping "this" in function calls within the object
Maintaining a separate value for "value" for each separate object so they don't share the same value.
// Emulating public api, private methods, private variables, public fields.
// New portion of question
Re-written to include binding function and prototypical notation. How do you move the Binding function into a base object that all new objects would get?
This is as close as I can come to getting this to use the best of both worlds. I have no idea what the pitfalls of this approach are though
var BaseObject = function ()
{
_getBinding = function (method)
{
var _self = this;
return function ()
{
_self[method].apply(_self, arguments);
};
};
return {
CallInline: _getBinding
}
}();
var TestObj = function (value)
{
$.extend(this, BaseObject);
// public var
this._value = value;
};
TestObj.prototype = function()
{
var privateVar = false;
// these are private
_giveMe = function () {
return this._value;
},
_callMeLaterTestObj = function () {
console.log('I am ' + this.constructor.name + ' my value is ' + this._value);
};
// public API
return {
GiveMe : _giveMe,
CallMeLaterTestObj : _callMeLaterTestObj
}
}();
function CallMeLater(v, i)
{
setTimeout(v.CallInline('CallMeLaterTestObj'), 10);
}
var V1 = new TestObj(1);
var V2 = new TestObj(2);
var V3 = new TestObj(3);
console.log('V1= ' + V1.GiveMe());
console.log('V2= ' + V2.GiveMe());
console.log('V3= ' + V3.GiveMe());
console.log('---');
V1.CallMeLaterTestObj();
console.log('---');

I think what you're looking for is this:
function TestObj(value) {
var _value = value;
this.giveMe = function() {
return _value;
};
this.callMeLaterTestObj = function() {
console.log('I am ' + this.constructor.name + ' my value is ' + _value);
};
return this;
};
function callMeLater(v, i) {
setTimeout(function() {
v.callMeLaterTestObj();
}, 10);
}
var v1 = new TestObj(1);
var v2 = new TestObj(2);
var v3 = new TestObj(3);
console.log('V1= ' + v1.giveMe());
console.log('V2= ' + v2.giveMe());
console.log('V3= ' + v3.giveMe());
console.log('---');
callMeLater(v1, 1);
callMeLater(v2, 2);
callMeLater(v3, 3);​
To access constructor.name, you need to declare the function with function name() syntax, rather than var name = function() syntax.
To keep private variables and expose a public api, expose the public variables as properties of this in the function.
Be sure to return this from the constructor function to make it work.
It's also good practice to follow the naming convention of CamelCase for class names (of which TestObj is one) and lowerCamelCase for variables / methods / objects / etc. Helps keep things clear as to which variables are instances, and which are Classes.
Test and see the console output expected here.
note
Regarding wrapping v.callMeLaterTestObj() in a closure for the setTimeout, this technique is completely cross-browser compatible. You won't have any issues.
The bind method is newer, although there are many libraries that will shim that for you in older browsers. My personal favourite is underscore.
note 2
You can't call a method on an object in setTimeout without wrapping it in a closure somewhere, however if you want to you can abstract the closure in the Class without using a generic bind function (as provided by Underscore or jQuery and others) you can 'roll your own' in the Class like this:
function TestObj(value) {
var _value = value;
var _self = this;
this.giveMe = function() {
return _value;
};
this.callMeLaterTestObj = function() {
console.log('I am ' + this.constructor.name + ' my value is ' + _value);
};
this.getBinding = function(method) {
var _self = this;
return function() {
_self[method].apply(_self, arguments);
};
};
return this;
};
function callMeLater(v, i) {
setTimeout(v.getBinding('callMeLaterTestObj'), 10);
}
var v1 = new TestObj(1);
var v2 = new TestObj(2);
var v3 = new TestObj(3);
console.log('V1= ' + v1.giveMe());
console.log('V2= ' + v2.giveMe());
console.log('V3= ' + v3.giveMe());
console.log('---');
callMeLater(v1, 1);
callMeLater(v2, 2);
callMeLater(v3, 3);​
explanation:
You need to use some sort of binding because, when you pass the method to setTimeout, you pass it by reference. So all setTimeout sees is a function - not the object it was on, which is why you lose the context of this.
Since setTimeout will therefore execute the function in the default scope - i.e. the browser window - you need a way to get this back, by reference, either through an inline anonymous function, or by returning a closure that uses the apply method to 'reset' this.
note 3
If you wanted to have your own bind method, and not include a library that provides it for you or include it in every class then you can use this one from Underscore, which defers to the native method in newer browsers:
function bind(func, context) {
var bound, args;
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
if (!_.isFunction(func)) throw new TypeError;
args = slice.call(arguments, 2);
return bound = function() {
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
ctor.prototype = func.prototype;
var self = new ctor;
var result = func.apply(self, args.concat(slice.call(arguments)));
if (Object(result) === result) return result;
return self;
};
};
Then use it like this:
function callMeLater(v, i) {
setTimeout(bind(v.callMeLaterTestObj, v), 10);
}
This will work well in all browsers.

No, you can't. That's just the way to do it. Btw, you can easily shim the bind method so that it is available in older browsers, too.
An alternative would be to move the closure into the prototype method, if you know that you always will need to bind the actual function:
TestObj.prototype.getCallMeLaterTestObj = function () {
var that = this;
return function() {
console.log('I am ' + that.constructor.name + ' my value is ' + that._value);
};
};
setTimeout(v.getCallMeLaterTestObj(), 10);
Btw, your prototype has no constructor property so the log will not work as expected.
Your only chance is to avoid the this keyword entirely:
TestObj = function() {
var privateVar = false; // these are private static
function TestObj(value) {
function giveMe() {
return value;
}
function callMeLaterTestObj() {
console.log('I am TestObj my value is ' + giveMe());
}
this._value = value;
this.giveMe = giveMe;
this.callMeLaterTestObj = callMeLaterTestObj;
/* you could do this as well:
return {
_value: value,
giveMe: giveMe,
callMeLaterTestObj: callMeLaterTestObj
}; */
}
return TestObj;
})();
var v = new TestObj;
setTimeout(v.callMeLater, 10);
But this is not very memory-efficient, as it does not use prototypical inheritance at all.

Related

How to insert new function without adding inside the self object in JS

I have the following JS code, how could I insert new function without adding inside the self object?
Function select(selector){
Var self = {
Print: ()=>{},
Delete: ()=>{}
};
Return self;
}
//I want to add new function here so I can call it by using select("something").newFunc()
Is there any ways to do that? I tried something as below, but I'm wondering if there's another way to do it.
After several hours of testing, I tried to assign all the methods inside a variable prototype's method (A), and then set A's prototype back to the variable's prototype. Then I can call it using the variable.
var myScript = function(selector){
return new myScript.prototype.init(selector);
}
var init = myScript.prototype.init = function(selector){
var self = {
//codes
};
return self;
}
init.prototype = myScript.prototype;
(function(mS){
mS.prototype.newFunc = function(){
return "Coding is Fun";
}
})(myScript);
After that, I can use myScript("something").newFunc()
That's what I've tried, please share if you know another way, thanks.
Constructor functions do not require the 'self' object you designed. In your case
You return the self object from the constructor
You use arrow functions that do not change the value of this. Arrow functions are cool, but they are not interchangeable with regular functions (at least not in every case - and inside a constructor function is such a case)
Look at the two constructor functions below (Select1 is based on your code, Select2 is based on a "how to do it"):
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
// adding a self object - arrow functions
function Select1(selector) {
this.selector = selector
var self = {
print: () => {
return 'Select1 print: ' + this.selector
},
delete: () => {
return 'Select1 delete: ' + this.selector
}
}
return self
}
// no self object - regular functions
function Select2(selector) {
this.selector = selector
this.print = function() {
return 'Select2 print: ' + this.selector
}
this.delete = function() {
return 'Select2 delete: ' + this.selector
}
return this
}
// instantiating the two different Objects
let select1 = new Select1('selector1')
let select2 = new Select2('selector2')
// calling the print method on both Objects
console.log(select1.print())
console.log(select2.print())
// logging both objects
console.log(select1)
console.log(select2)
// modifying the prototype of the constructor functions
// modifying Select1.self's prototype would throw an error
/*Select1.prototype.self.newFunc = () => {
return 'Select1 newFunc: ' + this.selector
}*/
Select1.prototype.newFunc = function() {
return 'Select1 newFunc: ' + this.selector
}
Select2.prototype.newFunc = function() {
return 'Select2 newFunc: ' + this.selector
}
// logging the new function
// logging select1.newFunc() would throw an error, as you return 'self', that's not modified
// console.log(select1.newFunc())
console.log(select2.newFunc())
// logging the modified object
console.log(select1)
console.log(select2)
BUT
You should use correct indentation - code is much more readable that way
You should follow naming and casing conventions, so others can quickly see what is what in your code (constructor functions begin with a capital letter, but other reserved words do not (so casing is important too)
USAGE
And if you want to use it like myScript('selector').myFunc(), then you need to wrap it in another function (like you did in your second code sample):
function Select2(selector) {
this.selector = selector
this.print = function() {
return 'Select2 print: ' + this.selector
}
this.delete = function() {
return 'Select2 delete: ' + this.selector
}
return this
}
function myFunc(selector) {
return new Select2(selector)
}
console.log(myFunc('s1').print())
console.log(myFunc('s2').print())
If you want to be able to set the selector, then you need a set() function:
function Select2(selector) {
this.selector = selector
this.print = function() {
return 'Select2 print: ' + this.selector
}
this.delete = function() {
return 'Select2 delete: ' + this.selector
}
// this.setSelector is the set() function
this.setSelector = function(s) {
this.selector = s
}
return this
}
function myFunc(selector) {
return new Select2(selector)
}
// instantiating Select2
const selector2 = myFunc('s1')
console.log(selector2.print()) // expected: s1
// setting the 'selector' of the instantiated
// Select2 Object to a new value
selector2.setSelector('s2')
console.log(selector2.print()) // expected: s2

A native way of adding custom JavaScript functions into a method-calls chain

I would like to known if there is a native way of doing this :
Object.prototype.chain = function(f) { return f.call(this) }
function fun1() {
doSomethingWithObject(this)
return this
}
function fun2() {
doSomethingElse(this)
return this
}
someObject
.method1('something')
.method2()
.chain(checkSomething() ? fun1 : fun2)
.method3()
But I do not feel like changing the prototype of Object. Is there a way to do this without modifying the prototype of Objects or the other constructors that I use (and am not the developer of)
Edits :
I feel I do not explain very well, so let' add some details :
What I would like to do is to use some APIs I do not define. someObject is defined like the following, with chainable methods :
var someObject = {
method1: function(val) {
// do something
return this
},
method2: function() {
// do something
return this
},
method3: function() {
// do something
return this
}
}
Now imagine I cannot change this code, because this object is from a library, and so I don't want to. Then, imagine that I would like to chain methods and some custom functions (see my first snippet) for many more different objects. The simplest thing to do is to attach a chain method to Object.prototype.
But I think that it could result in conflicts in the future. I am looking for a way to do the same thing without touching the prototype.
I'm surprised there are no answers to this to be honest.
There are many ways to natively introduce chaining. I like to use the revealing module pattern.
So I create a basic model (Go ahead and chuck this in your chrome of firefox console)
var Dog = function(name) {
var self = this;
this.name = name;
var core = {
getName:function(){
return self.name;
}
};
this.movement = function(){ //this function will be exposed including its returned functions for chaining
console.log(self.name + " is getting restless... ");
var jump = function(){
console.log(self.name + " jumps around ");
return this //returns the movement scope
};
var run = function(){
console.log(self.name + " has decided to run");
return this //returns the movement scope
};
return {
jump:jump,
run:run
};
}
console.log("A Pup has been born, we shall call him... " + name);
return{
movement:self.movement //only .movement is exposed to the outside world
};
}
Now create a new dog using var p = new Dog("doggyName");
now, you can chain functions. Try:
p.movement().jump().run().jump().run();
You should get the console logged text that corresponds with each function.
By returning the scope of this after executing your movement function you expose the additional functions that are returned in that scope (see the comments in the code). These can then be chained onto the end of your current function provided they are in the same scope. This allows you to scope specific parts of your code. For example with this dog, all movement is scoped to self.movement, you could have all eating scoped to self.eat and so on
Read up on the revealing module pattern. Though this is not the only way to do it.
The wrapper is something that will wrap any object to make it compatible with "chaining" and will add another chain method that will allow you to plug external functions and still get the chaining.
Check this example:
function myObj() {
this.state = {
a: 1
};
this.method1 = function () {
console.log("1");
}
this.method2 = function () {
console.log("2");
}
this.method3 = function () {
console.log("3");
}
this.method4 = function () {
console.log(this.state);
}
}
function objectChainWrapper(obj) {
this.chain = function (fn) {
fn.call(obj);
return this;
}
for (var prop in obj) {
if (obj.hasOwnProperty(prop) && typeof obj[prop] == 'function') {
this[prop] = (function (methodName) {
return function () {
obj[methodName].call(obj);
return this;
}
}(prop))
}
}
}
var obj = new myObj();
var wrapper = new objectChainWrapper(obj);
var chainMethod = function(){ console.log('chain') };
var chainMethodState = function(){ console.log(this.state) };
wrapper.method1().method2().chain(chainMethodState).method3().chain(chainMethod).method4();
JSFIDDLE.
To "plug" an unbound function into the object's method chain you can assign it to a property and call that:
function fn() {
document.write('hi ');
return this;
}
someObj = {
meth1: function() {
document.write('meth1 ');
return this;
},
meth2: function() {
document.write('meth2 ');
return this;
}
}
someObj
.meth1()
[someObj._=fn, '_']()
.meth2()
This doesn't look very pretty if you ask me. A more readable option is to add the chain method on the fly, like:
function chainable(obj) {
obj.chain = function(fn) {
return fn.call(this);
}
return obj;
}
chainable(someObj).meth1().chain(fn).meth2()

Javascript OOP - private/public methods [duplicate]

To make a JavaScript class with a public method I'd do something like:
function Restaurant() {}
Restaurant.prototype.buy_food = function(){
// something here
}
Restaurant.prototype.use_restroom = function(){
// something here
}
That way users of my class can:
var restaurant = new Restaurant();
restaurant.buy_food();
restaurant.use_restroom();
How do I create a private method that can be called by the buy_food and use_restroom methods but not externally by users of the class?
In other words, I want my method implementation to be able to do:
Restaurant.prototype.use_restroom = function() {
this.private_stuff();
}
But this shouldn't work:
var r = new Restaurant();
r.private_stuff();
How do I define private_stuff as a private method so both of these hold true?
I've read Doug Crockford's writeup a few times but it doesn't seem like "private" methods can be called by public methods and "privileged" methods can be called externally.
You can do it, but the downside is that it can't be part of the prototype:
function Restaurant() {
var myPrivateVar;
var private_stuff = function() { // Only visible inside Restaurant()
myPrivateVar = "I can set this here!";
}
this.use_restroom = function() { // use_restroom is visible to all
private_stuff();
}
this.buy_food = function() { // buy_food is visible to all
private_stuff();
}
}
Using self invoking function and call
JavaScript uses prototypes and does't have classes (or methods for that matter) like Object Oriented languages. A JavaScript developer need to think in JavaScript.
Wikipedia quote:
Unlike many object-oriented languages, there is no distinction between
a function definition and a method definition. Rather, the distinction
occurs during function calling; when a function is called as a method
of an object, the function's local this keyword is bound to that
object for that invocation.
Solution using a self invoking function and the call function to call the private "method" :
var MyObject = (function () {
// Constructor
function MyObject(foo) {
this._foo = foo;
}
function privateFun(prefix) {
return prefix + this._foo;
}
MyObject.prototype.publicFun = function () {
return privateFun.call(this, ">>");
}
return MyObject;
}());
var myObject = new MyObject("bar");
myObject.publicFun(); // Returns ">>bar"
myObject.privateFun(">>"); // ReferenceError: private is not defined
The call function allows us to call the private function with the appropriate context (this).
Simpler with Node.js
If you are using Node.js, you don't need the IIFE because you can take advantage of the module loading system:
function MyObject(foo) {
this._foo = foo;
}
function privateFun(prefix) {
return prefix + this._foo;
}
MyObject.prototype.publicFun = function () {
return privateFun.call(this, ">>");
}
module.exports= MyObject;
Load the file:
var MyObject = require("./MyObject");
var myObject = new MyObject("bar");
myObject.publicFun(); // Returns ">>bar"
myObject.privateFun(">>"); // ReferenceError: private is not defined
(new!) Native private methods in future JavaScript versions
TC39 private methods and getter/setters for JavaScript classes proposal is stage 3. That means any time soon, JavaScript will implement private methods natively!
Note that JavaScript private class fields already exists in modern JavaScript versions.
Here is an example of how it is used:
class MyObject {
// Private field
#foo;
constructor(foo) {
this.#foo = foo;
}
#privateFun(prefix) {
return prefix + this.#foo;
}
publicFun() {
return this.#privateFun(">>");
}
}
You may need a JavaScript transpiler/compiler to run this code on old JavaScript engines.
PS: If you wonder why the # prefix, read this.
(deprecated) ES7 with the Bind Operator
Warning: The bind operator TC39 proposition is near dead https://github.com/tc39/proposal-bind-operator/issues/53#issuecomment-374271822
The bind operator :: is an ECMAScript proposal and is implemented in Babel (stage 0).
export default class MyObject {
constructor (foo) {
this._foo = foo;
}
publicFun () {
return this::privateFun(">>");
}
}
function privateFun (prefix) {
return prefix + this._foo;
}
You can simulate private methods like this:
function Restaurant() {
}
Restaurant.prototype = (function() {
var private_stuff = function() {
// Private code here
};
return {
constructor:Restaurant,
use_restroom:function() {
private_stuff();
}
};
})();
var r = new Restaurant();
// This will work:
r.use_restroom();
// This will cause an error:
r.private_stuff();
More information on this technique here: http://webreflection.blogspot.com/2008/04/natural-javascript-private-methods.html
In these situations when you have a public API, and you would like private and public methods/properties, I always use the Module Pattern. This pattern was made popular within the YUI library, and the details can be found here:
http://yuiblog.com/blog/2007/06/12/module-pattern/
It is really straightforward, and easy for other developers to comprehend. For a simple example:
var MYLIB = function() {
var aPrivateProperty = true;
var aPrivateMethod = function() {
// some code here...
};
return {
aPublicMethod : function() {
aPrivateMethod(); // okay
// some code here...
},
aPublicProperty : true
};
}();
MYLIB.aPrivateMethod() // not okay
MYLIB.aPublicMethod() // okay
Here is the class which I created to understand what Douglas Crockford's has suggested in his site Private Members in JavaScript
function Employee(id, name) { //Constructor
//Public member variables
this.id = id;
this.name = name;
//Private member variables
var fName;
var lName;
var that = this;
//By convention, we create a private variable 'that'. This is used to
//make the object available to the private methods.
//Private function
function setFName(pfname) {
fName = pfname;
alert('setFName called');
}
//Privileged function
this.setLName = function (plName, pfname) {
lName = plName; //Has access to private variables
setFName(pfname); //Has access to private function
alert('setLName called ' + this.id); //Has access to member variables
}
//Another privileged member has access to both member variables and private variables
//Note access of this.dataOfBirth created by public member setDateOfBirth
this.toString = function () {
return 'toString called ' + this.id + ' ' + this.name + ' ' + fName + ' ' + lName + ' ' + this.dataOfBirth;
}
}
//Public function has access to member variable and can create on too but does not have access to private variable
Employee.prototype.setDateOfBirth = function (dob) {
alert('setDateOfBirth called ' + this.id);
this.dataOfBirth = dob; //Creates new public member note this is accessed by toString
//alert(fName); //Does not have access to private member
}
$(document).ready()
{
var employee = new Employee(5, 'Shyam'); //Create a new object and initialize it with constructor
employee.setLName('Bhaskar', 'Ram'); //Call privileged function
employee.setDateOfBirth('1/1/2000'); //Call public function
employee.id = 9; //Set up member value
//employee.setFName('Ram'); //can not call Private Privileged method
alert(employee.toString()); //See the changed object
}
ES12 Private Methods
You can do this now with es12 private methods. You just need to add a # before the method name.
class ClassWithPrivateMethod {
#privateMethod() {
return 'hello world';
}
getPrivateMessage() {
return #privateMethod();
}
}
I conjured up this: EDIT: Actually, someone has linked to a identical solution. Duh!
var Car = function() {
}
Car.prototype = (function() {
var hotWire = function() {
// Private code *with* access to public properties through 'this'
alert( this.drive() ); // Alerts 'Vroom!'
}
return {
steal: function() {
hotWire.call( this ); // Call a private method
},
drive: function() {
return 'Vroom!';
}
};
})();
var getAwayVechile = new Car();
hotWire(); // Not allowed
getAwayVechile.hotWire(); // Not allowed
getAwayVechile.steal(); // Alerts 'Vroom!'
ES2021 / ES12 - Private Methods
Private method names start with a hash # prefix and can be accessed only inside the class where it is defined.
class Restaurant {
// private method
#private_stuff() {
console.log("private stuff");
}
// public method
buy_food() {
this.#private_stuff();
}
};
const restaurant = new Restaurant();
restaurant.buy_food(); // "private stuff";
restaurant.private_stuff(); // Uncaught TypeError: restaurant.private_stuff is not a function
I think such questions come up again and again because of the lack of understanding of the closures. Сlosures is most important thing in JS. Every JS programmer have to feel the essence of it.
1. First of all we need to make separate scope (closure).
function () {
}
2. In this area, we can do whatever we want. And no one will know about it.
function () {
var name,
secretSkills = {
pizza: function () { return new Pizza() },
sushi: function () { return new Sushi() }
}
function Restaurant(_name) {
name = _name
}
Restaurant.prototype.getFood = function (name) {
return name in secretSkills ? secretSkills[name]() : null
}
}
3. For the world to know about our restaurant class,
we have to return it from the closure.
var Restaurant = (function () {
// Restaurant definition
return Restaurant
})()
4. At the end, we have:
var Restaurant = (function () {
var name,
secretSkills = {
pizza: function () { return new Pizza() },
sushi: function () { return new Sushi() }
}
function Restaurant(_name) {
name = _name
}
Restaurant.prototype.getFood = function (name) {
return name in secretSkills ? secretSkills[name]() : null
}
return Restaurant
})()
5. Also, this approach has potential for inheritance and templating
// Abstract class
function AbstractRestaurant(skills) {
var name
function Restaurant(_name) {
name = _name
}
Restaurant.prototype.getFood = function (name) {
return skills && name in skills ? skills[name]() : null
}
return Restaurant
}
// Concrete classes
SushiRestaurant = AbstractRestaurant({
sushi: function() { return new Sushi() }
})
PizzaRestaurant = AbstractRestaurant({
pizza: function() { return new Pizza() }
})
var r1 = new SushiRestaurant('Yo! Sushi'),
r2 = new PizzaRestaurant('Dominos Pizza')
r1.getFood('sushi')
r2.getFood('pizza')
I hope this helps someone better understand this subject
Personally, I prefer the following pattern for creating classes in JavaScript :
var myClass = (function() {
// Private class properties go here
var blueprint = function() {
// Private instance properties go here
...
};
blueprint.prototype = {
// Public class properties go here
...
};
return {
// Public class properties go here
create : function() { return new blueprint(); }
...
};
})();
As you can see, it allows you to define both class properties and instance properties, each of which can be public and private.
Demo
var Restaurant = function() {
var totalfoodcount = 0; // Private class property
var totalrestroomcount = 0; // Private class property
var Restaurant = function(name){
var foodcount = 0; // Private instance property
var restroomcount = 0; // Private instance property
this.name = name
this.incrementFoodCount = function() {
foodcount++;
totalfoodcount++;
this.printStatus();
};
this.incrementRestroomCount = function() {
restroomcount++;
totalrestroomcount++;
this.printStatus();
};
this.getRestroomCount = function() {
return restroomcount;
},
this.getFoodCount = function() {
return foodcount;
}
};
Restaurant.prototype = {
name : '',
buy_food : function(){
this.incrementFoodCount();
},
use_restroom : function(){
this.incrementRestroomCount();
},
getTotalRestroomCount : function() {
return totalrestroomcount;
},
getTotalFoodCount : function() {
return totalfoodcount;
},
printStatus : function() {
document.body.innerHTML
+= '<h3>Buying food at '+this.name+'</h3>'
+ '<ul>'
+ '<li>Restroom count at ' + this.name + ' : '+ this.getRestroomCount() + '</li>'
+ '<li>Food count at ' + this.name + ' : ' + this.getFoodCount() + '</li>'
+ '<li>Total restroom count : '+ this.getTotalRestroomCount() + '</li>'
+ '<li>Total food count : '+ this.getTotalFoodCount() + '</li>'
+ '</ul>';
}
};
return { // Singleton public properties
create : function(name) {
return new Restaurant(name);
},
printStatus : function() {
document.body.innerHTML
+= '<hr />'
+ '<h3>Overview</h3>'
+ '<ul>'
+ '<li>Total restroom count : '+ Restaurant.prototype.getTotalRestroomCount() + '</li>'
+ '<li>Total food count : '+ Restaurant.prototype.getTotalFoodCount() + '</li>'
+ '</ul>'
+ '<hr />';
}
};
}();
var Wendys = Restaurant.create("Wendy's");
var McDonalds = Restaurant.create("McDonald's");
var KFC = Restaurant.create("KFC");
var BurgerKing = Restaurant.create("Burger King");
Restaurant.printStatus();
Wendys.buy_food();
Wendys.use_restroom();
KFC.use_restroom();
KFC.use_restroom();
Wendys.use_restroom();
McDonalds.buy_food();
BurgerKing.buy_food();
Restaurant.printStatus();
BurgerKing.buy_food();
Wendys.use_restroom();
McDonalds.buy_food();
KFC.buy_food();
Wendys.buy_food();
BurgerKing.buy_food();
McDonalds.buy_food();
Restaurant.printStatus();
See also this Fiddle.
All of this closure will cost you. Make sure you test the speed implications especially in IE. You will find you are better off with a naming convention. There are still a lot of corporate web users out there that are forced to use IE6...
Don't be so verbose. It's Javascript. Use a Naming Convention.
After years of working in es6 classes, I recently started work on an es5 project (using requireJS which is already very verbose-looking). I've been over and over all the strategies mentioned here and it all basically boils down to use a naming convention:
Javascript doesn't have scope keywords like private. Other developers entering Javascript will know this upfront. Therefore, a simple naming convention is more than sufficient. A simple naming convention of prefixing with an underscore solves the problem of both private properties and private methods.
Let's take advantage of the Prototype for speed reasons, but lets not get anymore verbose than that. Let's try to keep the es5 "class" looking as closely to what we might expect in other backend languages (and treat every file as a class, even if we don't need to return an instance).
Let's demonstrate with a more realistic module situation (we'll use old es5 and old requireJs).
my-tooltip.js
define([
'tooltip'
],
function(
tooltip
){
function MyTooltip() {
// Later, if needed, we can remove the underscore on some
// of these (make public) and allow clients of our class
// to set them.
this._selector = "#my-tooltip"
this._template = 'Hello from inside my tooltip!';
this._initTooltip();
}
MyTooltip.prototype = {
constructor: MyTooltip,
_initTooltip: function () {
new tooltip.tooltip(this._selector, {
content: this._template,
closeOnClick: true,
closeButton: true
});
}
}
return {
init: function init() {
new MyTooltip(); // <-- Our constructor adds our tooltip to the DOM so not much we need to do after instantiation.
}
// You could instead return a new instantiation,
// if later you do more with this class.
/*
create: function create() {
return new MyTooltip();
}
*/
}
});
Take any of the solutions that follow Crockford's private or priviledged pattern. For example:
function Foo(x) {
var y = 5;
var bar = function() {
return y * x;
};
this.public = function(z) {
return bar() + x * z;
};
}
In any case where the attacker has no "execute" right on the JS context he has no way of accessing any "public" or "private" fields or methods. In case the attacker does have that access he can execute this one-liner:
eval("Foo = " + Foo.toString().replace(
/{/, "{ this.eval = function(code) { return eval(code); }; "
));
Note that the above code is generic to all constructor-type-privacy. It will fail with some of the solutions here but it should be clear that pretty much all of the closure based solutions can be broken like this with different replace() parameters.
After this is executed any object created with new Foo() is going to have an eval method which can be called to return or change values or methods defined in the constructor's closure, e.g.:
f = new Foo(99);
f.eval("x");
f.eval("y");
f.eval("x = 8");
The only problem I can see with this that it won't work for cases where there is only one instance and it's created on load. But then there is no reason to actually define a prototype and in that case the attacker can simply recreate the object instead of the constructor as long as he has a way of passing the same parameters (e.g. they are constant or calculated from available values).
In my opinion, this pretty much makes Crockford's solution useless. Since the "privacy" is easily broken the downsides of his solution (reduced readability & maintainability, decreased performance, increased memory) makes the "no privacy" prototype based method the better choice.
I do usually use leading underscores to mark __private and _protected methods and fields (Perl style), but the idea of having privacy in JavaScript just shows how it's a misunderstood language.
Therefore I disagree with Crockford except for his first sentence.
So how do you get real privacy in JS? Put everything that is required to be private on the server side and use JS to do AJAX calls.
The apotheosis of the Module Pattern: The Revealing Module Pattern
A neat little extension to a very robust pattern.
If you want the full range of public and private functions with the ability for public functions to access private functions, layout code for an object like this:
function MyObject(arg1, arg2, ...) {
//constructor code using constructor arguments...
//create/access public variables as
// this.var1 = foo;
//private variables
var v1;
var v2;
//private functions
function privateOne() {
}
function privateTwon() {
}
//public functions
MyObject.prototype.publicOne = function () {
};
MyObject.prototype.publicTwo = function () {
};
}
var TestClass = function( ) {
var privateProperty = 42;
function privateMethod( ) {
alert( "privateMethod, " + privateProperty );
}
this.public = {
constructor: TestClass,
publicProperty: 88,
publicMethod: function( ) {
alert( "publicMethod" );
privateMethod( );
}
};
};
TestClass.prototype = new TestClass( ).public;
var myTestClass = new TestClass( );
alert( myTestClass.publicProperty );
myTestClass.publicMethod( );
alert( myTestClass.privateMethod || "no privateMethod" );
Similar to georgebrock but a little less verbose (IMHO)
Any problems with doing it this way? (I haven't seen it anywhere)
edit: I realised this is kinda useless since every independent instantiation has its own copy of the public methods, thus undermining the use of the prototype.
Here's what i enjoyed the most so far regarding private/public methods/members and instantiation in javascript:
here is the article: http://www.sefol.com/?p=1090
and here is the example:
var Person = (function () {
//Immediately returns an anonymous function which builds our modules
return function (name, location) {
alert("createPerson called with " + name);
var localPrivateVar = name;
var localPublicVar = "A public variable";
var localPublicFunction = function () {
alert("PUBLIC Func called, private var is :" + localPrivateVar)
};
var localPrivateFunction = function () {
alert("PRIVATE Func called ")
};
var setName = function (name) {
localPrivateVar = name;
}
return {
publicVar: localPublicVar,
location: location,
publicFunction: localPublicFunction,
setName: setName
}
}
})();
//Request a Person instance - should print "createPerson called with ben"
var x = Person("ben", "germany");
//Request a Person instance - should print "createPerson called with candide"
var y = Person("candide", "belgium");
//Prints "ben"
x.publicFunction();
//Prints "candide"
y.publicFunction();
//Now call a public function which sets the value of a private variable in the x instance
x.setName("Ben 2");
//Shouldn't have changed this : prints "candide"
y.publicFunction();
//Should have changed this : prints "Ben 2"
x.publicFunction();
JSFiddle: http://jsfiddle.net/northkildonan/kopj3dt3/1/
The module pattern is right in most cases. But if you have thousands of instances, classes save memory. If saving memory is a concern and your objects contain a small amount of private data, but have a lot of public functions, then you'll want all public functions to live in the .prototype to save memory.
This is what I came up with:
var MyClass = (function () {
var secret = {}; // You can only getPriv() if you know this
function MyClass() {
var that = this, priv = {
foo: 0 // ... and other private values
};
that.getPriv = function (proof) {
return (proof === secret) && priv;
};
}
MyClass.prototype.inc = function () {
var priv = this.getPriv(secret);
priv.foo += 1;
return priv.foo;
};
return MyClass;
}());
var x = new MyClass();
x.inc(); // 1
x.inc(); // 2
The object priv contains private properties. It is accessible through the public function getPriv(), but this function returns false unless you pass it the secret, and this is only known inside the main closure.
What about this?
var Restaurant = (function() {
var _id = 0;
var privateVars = [];
function Restaurant(name) {
this.id = ++_id;
this.name = name;
privateVars[this.id] = {
cooked: []
};
}
Restaurant.prototype.cook = function (food) {
privateVars[this.id].cooked.push(food);
}
return Restaurant;
})();
Private variable lookup is impossible outside of the scope of the immediate function.
There is no duplication of functions, saving memory.
The downside is that the lookup of private variables is clunky privateVars[this.id].cooked is ridiculous to type. There is also an extra "id" variable.
Wrap all code in Anonymous Function: Then , all functions will be private ,ONLY functions attached to window object :
(function(w,nameSpacePrivate){
w.Person=function(name){
this.name=name;
return this;
};
w.Person.prototype.profilePublic=function(){
return nameSpacePrivate.profile.call(this);
};
nameSpacePrivate.profile=function(){
return 'My name is '+this.name;
};
})(window,{});
Use this :
var abdennour=new Person('Abdennour');
abdennour.profilePublic();
FIDDLE
I prefer to store private data in an associated WeakMap. This allows you to keep your public methods on the prototype where they belong. This seems to be the most efficient way to handle this problem for large numbers of objects.
const data = new WeakMap();
function Foo(value) {
data.set(this, {value});
}
// public method accessing private value
Foo.prototype.accessValue = function() {
return data.get(this).value;
}
// private 'method' accessing private value
function accessValue(foo) {
return data.get(foo).value;
}
export {Foo};
2021 HERE!
This polyfill effectively hides your private properties and methods returning undefined when you try to read your private property and a TypeError when you try to execute your private method thus effectively making them both PRIVATE to the outside but giving you access to them by using your public methods.
If you check it you will see it is very easy to implement. For the most part you don't need to do anything quirky like using Proxy objects, underscore functions (_myprivate), getters or setters. None of that. The only thing required is to place in your constructor that like snippet of code that is aimed to let you expose your public interface to the outside world.
((self) => ({
pubProp: self.pubProp,
// More public properties to export HERE
// ...
pubMethod: self.pubMethod.bind(self)
// More public mehods to export HERE
// Be sure bind each of them to self!!!
// ...
}))(self);
The above code is where the magic happens. It is an IIFE that returns an object with just the properties and methods you want to exposed and bound to the context of the object that was first instantiated.
You can still access your hidden properties and methods but only through your public methods just the way OOP should do.
Consider that part of the code as your module.exports
BTW, this is without using the latest ECMAScript 2022 # addition to the language.
'use strict';
class MyClass {
constructor(pubProp) {
let self = this;
self.pubProp = pubProp;
self.privProp = "I'm a private property!";
return ((self) => ({
pubProp: self.pubProp,
// More public properties to export HERE
// ...
pubMethod: self.pubMethod.bind(self)
// More public mehods to export HERE
// Be sure to bind each of them to self!!!
// ...
}))(self);
}
pubMethod() {
console.log("I'm a public method!");
console.log(this.pubProp);
return this.privMethod();
}
privMethod() {
console.log("I'm a private method!");
return this.privProp
}
}
const myObj = new MyClass("I'm a public property!");
console.log("***DUMPING MY NEW INSTANCE***");
console.dir(myObj);
console.log("");
console.log("***TESTING ACCESS TO PUBLIC PROPERTIES***");
console.log(myObj.pubProp);
console.log("");
console.log("***TESTING ACCESS TO PRIVATE PROPERTIES***");
console.log(myObj.privProp);
console.log("");
console.log("***TESTING ACCESS TO PUBLIC METHODS***");
console.log("1. pubMethod access pubProp ");
console.log("2. pubMethod calls privMethod");
console.log("3. privMethod access privProp");
console.log("")
console.log(myObj.pubMethod());
console.log("");
console.log("***TESTING ACCESS TO PRIVATE METHODS***");
console.log(myObj.privMethod());
Check my gist
Private functions cannot access the public variables using module pattern
Since everybody was posting here his own code, I'm gonna do that too...
I like Crockford because he introduced real object oriented patterns in Javascript. But he also came up with a new misunderstanding, the "that" one.
So why is he using "that = this"? It has nothing to do with private functions at all. It has to do with inner functions!
Because according to Crockford this is buggy code:
Function Foo( ) {
this.bar = 0;
var foobar=function( ) {
alert(this.bar);
}
}
So he suggested doing this:
Function Foo( ) {
this.bar = 0;
that = this;
var foobar=function( ) {
alert(that.bar);
}
}
So as I said, I'm quite sure that Crockford was wrong his explanation about that and this (but his code is certainly correct). Or was he just fooling the Javascript world, to know who is copying his code? I dunno...I'm no browser geek ;D
EDIT
Ah, that's what is all about: What does 'var that = this;' mean in JavaScript?
So Crockie was really wrong with his explanation....but right with his code, so he's still a great guy. :))
In general I added the private Object _ temporarily to the object.
You have to open the privacy exlipcitly in the "Power-constructor" for the method.
If you call the method from the prototype, you will
be able to overwrite the prototype-method
Make a public method accessible in the "Power-constructor": (ctx is the object context)
ctx.test = GD.Fabric.open('test', GD.Test.prototype, ctx, _); // is a private object
Now I have this openPrivacy:
GD.Fabric.openPrivacy = function(func, clss, ctx, _) {
return function() {
ctx._ = _;
var res = clss[func].apply(ctx, arguments);
ctx._ = null;
return res;
};
};
This is what I worked out:
Needs one class of sugar code that you can find here. Also supports protected, inheritance, virtual, static stuff...
;( function class_Restaurant( namespace )
{
'use strict';
if( namespace[ "Restaurant" ] ) return // protect against double inclusions
namespace.Restaurant = Restaurant
var Static = TidBits.OoJs.setupClass( namespace, "Restaurant" )
// constructor
//
function Restaurant()
{
this.toilets = 3
this.Private( private_stuff )
return this.Public( buy_food, use_restroom )
}
function private_stuff(){ console.log( "There are", this.toilets, "toilets available") }
function buy_food (){ return "food" }
function use_restroom (){ this.private_stuff() }
})( window )
var chinese = new Restaurant
console.log( chinese.buy_food() ); // output: food
console.log( chinese.use_restroom() ); // output: There are 3 toilets available
console.log( chinese.toilets ); // output: undefined
console.log( chinese.private_stuff() ); // output: undefined
// and throws: TypeError: Object #<Restaurant> has no method 'private_stuff'
Class({
Namespace:ABC,
Name:"ClassL2",
Bases:[ABC.ClassTop],
Private:{
m_var:2
},
Protected:{
proval:2,
fight:Property(function(){
this.m_var--;
console.log("ClassL2::fight (m_var)" +this.m_var);
},[Property.Type.Virtual])
},
Public:{
Fight:function(){
console.log("ClassL2::Fight (m_var)"+this.m_var);
this.fight();
}
}
});
https://github.com/nooning/JSClass
I have created a new tool to allow you to have true private methods on the prototype
https://github.com/TremayneChrist/ProtectJS
Example:
var MyObject = (function () {
// Create the object
function MyObject() {}
// Add methods to the prototype
MyObject.prototype = {
// This is our public method
public: function () {
console.log('PUBLIC method has been called');
},
// This is our private method, using (_)
_private: function () {
console.log('PRIVATE method has been called');
}
}
return protect(MyObject);
})();
// Create an instance of the object
var mo = new MyObject();
// Call its methods
mo.public(); // Pass
mo._private(); // Fail
You have to put a closure around your actual constructor-function, where you can define your private methods.
To change data of the instances through these private methods, you have to give them "this" with them, either as an function argument or by calling this function with .apply(this) :
var Restaurant = (function(){
var private_buy_food = function(that){
that.data.soldFood = true;
}
var private_take_a_shit = function(){
this.data.isdirty = true;
}
// New Closure
function restaurant()
{
this.data = {
isdirty : false,
soldFood: false,
};
}
restaurant.prototype.buy_food = function()
{
private_buy_food(this);
}
restaurant.prototype.use_restroom = function()
{
private_take_a_shit.call(this);
}
return restaurant;
})()
// TEST:
var McDonalds = new Restaurant();
McDonalds.buy_food();
McDonalds.use_restroom();
console.log(McDonalds);
console.log(McDonalds.__proto__);
I know it's a bit too late but how about this?
var obj = function(){
var pr = "private";
var prt = Object.getPrototypeOf(this);
if(!prt.hasOwnProperty("showPrivate")){
prt.showPrivate = function(){
console.log(pr);
}
}
}
var i = new obj();
i.showPrivate();
console.log(i.hasOwnProperty("pr"));

Trying to simulate class in javascript, but cannot reach variables inside

I am generating a lot of "classes" (actually functions trying to simulate classes as in c# or other object oriented languages), and are looking for the best way to do this.
As you might notice, I also have jQuery available.
This is how all classes are generated at this point:
MyClass = (function() {
function innerClass() {
var self = this;
var myField;
// This function works as the constructor
this.init = function(opts) {
// Arguments to the constructor
var defaultOpts = {
myInitArgument: null
}
opts = $.extend(defaultOpts, opts);
self = this;
// Any custom constructor code is generated here...
}
// A function
this.myFunction = function() {
myField = "Hello World!";
}
// Returns an object with all selected fields and function that should work as "public". Those not mentioned here, will not be visible outside this class.
return {
init: this.init,
myFunction: this.myFunction,
myField: myField,
}
}
return innerClass;
})();
Then I create instances of the class like this:
var myObject = new MyClass();
myObject.init({myInitArgument: 'test'});
My main problem here is that inside the myFunction, "myField" will be set to "Hello World!" if I break in the debugger (i.e. Chrome Developer Tools), but using "myObject.myField" returns undefined.
I made a fiddle if you would like to play around with this sample.
What is the best way to accomplish this problem, and are there perhaps other things you feel of warning me about?
JavaScript is a bit weird when it comes to making classes and objects. IMO, this is the most reliable and readable method of doing it: start with a function that becomes your primitive object (Fruit).
Edit: thanks to #Bergi for pointing out that previous version had vestigial variables, needed to be moved to init().
function Fruit(opts) {
this.init(opts);
}
Now, expand the function, giving it more functions, like init, etc:
Fruit.prototype.init = function(opts) {
// init values go here
this.cost = 0;
this.count = 0;
var that = this; // in the iteration below, we want to refer to our parent
for( k in opts )(function(k, v) {
that[k] = v;
})(k, opts[k]);
}
// now, here's a specialized set of functions that sets properties (price/quant)
// note that they do "return this" - this is so you can conveniently chain
// commands. ex: apple.setPrice(10).setQuantity(5);
Fruit.prototype.setPrice = function(how_much) {
this.cost = how_much;
return(this);
}
Fruit.prototype.setQuantity = function(how_many) {
this.count = how_many;
return(this);
}
Simple function to return a computed value. At this point, once instantiated, the object becomes 'self aware'. Helper functions like this become more readable.
Fruit.prototype.getEarnings = function() {
return( this.cost * this.count );
}
So far we've only setup the abstract structure. To use this, create a new object:
var apple = new Fruit({ genus: 'Malus' });
var orange = new Fruit({ genus: 'Citrus' });
apple.setPrice(1.50).setQuantity(20);
orange.setPrice(1.25).setQuantity(40);
console.info( apple.genus + " will earn you $" + apple.getEarnings() ); // $30
console.info( orange.genus + " will earn you $" + orange.getEarnings() ); // $50
I don't understand what you do that much complicated things to have classes.
var myField and <returned object>.myField are two different variables, modifying one won't change the other.
You can try this (encapsulation):
return {
init: this.init,
myFunction: this.myFunction,
getMyField: function() {return myField;},
}
// ...
$('.console').append('<br />Outside myFunction: ' + myObject.getMyField());
or this (get operator):
return {
init: this.init,
myFunction: this.myFunction,
get myField() {return myField;},
}
// ...
$('.console').append('<br />Outside myFunction: ' + myObject.myField);
This worked fine for me
$('.console').append('Class simulation test:<br />');
// My class
function MyClass() {
var self = this, myField;
// This function works as the constructor
this.init = function(opts) {
// Arguments to the constructor
$('.console').append('<br />Inside myFunction: ' + JSON.stringify(opts));
var defaultOpts = {
myInitArgument: null
}
opts = $.extend(defaultOpts, opts);
//self = this; // no need of this
// Any custom constructor code is generated here...
this.myFunction('Hello from the constructor!');
}
// A function
this.myFunction = function(value) {
this.myField = value; //if you dont use var it will either refer to parent my field or window
$('.console').append('<br />Inside myFunction: ' + this.myField);
};
console.log(JSON.stringify(arguments[0]));
this.init(arguments[0]);
// Returns an object with all selected fields and function that should work as "public". Those not mentioned here, will not be visible outside this class.
return {
myFunction: this.myFunction,
myField: myField,
}
}
// instanciate
var myObject = new MyClass({myInitArgument: 'test'});
// test
myObject.myFunction('Hello from the outside!');
$('.console').append('<br />Outside myFunction: ' + myObject.myField);
I have recently been researching this. I have succeeded, here. The ticker object at that link is a real psuedo class.
var foo = function(args){
this.args = args;
this.whatever = "whatever";
}
foo.prototype.addBar = function(bar){
this.args += bar;
}
foo.prototype.getArgs = function(){
return this.args;
}
var baz = new foo("Hello");
baz.addBar(" Super Man");
var helloStr = baz.getArgs();
//helloStr holds "Hello Super Man"
var what = baz.whatever;
//what holds "whatever"
Simple, no need for inner function, new foo() is the constructor.

Can you dynamically add local variables to a function?

I'm using objects to namespace my JavaScript code. These objects usually contain functions that are called mapping the this-pointer to the object itself using apply. However, I find it inconvenient to use the this-pointer everytime I want to access other functions or properties of the object, especially because in lots of cases I use the new-operator to use function-objects the way you would use classes. I would prefer writing new Line() instead if new this.Line().
It would be great if you could add local variables to a function the way php does it with extract (pseudocode following, it's a little more complicated)
var sample_object = {
"some_function": function() {}
}
test() {
extract(sample_object);
some_function(); // imported from sample_object
}
Is that even possible?
I'm pretty sure eval is your only answer; but you need to be aware that if there's any input outside of your control involved, it isn't safe
function dynamicArgs (varName, varValue) {
eval("var " + varName + "=" + JSON.encode(varValue) );
alert(a);
}
dynamicArgs("a", "value");
You can see the problem with this. How is your function supposed to call the dynamic variable if it doesn't know its name? I hardcoded it to the a variable since I pass it in when calling it, but that's not a good solution. The only solution would be another eval. You really should think about what you need to do and whether this is useful. But it's doable.
Here it is in action: http://jsfiddle.net/mendesjuan/GG3Wu/
function dynamicArgs (varName, varValue) {
eval('var ' + varName + "='" + varValue + "';");
alert(eval(varName));
}
dynamicArgs("f", "Here I am");
Now here's an example like what you're doing, creating a variable from this.MyConstructor
http://jsfiddle.net/mendesjuan/AK3WD/
var ns = {
MyConstructor: function(val) {
this.prop = val;
},
runConstructor: function(val) {
var Ctor = "MyConstructor";
eval('var ' + Ctor + ' = this.' + Ctor);
return new MyConstructor(val);
}
}
alert( ns.runConstructor("Hello").prop );
And here's an example if you wanted to import all the values from an object into the scope;
http://jsfiddle.net/mendesjuan/AK3WD/1/
var ns = {
MyConstructor: function(val) {
this.val= val;
},
anotherProperty: 5,
runConstructor: function(val) {
// Bring all the variables from this into this scope
for (var prop in this) {
eval('var ' + prop + ' = this.' + prop);
}
alert('Testing var anotherProperty: ' + anotherProperty);
var obj = new MyConstructor(val);
alert('Created MyConstructor: its prop is ' + obj.val)
}
}
ns.runConstructor("Hello");
There is controversial with, which has some great applications, but is marginally slow and prone to errors. It throws an error in the strict mode (which you should always opt into) and is going to be deprecated.
var sampleObject = {
someFunction: function() {},
b: 10
}
with (sampleObject) {
typeof someFunction // "function"
var a = 42
var b = 20
}
sampleObject.a // undefined
sampleObject.b // 20
Note, that new variables defined in a with-block won't be added to the object. Nevertheless, if the object already had an eponymous property in it, this property would be modified (thanks, #Rocket).
Just for fun, here's an implementation of extract using eval (which is even more evil than with). You can do unspeakable things with it, for example if your object has properties like sampleObject['x; while (true) { alert("Hi!") }'].
This is how I did it:
function smObject ( object) {
return function () {
function getter(prop) {
return function() {
return this[prop];
}
}
function setter(prop) {
return function(data) {
this[prop]=data;
}
}
for (var o = 0; o < object.length; o++) {
this[object[o]] = {};
this['get' + object[o]] = getter(object[o]);
this['set' + object[o]] = setter(object[o]);
}
}
}
now you can instantiate a function like this:
var fields = ['Name', 'Id', 'Other', '....' ]
var MyFunction = smObject( fields );
var myObject = new MyFunction();
// getter/setters
myObject.setId(5);
myObject.getId(); // will return 5
Regards,
Emanouil

Categories

Resources