I'm reading memoization chapter of John Resig's book about Javascript and I've got the following question:
Is it better to develop memoization for a method or create cache as object's property assuming that I can modify object's design?
This example implements caching as part of object's functionality:
function Calc() {
this._cache = {};
this.isEven = function(arg) {
return this._cache[arg] !== undefined ?
this._cache[arg] :
this._cache[arg] = (arg%2===0);
}
}
This example implements caching as part of function's functionality:
function Calc() {
this.isEven = function(arg) {
this.isEven.cache = this.isEven.cache || {};
return this.isEven.cache[arg] !== undefined ?
this.isEven.cache[arg] :
this.isEven.cache[arg] = (arg%2===0);
}
}
This is the way they should be used:
var obj = new Calc();
obj.isEven(3);
Well, here's the thing: what if you had an "isOdd" function? You would want it to have its own cache, so the second option is easier.
That being said, this isn't really a good example, because x%2==0 is a really cheap operation, so it shouldn't be made into a function.
Related
I have read that private state of instance objects is generally not advised, and I would appreciate the help in pointing out the flaws/shortcomings of the following implementation.
Any advise/critique is greatly appreciated.
var namespace = {};
namespace.parent = {
parent_method1 : function () {},
parent_method2 : function () {}
};
namespace.child = function (properties) {
var private="secret";
this.prototype = {
create : function () {
this.unique = 'base';
this.unique += this.properties;
return this.unique;
},
get_private: function () {
console.log(private);
},
set_private: function (val) {
private = val;
}
};
var proto = Object.create(namespace.parent);
var instance = Object.create(proto);
for (var property in this.prototype) {
if (this.prototype.hasOwnProperty(property)) {
proto[property] = this.prototype[property];
}
}
instance.properties = properties;
return instance;
};
var a = namespace.child("a");
console.log(a.create());
a.get_private();
a.set_private("new_a_secret");
a.get_private();
var b = namespace.child("b");
console.log(b.create());
b.get_private();
a.get_private();
I would appreciate the help in pointing out the flaws/shortcomings of the following implementation.
I don't see anything wrong with your implementation of the var private, provided that it does what you expect it to do.
However, the big flaw of the code is: I don't understand it. What is your implementation supposed to do? It does not follow any of the standard patterns. This might be a shortcoming of the pseudo-methods and clear up when implementing a real world model; however as it stands it's quite confusing. Some documentation comments would help as well.
Specifically:
What does namespace.child do? It looks like a factory function, but I'm not sure what "childs" it does produce.
Also, for some reason it does set the namespace.prototype property to a new object on every invocation, which is then mixed into the instance object proto object. However, it leaves the internals (get_private, set_private) of the last created instance in global scope.
Are a and b supposed to be classes? Why do they have .create() methods, that initialise the class (instance?) - and should rather be called .init() if at all? Why do they return the .unique property value?
Why doesn't the child method initialize those factored objects right away?
What is that .properties field that holds a string value?
Why are you using two-level inheritance for those instance objects? Object.create(namespace.parent) is understandable, it inherits from a static object that is shared. But why is then Object.create(proto) used, copying some properties (create, get_private, set_private) on the proto and some properties (properties, unique) on the instance? Why distinguish between them?
This is such a fundamental question, that I'm sure it's a duplicate, so I apologize in advance, but is this how I write an object such that I use by saying:
myApplication.myFirstMethod(x);
x = myApplication.myFirstMethod();
Here's the code:
myApplication = {};
(function() {
myApplication.myFirstMethod = function() {
var local = {};
if (arguments.length) {
local.result = arguments[0];
}
return local.result;
}
myApplication.mySecondMethod = function() {
var local = {};
if (arguments.length) {
local.result = arguments[0];
}
return local.result;
}
})();
jsFiddle Demo
A more object oriented approach would be to use instantiation and prototype.
Setup
var Application = function(){
this.local = {};
};
Application.prototype.Value = function(){
if (arguments.length) {
this.local.result = arguments[0];
}else{
return this.local.result;
}
};
Used
var app = new Application();
app.Value(6);
alert(app.Value());//6
From a jQuery point of view, they will first screen to see if there are arguments, this code is direct from their source for the val function:
val: function( value ) {
if ( !arguments.length ) {
var elem = this[0];
...
It then goes on to use the element's native API and some other metrics to get the value for the element (In general, the only type of elements which will return a value from val are going to be elements such as input, select, etc. - form elements basically).
At the end of the if block it attempts to return various results based on if it found a value attached to the element (or set of elements). This guarantees that the clause of "setting" never executes when a "get" is encountered. If the case is that "set" is being used it goes through a slightly complex set of code to properly set a value to the element.
The reason that the code shows val: function() is because it is part of an object which is being used to "extend" the jQuery prototype using jQuery's extend functionality.
This is the exact code in a jsfiddle of jQuery's val function
There are many patterns for creating objects like this and everyone has their favorites. Addy Osmani does an excellent job of summarizing the most popular patterns in his Javascript Design Patterns "book". Specifically, this section:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/#designpatternsjavascript
I reread this semi-annualy just to make sure I'm keeping all the patterns in my quiver.
I'm trying to use memoization to speed up my Javascript, but I need it on a proto method, and I need said method to have access to the this object, and it's giving me fits. Here's what I have:
MyObj.prototype.myMethod = function(){
var self = this
, doGetData = (function() {
var memo = []
, data = function(obj) {
var result = memo;
if (obj.isDirty) {
obj.isDirty = false;
result = $.map(obj.details, function(elem, i) {
return elem.export();
});
memo = result;
}
return result;
}
return data;
}())
;
return doGetData(self);
};
I can get it to run, I just can't get it to memoize. I know something is wrong, but I can't figure out what. I know there are tons of examples of how to memoize, but none that I've come across deal with scope like this.
If you want the function on the prototype, but you want it to memoize for each instance independently, then "memo" needs to be an instance property (or a closure could be the instance property, I guess; whichever).
MyObj.prototype.myMethod = function() {
if (!("memo" in this) || this.isDirty) {
this.isDirty =false;
this.memo = $.map(obj.details, function(elem, i) {
return elem.export();
});
}
return this.memo;
};
I don't think you can do it without polluting the instances, though you could use newer JavaScript features to keep the "memo" thing from being enumerable. The prototype is shared by all instances, after all.
It is possible to use a Map object for storing and retrieving method caches for all instances. Maps support objects as keys. (Kind of off-topic, but strict mode affects the propagation of "this". Now this works without "var self = this;".)
"use strict";
MyObj.prototype.myMethod = function() {
var prototypeCache = new Map();
return function(arg) {
if (!prototypeCache.has(this)) prototypeCache.set(this, new Map());
var instanceCache = prototypeCache.get(this);
if (instanceCache.has(arg)) return instanceCache.get(arg);
else {
//Do expensive calculation that is stored in result...
instanceCache.set(arg, result);
return result;
}
};
}();
Now for simplicity I also used a Map for the instanceCache. For speed one would typically use just an object. It depends on the keys one can make. It is typically possible to find a way to store by unique strings. (Numbers can be converted, Objects can have id strings and state/version properties, multiple arguments can be concatenated into one string...)
Another solution entirely is to create the method in the constructor instead of having it in the prototype. But that is just as bad pollution as having method caches in instance properties. Much worse, I think.
In Javascript, it seems like using property accessors is not all that common (unlike in other OO languages such as Java for example).
If I have a Person object with a name, defined as
function Person(name) {
this.name = name;
}
A person's name is not going to change, but I do want to be able to access it when needed, so I could do something like:
function Person(name) {
var name = name;
this.getName = function() {
return name;
}
}
Even in a dynamic language, I think the principles of using getters and setters apply the same way they do to statically typed OO languages (e.g. encapsulation, adding validation, restricting access, etc)
This question may get closed as subjective, but I'm curious as to why this behavior doesn't appear more often (e.g. Java developers would go crazy if everything was public).
Is there a "standard" way to do this in javascript? I've seen Object.defineProperty, but not all browsers support that.
Javascript has intercept-able property accessors:
http://ejohn.org/blog/javascript-getters-and-setters/
IMHO this is a far better solution to enforce the Uniform Access Principle than Java's more strict explicit getters, but that is also part of the simplicity and inflexibility of that language (Groovy for instance allows for similar interception).
I know my thoughts on the subject.
Getters and setters are evil.
Wait! Really! Bear with me a moment and let me explain.
Just using a method to get and set a value is .. well .. kinda pointless. It doesn't protect, not really, and what you put in is what you get out.
On the other hand, I'm rather fond of methods that put information in, then get information back out. BUT here is the magic part! It isn't the same information. Not directly.
function Person(name) {
this.getFullName = function() {return this.firstName + " " + this.lastName;};
this.setBirthday = function(date) { this.birthday = date; };
this.getAge = function() { /* Return age based on the birthday */ };
this.isOfLegalDrinkingAge function() { /* do your math here too */ };
}
But most of the time I'm just shoving static data in and getting static data out. What is the point of hiding it behind getters and setters?
As a secondary reason, dealing with the DOM and most host objects, you set properties. You don't play with getters and setters. Not using them fits the rest of the 'flavor' of what JS coders do.
I think the answer is that emulating classes in javascript is not the common practice, because the language is actually prototypal.
Although it is possible to create class like structures (as in your example), they are not really like java classes, and as a programmer, you end up fighting with the nuances.
If however, you embrace the prototypal nature of javascript, you are rewarded by a different, yet cohesive, and simple structure for the language.
It is not necessary to use getters and setters with prototypal structure, as you can simply set an object by, well, setting it to a value, and get it by, calling it as a value.
Javascript does not force you to write structured code, and does not stop you from doing so. I think the culture that has grown up around javascript has developed a good coding style, that is perfectly valid, and different from any other language I use.
I know this answer is not definitive, and conclusive, but hopefully there are some ideas in there that help you to find the anser you are looking for.
I apologize if I dont understand the question correctly, but self executing functions are one way to make members public/private
var Person = function(){
var _name = "Roger",
self = { getName : function (){ return _name; }};
return self;
}()
You can then access Person.getName() from anywhere , but not set _name.
This is what I used for local fields:
TYPE_DEFAULT_VALUE= {
number: 0,
string: "",
array: [],
object: {},
};
typeOf = function (object) {
if (typeof object === "number" && isNaN(object))
return NaN;
try {
return Object.prototype.toString.call(object).slice(8, -1).toLowerCase();
}
catch(ex) {
return "N/A";
};
};
getAccessor = function(obj, key, type, defaultValue) {
if (defaultValue === undefined)
defaultValue = TYPE_DEFAULT_VALUE[type] === undefined ? null : TYPE_DEFAULT_VALUE[type];
return {
enumerable: true,
configurable: true,
get: function () {
if (obj[key] === undefined)
obj[key] = defaultValue;
return obj[key];
},
set: function (value) {
if (typeOf(value) === type)
obj[key] = value;
},
};
}
LocalFields = function (fields, object) {
/**
* field properties
* {
* type: [ required ] ( number | string | array | object | ... ),
* defaultValue: [ optional ]
* }
*/
if (! fields)
throw "Too few parameters ...";
if (! object)
object = this;
var obj = this;
var fieldsAccessor = {};
for(key in fields){
field = fields[key];
fieldHandler = key[0].toUpperCase() + key.substr(1);
if(! field.type)
throw "Type not set for field: " + key;
fieldsAccessor[fieldHandler] = getAccessor(obj, fieldHandler, field.type, field.defaultValue)
}
Object.defineProperties(object, fieldsAccessor);
}
Now for each Class I can just call something like:
Person = function(){
new LocalFields({
id: { type: "number" },
name: { type: "string" },
}, this);
}
And then like VS getter and setter you'll call:
var alex = new Person();
alex.Name = "Alex Ramsi";
console.clear();
console.info(alex.Name);
I use the iOS UI Automation framework to make sure my iPhone app rocks.
Everybody who uses this framework would tell you that it's great, but that it's lacking a lot of structure.
So I have to deal with instances of UIAWindow, which represent different screens of my app. To be more object-oriented, I'd like to have a specific class for each screen, so I could add specific methods, like
myScreen1.tapDoneButton();
var total = myScreen2.getNumberOfElements();
For the moment, I'm able to achieve this by passing the instances of UIAWindow to functions that will add the appropriate methods, like this :
function makeMainScreen(actualScreen)
{
actualScreen.constructor.prototype.getAddButton = function() {
return this.buttons()["add button"];
};
actualScreen.constructor.prototype.tapAddButton = function() {
this.getAddButton().tap();
};
// Add any desired method...
return actualScreen;
}
It works fine, I use it like this :
var mainScreen = makeMainScreen(app.mainWindow());
mainScreen.tapAddButton();
But that doesn't seem object-oriented enough, I would like to create real objects, using the new and this keywords, so I'd have a declaration like this :
function MainScreen(actualScreen){
// This line doesn't work : because 'this' is immutable
this = actualScreen;
this.tapAddButton = function(){
this.getAddButton().tap();
}
//...
}
And I'd use it like this :
var mainScreen = new MainScreen(app.mainWindow());
mainScreen.tapAddButton();
I thought I could save the actualScreen as a property of the object (Like in Grace Shao's answer below), and call all the methods on it, but I'd like keep the original UIAWindow methods.
Does anybody know how to do this?
Or perhaps what I'm trying to achieve doesn't make sense, in which case I'd be happy to know.
If I understand correctly, you could try the following:
function MainScreen(actualScreen){
this.screen = actualScreen;
}
MainScreen.prototype.tapAddButton = function () {
this.screen.getAddButton().tap();
};
MainScreen.prototype.getScreen = function () {
return this.screen;
};
//...
var mainScreen = new MainScreen(app.mainWindow());
mainScreen.tapAddButton();
You are correct that you cannot assign anything to this. You could also define the methods inside the constructor MainScreen, but they would be considered privileged members.
function MainScreen(actualScreen){
this.screen = actualScreen;
this.tapAddButton = function () {
this.screen.getAddButton().tap();
};
}
If you dont want them to be privileged members, it is better to define them outside the constructor. Otherwise, the members will be initialized over and over again everytime when you instantiate a new object.
Updated:
You could also wrappers for the methods of screen inside the constructor as below.
var prop;
for (prop in actualScreen) {
if (typeof actualScreen[prop] !== 'Function') {
continue;
}
this[prop] = function () {
return actualScreen[prop].apply(actualScreen, arguments);
};
}