Check out this code. This is a very simple JavaScript object which is implemented using Module Pattern (and you can see the live example at this fiddle address)
var human = function() {
var _firstName = '';
var _lastName = ''
return {
get firstName() {
return _firstName;
}, get lastName() {
return _lastName;
}, set firstName(name) {
_firstName = name;
}, set lastName(name) {
_lastName = name;
}, get fullName() {
return _firstName + ' ' + _lastName;
}
}
}();
human.firstName = 'Saeed';
human.lastName = 'Neamati';
alert(human.fullName);
However, IE8 doesn't support JavaScript get and set keywords. You can both test it and see MDN.
What should I do to make this script compatible with IE8 too?
What should I do to make this script compatible with IE8 too?
Change it completely. For example, instead of using accessor properties, use a combination of normal properties and functions:
human.firstName = 'Saeed';
human.lastName = 'Neamati';
alert(human.getFullName());
Somebody else suggested using a DOM object in IE and adding the properties using Object.defineProperty(). While it may work, I'd highly recommend against this approach for several reasons, an example being that the code you write may not be compatible in all browsers:
var human = document.createElement('div');
Object.defineProperty(human, 'firstName', { ... });
Object.defineProperty(human, 'lastName', { ... });
Object.defineProperty(human, 'children', { value: 2 });
alert(human.children);
//-> "[object HTMLCollection]", not 2
This is true of at least Chrome. Either way it's safer and easier to write code that works across all the browsers you want to support. Any convenience you gain from being able to write code to take advantage of getters and setters has been lost on the extra code you wrote specifically targeting Internet Explorer 8.
This is, of course, in addition to the reduction in performance, the fact that you will not be able to use a for...in loop on the object and the potential confusion ensuing when you use a property you thought you defined but was pre-existing on the DOM object.
You cannot (as Andy answered)
The closest alternative would be
var human = function() {
var _firstName = '';
var _lastName = '';
return {
firstName: function() {
if (arguments.length === 1) {
_firstName = arguments[0];
}
else {
return _firstName;
}
},
lastName: function() {
if (arguments.length === 1) {
_lastName = arguments[0];
}
else {
return _lastName;
}
},
fullName: function() {
return _firstName + ' ' + _lastName;
}
};
}();
human.firstName('Saeed');
human.lastName('Neamati');
alert(human.fullName());
Demo at http://jsfiddle.net/gaby/WYjqB/2/
IE8 supports getters and setters on DOM nodes, so if you really want to have getters and setters, you can do this:
var objectForIe8 = $("<div></div>")[0];
Object.defineProperty(objectForIe8, "querySelector", {
get: function() {
return this.name;
},
set: function(val) {
this.name = val+", buddy";
}
});
// notice you can overwrite dom properties when you want to use that property name
objectForIe8.querySelector = "I'm not your guy";
alert(objectForIe8.querySelector);
Note this gives you a somewhat significant performance hit, so I wouldn't use this technique if you need to create thousands of objects like this. But if you're not worried about performance of this particular object, it'll tide you over. And if you couldn't care less about ie8 performance, and just want it to work, use this technique for ie8 only and you're golden : )
Check it on http://robertnyman.com/2009/05/28/getters-and-setters-with-javascript-code-samples-and-demos/
The future, and ECMAScript standardized way, of extending objects in
all sorts of ways is through Object.defineProperty. This is how
Internet Explorer chose to implement getters and setters, but it is
unfortunately so far only available in Internet Explorer 8, and not in
any other web browser. Also, IE 8 only supports it on DOM nodes, but
future versions are planned to support it on JavaScript objects as
well.
You can find the test cases on the same site at http://robertnyman.com/javascript/javascript-getters-setters.html#object-defineproperty
Object.defineProperty(document.body, "description", {
get : function () {
return this.desc;
},
set : function (val) {
this.desc = val;
}
});
document.body.description = "Content container";
Result:
document.body.description = "Content container"
Related
I've been looking into JavaScript frameworks such as Angular and Meteor lately, and I was wondering how they know when an object property has changed so that they could update the DOM.
I was a bit surprised that Angular used plain old JS objects rather than requiring you to call some kind of getter/setter so that it could hook in and do the necessary updates. My understanding is that they just poll the objects regularly for changes.
But with the advent of getters and setters in JS 1.8.5, we can do better than that, can't we?
As a little proof-of-concept, I put together this script:
(Edit: updated code to add dependent-property/method support)
function dependentProperty(callback, deps) {
callback.__dependencies__ = deps;
return callback;
}
var person = {
firstName: 'Ryan',
lastName: 'Gosling',
fullName: dependentProperty(function() {
return person.firstName + ' ' + person.lastName;
}, ['firstName','lastName'])
};
function observable(obj) {
if (!obj.__properties__) Object.defineProperty(obj, '__properties__', {
__proto__: null,
configurable: false,
enumerable: false,
value: {},
writable: false
});
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
if(!obj.__properties__[prop]) obj.__properties__[prop] = {
value: null,
dependents: {},
listeners: []
};
if(obj[prop].__dependencies__) {
for(var i=0; i<obj[prop].__dependencies__.length; ++i) {
obj.__properties__[obj[prop].__dependencies__[i]].dependents[prop] = true;
}
delete obj[prop].__dependencies__;
}
obj.__properties__[prop].value = obj[prop];
delete obj[prop];
(function (prop) {
Object.defineProperty(obj, prop, {
get: function () {
return obj.__properties__[prop].value;
},
set: function (newValue) {
var oldValue = obj.__properties__[prop].value;
if(oldValue !== newValue) {
var oldDepValues = {};
for(var dep in obj.__properties__[prop].dependents) {
if(obj.__properties__[prop].dependents.hasOwnProperty(dep)) {
oldDepValues[dep] = obj.__properties__[dep].value();
}
}
obj.__properties__[prop].value = newValue;
for(var i=0; i<obj.__properties__[prop].listeners.length; ++i) {
obj.__properties__[prop].listeners[i](oldValue, newValue);
}
for(dep in obj.__properties__[prop].dependents) {
if(obj.__properties__[prop].dependents.hasOwnProperty(dep)) {
var newDepValue = obj.__properties__[dep].value();
for(i=0; i<obj.__properties__[dep].listeners.length; ++i) {
obj.__properties__[dep].listeners[i](oldDepValues[dep], newDepValue);
}
}
}
}
}
});
})(prop);
}
}
return obj;
}
function listen(obj, prop, callback) {
if(!obj.__properties__) throw 'object is not observable';
obj.__properties__[prop].listeners.push(callback);
}
observable(person);
listen(person, 'fullName', function(oldValue, newValue) {
console.log('Name changed from "'+oldValue+'" to "'+newValue+'"');
});
person.lastName = 'Reynolds';
Which logs:
Name changed from "Ryan Gosling" to "Ryan Reynolds"
The only problem I see is with defining methods such as fullName() on the person object which would depend on the other two properties. This requires a little extra markup on the object to allow developers to specify the dependency.
Other than that, are there any downsides to this approach?
JsFiddle
advent of getters and setters in JS 1.8.5 - are there any downsides to this approach?
You don't capture any property changes apart from the observed ones. Sure, this is enough for modeled entity objects, and for anything else we could use Proxies.
It's limited to browsers that support getters/setters, and maybe even proxies. But hey, who does care about outdated browsers? :-) And in restricted environments (Node.js) this doesn't hold at all.
Accessor properties (with getter and setter) are much slower than real get/set methods. Of course I don't expect them to be used in critical sections, and they can make code looking much fancier. Yet you need to keep that in the back of your mind. Also, the fancy-looking code can lead to misconceptions - normally you would expect property assignment/accessing to be a short (O(1)) operation, while with getters/setters there might be a lot of more happening. You will need to care not forgetting that, and the use of actual methods could help.
So if we know what we are doing, yes, we can do better.
Still, there is one huge point we need to remember: the synchronity/asynchronity (also have a look at this excellent answer). Angular's dirty checking allows you to change a bunch of properties at once, before the event fires in the next event loop turn. This helps to avoid (the propagation of) semantically invalid states.
Yet I see the synchronous getters/setters as a chance as well. They do allow us to declare the dependencies between properties and define the valid states by this. It will automatically ensure the correctness of the model, while we only have to change one property at a time (instead of changing firstName and fullName all the time, firstName is enough). Nevertheless, during dependency resolving that might not hold true so we need to care about it.
So, the listeners that are not related to the dependencies management should be fired asynchronous. Just setImmediate their loop.
By OO I mean classical OO. I keep going back and forth between defining my "classes" ( javascript does not have traditional classes ) using the module pattern to provide privacy and using object literals to create a collection of "public statics".
I have no guiding force when I create "classes" that lets me determine what type of organization to use. Well, besides the fact that my code passes both jshint and jslint w/ no options set.
I'm working w/ about 1500 lines of code so I need a "guiding force" before the code becomes un-manageable and I have to scrap it.
I am well aware of the different ways to write "classes" in JavaScript. Those taught by JavaScript Web Applications written by Alex MacCaw as well as the numerous ways listed here on SO.
However, application wise, I just don't know what method to use.
The simplest seems to be a collection of methods and variables in an object literal like this:
var public_statics = {
public_func: function () {},
public_var: "hello"
}
and the most complicated seems to be - an IIFE.
(function(){
var private_var;
function private_func(){
}
})();
How do I know which one to use or the multitude of in-between variations?
For a concrete example: How about for a controller in the MVC.
Currently ( and some what randomly chosen), I implement a controller like this:
var Co = {};
Co.Controller = function(){
// 'classes' from Mo are called here
// 'classes' from Su are called here
}
then I tack on other Control related method to Co.
How do I choose what style of OO to use?
Updated
My library is currently divided between 4 namespaces:
var Mo = {},
Vi = {},
Co = {},
Su = {};
Model, View, and Controller should be self-explanatory and (Su)pport is for all "classes" not contained in the MVC, for example DOM access, Effects, Debug code, etc.
What OO style should I use to further organize this library/code?
Controller "Class" example:
/**
** Controller
*/
Co.Controller = function (o_p) {
var o_p_string_send;
Su.time();
o_p = Mo[o_p.model].pre(o_p);
if (o_p.result !== 'complete') {
o_p_string_send = JSON.stringify(o_p);
Su.time();
//Su.log(o_p_string_send);
Co.serverCall('pipe=' + o_p_string_send, function (o_p_string_receive) {
Su.time();
//Su.log(o_p_string_receive);
o_p.server = JSON.parse(o_p_string_receive);
Mo[o_p.model].post(o_p);
Su.time(true);
Su.log('Server time: [' + o_p.server.time + ']');
});
}
};
IFFEs are often confusing to read and personally, I have no idea why they have become so mainstream. I think code should be easy to read and concise. Attempting to simulate language behavior that is not part of the language specification is often-times a very dumb idea.
For example, JavaScript does not support multiple inheritance, polymorphism, or many other interesting paradigms. So a lot of times, we see people trying to create these crazy ways of sorta'-kinda' having polymorphism or private members, etc in JS. I think this is a mistake.
I'm currently working as a sort of hobby project on a high-performance JS data structures library (I'm trying to outperform Google's closure and a bunch of others). Coming from a C++ and Java background, I always like to make stuff classes and I like inheritance, etc, etc. Let me share some code-snippets with you. At first, I thought I was being clever because I was writing stuff like this:
function __namespace(n, v) {
return {"meta":{"namespace":n,"version":v}};
}
var FJSL = FJSL == undefined ? new __namespace("Fast JavaScript Library", 0.1) : FJSL;
__using = function(parent, child) {
clazz = new child();
clazz.super = new parent();
if (clazz.super == undefined) return clazz;
for (a in clazz.super) {
for (b in clazz) {
if (a == "constructor" || b == "constructor") continue;
if (clazz[b] === clazz.super[a]) continue;
if (a == b && typeof clazz[b] != typeof clazz.super[a]) throw "Typesafety breached on '" + a + "' while trying to resolve polymorphic properties.";
if (a == b && typeof clazz[b] == typeof clazz.super[a]) {
clazz["_"+a] = clazz.super[a];
} else if (clazz[a] == undefined) {
clazz[a] = clazz.super[a];
}
}
}
return clazz;
};
And I was using it like so (in the example of a simple Queue):
FJSL.Array = function() {
this.data = [];
this.contains = function(idx, element) {
for (var i = idx; i < this.data.length; i++) {
if (this.data[i] === element)
return i;
}
return -1;
}
this.size = function() {
return this.data.length;
}
}
FJSL.Queue = function() {
return __using(FJSL.Array,
function() {
this.head = 0;
this.tail = 0;
this.enqueue = function(element) {
this.data[this.tail++] = element;
};
this.dequeue = function() {
if (this.tail == this.head)
return undefined;
return this.data[this.head++];
};
this.peek = function() {
return this.data[this.head];
};
this.size = function() {
return this.tail - this.head;
};
this.contains = function(element) {
return this._contains(this.head, element);
};
}
)};
You'll note how I'm sort of faking inheritance (a Queue uses an Array, har har, I'm clever). However, this is absolutely insane to a) read and b) understand. I couldn't help but be reminded of this meme:
Let me show you functionally equivalent code without me trying to do all this fancy pre- and post-processing:
FJSL.Queue = function(opts) {
this.options = opts;
this.head = 0;
this.tail = 0;
this.data = [];
};
FJSL.Queue.prototype = {
add : function(element) {
this.data[this.tail++] = element;
},
enqueue : function(element) {
this.data[this.tail++] = element;
},
dequeue : function() {
if (this.tail == this.head) {
return undefined;
}
return this.data[this.head++];
},
peek : function() {
return this.data[this.head];
},
size : function() {
return this.tail - this.head;
},
contains : function(element) {
// XXX: for some reason a for : loop doesn't get JIT'ed in Chrome
for (var i = this.head; i < this.data.length; i++) {
if (this.data[i] === element) {
return true;
}
}
return false;
},
isEmpty : function() {
if (size) {
return true;
}
return false
},
clear : function() {
this.data = [];
}
};
Obviously, I'd have to duplicate the prototype constructor for any other structures that may use an array, but what I'm trying to accomplish is so much clearer, even a novice JS programmer can tell what's going on. Not only that, but if people want to modify the code, they know exactly where to go and what to do.
My suggestion is don't get caught up in the insanity of trying to make JS behave like C++ or Java. It's never going to. And yeah, you can fake inheritance and private/public/protected members, but JS was never intended for that. I think the repercussion of having this kind of bloated code (that attempts to simulate non-standard behavior) is very taxing on high-performance web-apps and their ilk.
In short, I suggest using an object literal:
var public_statics = {
public_func: function () {},
public_var: "hello"
}
It's easy to understand, easy to modify, and easy to extend. If your system is brittle enough to crash and burn if someone accidentally changes some "private" variable, you simply need to document it.
I personally prefer the IIFE simply because you can make methods private. Otherwise, you will have to do some sort of weird convention with underscores.
Furthermore, stylitically, if you encapsulate it within a function, you have the option of making semicolons - its plain old javascript. Requiring each line in the object literal to end with a comma seems funny to me.
Because JavaScript the language itself is implemented in many different ways, i.e. it is different for each browser, you already have to begin with inconsistency.
JavaScript does not directly support classical inheritance. ( It supports prototypical inheritance ).
For my needs I will choose not to implement classical inheritance. This is not ideal b.c. classical inheritance allows you to directly implement best practice OO - encapsulation, inheritance, and polymorphism.
However I prefer to wait until the language directly supports OO via classical inheritance or similar.
In the mean time I will just use the basic prototypical inheritance to help enable code re-use.
I don't really know how to explain this but I'll show you code and tell you what I'd like to achieve.
Let's say I make a quick object:
var test = {};
And then I set a property to it: (I insist on the syntax, it mustn't use any function as the setter)
test.hello = 'world';
Pretty simple, eh? Now I'd like to add a function to that object that would get called everytime a new property gets set. Like this:
var test = {
newPropertyHasBeenSet: function(name){
console.log(name + 'has been set.');
}
};
test.hello = 'world';
// Now newPropertyHasBeenSet gets called with 'hello' as an argument.
// hello has been set.
I don't know if it's possible, but that would be quite amazing. Anyone has an idea of how to achieve so?
EDIT: I'd like also to be able to do the same for property get (so test.hello would call get('hello') for example).
EDIT2: This is for server-side javascript using node.js.
Thanks a lot and have a nice day!
try this example in chrome (as mentioned in previous comments it uses ES6 Proxy):
var p = new Proxy(
{},
{
get: function(obj, name) {
console.log('read request to ' + name + ' property');
if (name == 'test_test') return 1234;
else return 'Meh';
},
set: function(obj, name, value) {
console.log('write request to ' + name + ' property with ' + value + ' value');
},
}
);
console.log(p.test_test);
console.log(p.test);
p.qqq = 'test';
result:
read request to test_test property
1234
read request to test property
Meh
write request to qqq property with test value
var test = {};
Object.defineProperty(test, "hello", {
get : function () {
return this._hello;
},
set : function (val) {
alert(val);
this._hello = val;
}
});
test.hello = "world";
Something like that. But it will not work on old browsers.
You can find more options here: http://robertnyman.com/javascript/javascript-getters-setters.html
If you really insist on keeping the test.hello = "world" syntax to detect changes for existing properties, then you'll have to wait a few years for Object.watch to become part of the next EcmaScript standard.
Luckily, you can do the same in EcmaScript 5 using Object.defineProperty. Eli Grey made a nice Object.watch polyfill which you can call like this:
var test = {};
test.watch("hello", function(propertyName, oldValue, newValue) {
console.log(propertyName + " has been set to " + newValue);
});
test.hello = "world"; // triggers the watch handler
You could modify his code to trigger a different handler inside the getter as well, so you can detect property accesses.
Unfortunately, browser support is limited to modern browsers including Internet Explorer 9, Firefox 4, Chrome, Opera 12 and Safari 5.
If you want to trigger a handler when a new property is set, you'll have even more trouble. The best you could do is wrapping your object inside a proxy and placing a set trap. You can then detect whether the property already existed by testing if this.getOwnPropertyDescriptor(name) returns a 'truthy' value. The Proxy API is very experimental though and only a few browsers provide a prototype implementation to play with. You'll probably have to wait quite a while to get a completed API with decent browser support.
you need a library that provides key-value observing and bindings.
ember-metal is one such library.
basically you create objects, and you can register observers on properties of those objects.
var obj = Em.Object.create({
val: null
valDidChange:function(){...}.observes('val')
});
valDidChange will fire whenever val property changes, so
obj.set('val', 'newValue');
will cause the observer to fire.
What about something like this? Here's a jsfiddle.
var objectManager = function(obj, setCallback){
this.obj = obj;
this.setCallback = setCallback;
};
objectManager.prototype.setProperty = function(prop, value){
this.obj[prop] = value;
this.setCallback(prop);
};
objectManager.prototype.getObj = function(){
return this.obj;
};
// USAGE:
var testMgr = new objectManager({}, function(prop){
console.log(name + ' has been set.');
});
testMgr.setProperty("hello", "world"); //should log "hello has been set.";
I suppose this could apply to any dynamic language, but the one I'm using is JavaScript. We have a situation where we're writing a couple of controls in JavaScript that need to expose a Send() function which is then called by the page that hosts the JavaScript. We have an array of objects that have this Send function defined so we iterate through the collection and call Send() on each of the objects.
In an OO language, if you wanted to do something similar, you'd have an IControl interface that has a Send() function that must be implemented by each control and then you'd have a collection of IControl implementations that you'd iterate through and call the send method on.
My question is, with JavaScript being a dynamic language, is there any need to define an interface that the controls should inherit from, or is it good enough to just call the Send() function exposed on the controls?
Dynamic languages often encourage Duck Typing, in which methods of the object dictate how it should be used rather than an explicit contract (such as an interface).
This is the same for PHP; you don't really need interfaces. But they exist for architectural needs. In PHP, you can specify type hints for functions which can be useful.
Second, an interface is a contract. It's a formal contract that all objects from this interface have those functions. Better to ensure that your classes meet those requirements than to remember: "mm, this class has isEnabled() but the other one is checkIfEnabled()". Interfaces help you to standardise. Others working on the derived object don't have to check whether the name is isEnabled or checkIfEnabled (better to let the interpreter catch those problems).
Since you can call any method on any object in a dynamic language, I'm not sure how interfaces would come into play in any truly useful way. There are no contracts to enforce because everything is determined at invocation time - an object could even change whether it conforms to a "contract" through its life as methods are added and removed throughout runtime. The call will fail if the object doesn't fulfill a contract or it will fail if it doesn't implement a member - either case is the same for most practical purposes.
We saw a nice implementation in the page below, this is ours (short version of it)
var Interface = function (methods) {
var self = this;
self.methods = [];
for (var i = 0, len = methods.length; i < len; i++) {
self.methods.push(methods[i]);
}
this.implementedBy = function (object) {
for (var j = 0, methodsLen = self.methods.length; j < methodsLen; j++) {
var method = self.methods[j];
if (!object[method] || typeof object[method] !== 'function') {
return false;
}
}
return true;
}
};
//Call
var IWorkflow = new Interface(['start', 'getSteps', 'end']);
if (IWorkflow.implementedBy(currentWorkFlow)) {
currentWorkFlow.start(model);
}
The whole example is at:
http://www.javascriptbank.com/how-implement-interfaces-in-javascript.html
Another alternative to the interfaces is offered by bob.js:
1. Check if the interface is implemented:
var iFace = { say: function () { }, write: function () { } };
var obj1 = { say: function() { }, write: function () { }, read: function () { } };
var obj2 = { say: function () { }, read: function () { } };
console.log('1: ' + bob.obj.canExtractInterface(obj1, iFace));
console.log('2: ' + bob.obj.canExtractInterface(obj2, iFace));
// Output:
// 1: true
// 2: false
2. Extract interface from the object and still execute the functions properly:
var obj = {
msgCount: 0,
say: function (msg) { console.log(++this.msgCount + ': ' + msg); },
sum: function (a, b) { console.log(a + b); }
};
var iFace = { say: function () { } };
obj = bob.obj.extractInterface(obj, iFace);
obj.say('Hello!');
obj.say('How is your day?');
obj.say('Good bye!');
// Output:
// 1: Hello!
// 2: How is your day?
// 3: Good bye!
Long story short: I'm in a situation where I'd like a PHP-style getter, but in JavaScript.
My JavaScript is running in Firefox only, so Mozilla specific JS is OK by me.
The only way I can find to make a JS getter requires specifying its name, but I'd like to define a getter for all possible names. I'm not sure if this is possible, but I'd very much like to know.
Proxy can do it! I'm so happy this exists!! An answer is given here: Is there a javascript equivalent of python's __getattr__ method? . To rephrase in my own words:
var x = new Proxy({}, {
get(target, name) {
return "Its hilarious you think I have " + name
}
})
console.log(x.hair) // logs: "Its hilarious you think I have hair"
Proxy for the win! Check out the MDN docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Works in chrome, firefox, and node.js. Downsides: doesn't work in IE - freakin IE. Soon.
You can combine proxy and class to have a nice looking code like php:
class Magic {
constructor () {
return new Proxy(this, this);
}
get (target, prop) {
return this[prop] || 'MAGIC';
}
}
this binds to the handler, so you can use this instead of target.
Note: unlike PHP, proxy handles all prop access.
let magic = new Magic();
magic.foo = 'NOT MAGIC';
console.log(magic.foo); // NOT MAGIC
console.log(magic.bar); // MAGIC
You can check which browsers support proxy http://caniuse.com/#feat=proxy.
The closest you can find is __noSuchMethod__ (__noSuchMethod__ is deprecated), which is JavaScript's equivalent of PHP's __call().
Unfortunately, there's no equivalent of __get/__set, which is a shame, because with them we could have implemented __noSuchMethod__, but I don't yet see a way to implement properties (as in C#) using __noSuchMethod__.
var foo = {
__noSuchMethod__ : function(id, args) {
alert(id);
alert(args);
}
};
foo.bar(1, 2);
Javascript 1.5 does have getter/setter syntactic sugar. It's explained very well by John Resig here
It's not generic enough for web use, but certainly Firefox has them (also Rhino, if you ever want to use it on the server side).
If you really need an implementation that works, you could "cheat" your way arround by testing the second parameter against undefined, this also means you could use get to actually set parameter.
var foo = {
args: {},
__noSuchMethod__ : function(id, args) {
if(args === undefined) {
return this.args[id] === undefined ? this[id] : this.args[id]
}
if(this[id] === undefined) {
this.args[id] = args;
} else {
this[id] = args;
}
}
};
If you're looking for something like PHP's __get() function, I don't think Javascript provides any such construct.
The best I can think of doing is looping through the object's non-function members and then creating a corresponding "getXYZ()" function for each.
In dodgy pseudo-ish code:
for (o in this) {
if (this.hasOwnProperty(o)) {
this['get_' + o] = function() {
// return this.o -- but you'll need to create a closure to
// keep the correct reference to "o"
};
}
}
I ended up using a nickfs' answer to construct my own solution. My solution will automatically create get_{propname} and set_{propname} functions for all properties. It does check if the function already exists before adding them. This allows you to override the default get or set method with our own implementation without the risk of it getting overwritten.
for (o in this) {
if (this.hasOwnProperty(o)) {
var creategetter = (typeof this['get_' + o] !== 'function');
var createsetter = (typeof this['set_' + o] !== 'function');
(function () {
var propname = o;
if (creategetter) {
self['get_' + propname] = function () {
return self[propname];
};
}
if (createsetter) {
self['set_' + propname] = function (val) {
self[propname] = val;
};
}
})();
}
}
This is not exactly an answer to the original question, however this and this questions are closed and redirect here, so here I am. I hope I can help some other JS newbie that lands here as I did.
Coming from Python, what I was looking for was an equivalent of obj.__getattr__(key)and obj.__hasattr__(key) methods. What I ended up using is:
obj[key] for getattr and obj.hasOwnProperty(key) for hasattr (doc).
It is possible to get a similar result simply by wrapping the object in a getter function:
const getProp = (key) => {
const dictionary = {
firstName: 'John',
lastName: 'Doe',
age: 42,
DEFAULT: 'there is no prop like this'
}
return (typeof dictionary[key] === 'undefined' ? dictionary.DEFAULT : dictionary[key]);
}
console.log(getProp('age')) // 42
console.log(getProp('Hello World')) // 'there is no prop like this'