Javascript: Get Name of Current Object Property in Object Literal - javascript

File this one under "just curious" or "is it possible?"
Say for example I have...
home: function(options) {
this._home('home', options)
}
login: function(options) {
this._home('login', options)
}
home and login are obviously identifiers on dozens of object properties for tracking purposes. Is there a way to just return home or login without using any variables (an external function call is fine) within the object property?
UPDATE: Turns out this isn't possible. The accepted answer doesn't exactly answer the question, but it is a wonderful example of simplifying numerous calls to the same property.

If you mean that within the function that the home property references you want to be able to somehow get the string "home" from that property name without hardcoding it then no, to the best of my knowledge that isn't possible.
Just guessing at what you're trying to achieve, would something like this help at least a little bit:
function callHome(propName) {
return function(options) {
this._home(propName, options);
}
}
var someObj = {
home: callHome('home'),
login: callHome('login')
}
someObj.home({some:"option"});
At least then you don't have to repeat the same function body for each property. Demo: http://jsfiddle.net/EeEAw/
Note: I assume that the _home() function invoked but not defined in the question would be defined somewhere in the real-world code. I don't show it in my answer, though I created a dummy one in my fiddle.
Just as an aside, note that the function doesn't really "belong" to the object or to the property - there's nothing stopping you doing this sort of thing:
var obj = {
test : "test",
home : function() {
alert(this.test);
}
};
var funcRef = obj.home;
var obj2 = {
method1 : funcRef
}
obj.home = null;
funcRef();
obj2.method1();
That is, you can create multiple references to the same function, and the function will continue to exist even if the original obj.home property is set to some other value (as long as the additional references continue to exist).

Identifier resolution and object property look up use completely separate methods. You can use with to add an object to the top of the scope chain, but it is very much recommended against and may well fail completely in strict mode.
So if you have:
var obj = {test:'test'};
alert(test);
then the identifier test is resolved on the scope chain. Since it doesn't exist there, an error is thrown. However, for:
alert(obj.test);
then firstly obj is resolved and found as a reference to an object, then the identifier test is resolved as a property of the object. You can also use with:
with (obj) {
alert(test);
}
in which case obj is temporarily placed at the top of the scope chain and so test is resolved on it first.

Related

Cannot combine dynamic prototype pattern with prototype chaining [duplicate]

Stylistically, I prefer this structure:
var Filter = function( category, value ){
this.category = category;
this.value = value;
// product is a JSON object
Filter.prototype.checkProduct = function( product ){
// run some checks
return is_match;
}
};
To this structure:
var Filter = function( category, value ){
this.category = category;
this.value = value;
};// var Filter = function(){...}
Filter.prototype.checkProduct = function( product ){
// run some checks
return is_match;
}
Functionally, are there any drawbacks to structuring my code this way? Will adding a prototypical method to a prototype object inside the constructor function's body (i.e. before the constructor function's expression statement closes) cause unexpected scoping issues?
I've used the first structure before with success, but I want to make sure I'm not setting myself for a debugging headache, or causing a fellow developer grief and aggravation due to bad coding practices.
Functionally, are there any drawbacks to structuring my code this way?
Will adding a prototypical method to a prototype object inside the
constructor function's body (i.e. before the constructor function's
expression statement closes) cause unexpected scoping issues?
Yes, there are drawbacks and unexpected scoping issues.
Assigning the prototype over and over to a locally defined function, both repeats that assignment and creates a new function object each time. The earlier assignments will be garbage collected since they are no longer referenced, but it's unnecessary work in both runtime execution of the constructor and in terms of garbage collection compared to the second code block.
There are unexpected scoping issues in some circumstances. See the Counter example at the end of my answer for an explicit example. If you refer to a local variable of the constructor from the prototype method, then your first example creates a potentially nasty bug in your code.
There are some other (more minor) differences. Your first scheme prohibits the use of the prototype outside the constructor as in:
Filter.prototype.checkProduct.apply(someFilterLikeObject, ...)
And, of course, if someone used:
Object.create(Filter.prototype)
without running the Filter constructor, that would also create a different result which is probably not as likely since it's reasonable to expect that something that uses the Filter prototype should run the Filter constructor in order to achieve expected results.
From a run-time performance point of view (performance of calling methods on the object), you would be better off with this:
var Filter = function( category, value ){
this.category = category;
this.value = value;
// product is a JSON object
this.checkProduct = function( product ){
// run some checks
return is_match;
}
};
There are some Javascript "experts" who claim that the memory savings of using the prototype is no longer needed (I watched a video lecture about that a few days ago) so it's time to start using the better performance of methods directly on the object rather than the prototype. I don't know if I'm ready to advocate that myself yet, but it was an interesting point to think about.
The biggest disadvantage of your first method I can think of is that it's really, really easy to make a nasty programming mistake. If you happen to think you can take advantage of the fact that the prototype method can now see local variables of the constructor, you will quickly shoot yourself in the foot as soon as you have more than one instance of your object. Imagine this circumstance:
var Counter = function(initialValue){
var value = initialValue;
// product is a JSON object
Counter.prototype.get = function() {
return value++;
}
};
var c1 = new Counter(0);
var c2 = new Counter(10);
console.log(c1.get()); // outputs 10, should output 0
Demonstration of the problem: http://jsfiddle.net/jfriend00/c7natr3d/
This is because, while it looks like the get method forms a closure and has access to the instance variables that are local variables of the constructor, it doesn't work that way in practice. Because all instances share the same prototype object, each new instance of the Counter object creates a new instance of the get function (which has access to the constructor local variables of the just created instance) and assigns it to the prototype, so now all instances have a get method that accesses the local variables of the constructor of the last instance created. It's a programming disaster as this is likely never what was intended and could easily be a head scratcher to figure out what went wrong and why.
While the other answers have focused on the things that are wrong with assigning to the prototype from inside the constructor, I'll focus on your first statement:
Stylistically, I prefer this structure
Probably you like the clean encapsulation that this notation offers - everything that belongs to the class is properly "scoped" to it by the {} block. (of course, the fallacy is that it is scoped to each run of the constructor function).
I suggest you take at the (revealing) module patterns that JavaScript offers. You get a much more explicit structure, standalone constructor declaration, class-scoped private variables, and everything properly encapsulated in a block:
var Filter = (function() {
function Filter(category, value) { // the constructor
this.category = category;
this.value = value;
}
// product is a JSON object
Filter.prototype.checkProduct = function(product) {
// run some checks
return is_match;
};
return Filter;
}());
The first example code kind of misses the purpose of the prototype. You will be recreating checkProduct method for each instance. While it will be defined only on the prototype, and will not consume memory for each instance, it will still take time.
If you wish to encapsulate the class you can check for the method's existence before stating the checkProduct method:
if(!Filter.prototype.checkProduct) {
Filter.prototype.checkProduct = function( product ){
// run some checks
return is_match;
}
}
There is one more thing you should consider. That anonymous function's closure now has access to all variables inside the constructor, so it might be tempting to access them, but that will lead you down a rabbit hole, as that function will only be privy to a single instance's closure. In your example it will be the last instance, and in my example it will be the first.
Biggest disadvantage of your code is closing possibility to override your methods.
If I write:
Filter.prototype.checkProduct = function( product ){
// run some checks
return different_result;
}
var a = new Filter(p1,p2);
a.checkProduct(product);
The result will be different than expected as original function will be called, not my.
In first example Filter prototype is not filled with functions until Filter is invoked at least once. What if somebody tries to inherit Filter prototypically? Using either nodejs'
function ExtendedFilter() {};
util.inherit(ExtendedFilter, Filter);
or Object.create:
function ExtendedFilter() {};
ExtendedFilter.prototype = Object.create(Filter.prototype);
always ends up with empty prototype in prototype chain if forgot or didn't know to invoke Filter first.
Just FYI, you cannot do this safely either:
function Constr(){
const privateVar = 'this var is private';
this.__proto__.getPrivateVar = function(){
return privateVar;
};
}
the reason is because Constr.prototype === this.__proto__, so you will have the same misbehavior.

Javascript: Create a sub-class within a class [duplicate]

I thought I had a reasonable understanding of the this object in JavaScript. When dealing with objects, callbacks, and both events and handlers, I haven't had a problem with it since time immemorial. Now, however, all has changed.
I've fallen head over heels in love with JavaScript. Pure JS, that is, not jQuery, prototype.js, dojo... So naturally, I've taken to using closures. In some cases, though, this is catching me off guard here. Take this snippet for one:
function anyFunc(par)
{
//console.log(par);
console.log(this);
}
function makeClosure(func)
{
return function(par)
{
return func(par);
}
}
var close = makeClosure(anyFunc);
close('Foo');
var objWithClosure = {cls:makeClosure(anyFunc),prop:'foobar'};
objWithClosure.cls(objWithClosure.prop);
var scndObj = {prop:'Foobar2'};
scndObj.cls = makeClosure;
scndObj.cls = scndObj.cls(anyFunc);
scndObj.cls(scndObj.prop);
In all three cases, this logs as the window object. It's an easy fix, of course:
function makeClosure(func)
{
return function(par)
{
return func.call(this,par);
}
}
This fix works, I put it here to avoid people answering this, without explaining what I need to know: why is this behaving the way it does here?
ensures the caller is effectively the object that the closure belongs to. What I fail to understand is this:
Sure enough, this points to the window object in the first case, but in other cases, it shouldn't. I tried logging this in the makeClosure function just before returning, and it did log the object itself, not the window object. But when the actual closure is used, this is back to pointing to the window object. Why?
The only thing I can think of is that, by passing the anyFunc function as an argument, I'm actually passing window.anyFunc. So I tried this quick fix:
function makeClosure(func)
{
var theFunc = func;
return function(par)
{
theFunc(par);
}
}
With the expected results, this now points to the objects, but again: Why? I have a few idea's (theFunc is a reference to the function in the local scope [this > private: theFunc]?), but I'm sure there are people here with a lot more know-how when it comes to JS, so I was hoping to get some more explanation or links to articles worth reading from them...
Thanks
Update
Here's a fiddle, may be I left something out, but here this logs all sorts of things ;)
Edit/Update 2
The case that confuses me is here.
Final Edit
Ok, This is getting a rather messy post. So to clarify: What I was expecting was a behaviour similar to this:
function makeClosure()
{
function fromThisFunc()
{
console.log(this);
}
return fromThisFunc;
}
var windowContext = makeClosure();
windowContext();
var objectContext = {cls:makeClosure()};
objectContext.cls();
What caught me, was that the function anyFunc wasn't declared within the correct scope, and therefore, this pointed to the window object. I found this out by reading an ancient scroll I found somewhere on the web.
But something a little more complicated has happened because the function object now referred to by globalVar was created with a [[scope]] property referring to a scope chain containing the Activation/Variable object belonging to the execution context in which it was created (and the global object). Now the Activation/Variable object cannot be garbage collected either as the execution of the function object referred to by globalVar will need to add the whole scope chain from its [[scope]] property to the scope of the execution context created for each call to it.
So what I needed to do, was simplify rather then complicate things:
function fromThisFunc()
{
console.log(this);
}
function makeClosure(funcRef)
{
//some code here
return funcRef;
}
That should work, right?
PS: I'll except Alnitak's answer, but special thanks goes to Felix Kling for all the patience and info.
As soon as you call:
return func(par);
You're creating a new scope (with its own this) and in this case because you haven't specified an object, this === window usually or undefined in strict mode. The called function does not inherit whatever this was in the calling scope.
Ways to set a value for this are:
myobj.func(par); // this === myobj
or
func.call(myobj, ...) // this === myobj
There are also:
apply
bind
arrow functions, where this is set to the same value as the outer execution context (also see MDN:Arrow functions )
The value of this depends only on whether you call the function as a method or as a function.
If you call it as a method, this will be the object that the method belongs to:
obj.myFunction();
If you call it as a function, this will be the window object:
myFunction();
Note that even if you are in a method that belongs to an object, you still have to call other methods in the object using the method syntax, otherwise they will be called as functions:
this.myOtherFunction();
If you put a method reference in a variable, you will detach it from the object, and it will be called as a function:
var f = obj.myFunction;
f();
The call and apply methods are used to call a function as a method even if it's not a method in the object (or if it's a method in a different object):
myFunction.call(obj);

Can you get the property name through which a function was called?

I've done a lot of searching and some playing around, and I'm pretty sure the answer to this question is no, but I'm hoping a JavaScript expert might have a trick up his sleeve that can do this.
A JavaScript function can be referenced by multiple properties, even on completely different objects, so there's no such thing as the object or property that holds the function. But any time you actually call a function, you must have done so via a single object (at the very least, the window object for global function calls) and property on that object.
(A function can also be called via a function-local variable, but we can consider the function-local variable to be a property of the activation object of the scope, so that case is not an exception to this rule.)
My question is, is there a way to get that property name that was used to call the function, from inside the function body? I don't want to pass in the property name as an argument, or closure around a variable in an enclosing scope, or store the name as a separate property on the object that holds the function reference and have the function access that name property on the this object.
Here's an example of what I want to do:
var callName1 = function() { var callName = /* some magic */; alert(callName); };
var obj1 = {'callName2':callName1, 'callName3':callName1 };
var obj2 = {'callName4':callName1, 'callName5':callName1 };
callName1(); // should alert 'callName1'
obj1.callName2(); // should alert 'callName2'
obj1.callName3(); // should alert 'callName3'
obj2.callName4(); // should alert 'callName4'
obj2.callName5(); // should alert 'callName5'
From my searching, it looks like the closest you can get to the above is arguments.callee.name, but that won't work, because that only returns the name that was fixed to the function object when it was defined, and only if it was defined as a named function (which the function in my example is not).
I also considered that maybe you could iterate over all properties of the this object and test for equality with arguments.callee to find the property whose value is a reference to the function itself, but that won't work either (in the general case), because there could be multiple references to the function in the object's own (or inherited) property set, as in my example. (Also, that seems like it would be kind of an inefficient solution.)
Can this be done?
Short answer:
No, you cannot get "the property name" used to call your function.
There may be no name at all, or multiple names across different scopes, so "the property name" is pretty ill defined.
arguments.callee is deprecated and should not be used.
There exists no solution that does not use arguments or closure.
Long answer:
As thefourtheye commented, you should rethink what you are trying to do and ask that instead in a new question. But there are some common misconceptions, so I will try to explain why you cannot get the "simple property name".
The reason is because it is not simple.
Before we go ahead, let us clarify something. Activation Objects are not objects at all.
The ECMAScript 5.1 specification calls them Environment Records (10.2.1), but a more common term is Scope chain.
In a browser the global scope is (often) the window object, but all other scopes are not objects.
There may be an object that you use to call a function, and when you call a function you must be in some scope.
With few exceptions, scopes are not objects, and objects are not scopes.
Then, there are many names.
When you call a function, you need to reference it, such as through an object property. This reference may have a name.
Scope chain has declarations, which always have a name.
A Function (the real function, not reference) may also have a function name - your arguments.callee.name - which is fixed at declaration.
Not only are they different names, they are not (always) the "the property name" you are seeking.
var obj = { prop : function f(){} }, func = obj.prop;
// "obj" and "func" are declarations.
// Function name is "f" - use this name instead of arguments.callee
// Property name is "prop"
func(); // Reference name is "func"
obj.prop(); // Reference names are "obj" and "prop"
// But they are the same function!
// P.S. "this" in f is undefined (strict mode) or window (non-strict)
So, a function reference may comes from a binding (e.g. function declaration), an Object (arguments.callee), or a variable.
They are all References (8.7). And reference does have a name (so to speak).
The catch is, a function reference does not always come from an object or the scope chain, and its name is not always defined.
For example a common closure technique:
(function(i){ /* what is my name? */ })(i)
Even if the reference does have a name, a function call (11.2.3) does not pass the reference or its name to the function in any way.
Which keeps the JavaScript engine sane. Consider this example:
eval("(new Function('return function a(){}'))()")() // Calls function 'a'.
The final function call refers the eval function, which refers the result of a new global scope (in strict mode, anyway), which refers a function call statement, which refers a group, which refers an anonymous Function object, and which contains code that expresses and returns a function called 'a'.
If you want to get the "property name" from within a, which one should it get? "eval"? "Function"? "anonymous"? "a"? All of them?
Before you answer, consider complications such as function access across iframes, which has different globals as well as cross origin restriction, or interaction with native functions (Function.prototype.bind for example), and you will see how it quickly becomes hell.
This is also why arguments.caller, __caller__, and other similar techniques are now all deprecated.
The "property name" of a function is even more ill defined than the caller, almost unrealistic.
At least caller is always an execution context (not necessary a function).
So, not knowing what your real problem is, the best bet of getting the "property name" is using closure.
there is no reflection, but you can use function behavior to make adding your own fairly painless, and without resorting to try/catch, arguments.callee, Function.caller, or other strongly frowned-upon behavior, just wasteful looping:
// returning a function from inside a function always creates a new, unique function we can self-identify later:
function callName() {
return function callMe(){
for(var it in this) if(this[it]===callMe) return alert(it);
}
};
//the one ugly about this is the extra "()" at the end:
var obj1 = {'callName2':callName(), 'callName3':callName() };
var obj2 = {'callName4':callName(), 'callName5':callName() };
//test out the tattle-tale function:
obj1.callName2(); // alerts 'callName2'
obj2.callName5(); // alerts 'callName5'
if you REALLY want to make it look like an assignment and avoid the execution parens each time in the object literal, you can do this hacky routine to create an invoking alias:
function callName() {
return function callMe(){
for(var it in this) if(this[it]===callMe) return alert(it);
}
};
//make an alias to execute a function each time it's used :
Object.defineProperty(window, 'callNamer', {get: function(){ return callName() }});
//use the alias to assign a tattle-tale function (look ma, no parens!):
var obj1 = {'callName2': callNamer, 'callName3': callNamer };
var obj2 = {'callName4': callNamer, 'callName5': callNamer };
//try it out:
obj1.callName2(); // alerts 'callName2'
obj2.callName5(); // alerts 'callName5'
all that aside, you can probably accomplish what you need to do without all the looping required by this approach.
Advantages:
works on globals or object properties
requires no repetitive key/name passing
uses no proprietary or deprecated features
does not use arguments or closure
surrounding code executes faster (optimized) than
a try/catch version
is not confused by repeated uses
can handle new and deleted (renamed) properties
Caveats:
doesn't work on private vars, which have no property name
partially loops owner object each access
slower computation than a memorized property or code-time repetition
won't survive call/bind/apply
wont survive a setTimeout without bind() or a wrapper function
cannot easily be cloned
honestly, i think all the ways of accomplishing this task are "less than ideal", to be polite, and i would recommend you just bite the coding bullet and pass extra key names, or automate that by using a method to add properties to a blank object instead of coding it all in an object literal.
Yes.
Sort Of.
It depends on the browser. (Chrome=OK, Firefox=Nope)
You can use a factory to create the function, and a call stack parsing hack that will probably get me arrested.
This solution works in my version of Chrome on Windows 7, but the approach could be adapted to other browsers (if they support stack and show the property name in the call stack like Chrome does). I would not recommend doing this in production code as it is a pretty brittle hack; instead improve the architecture of your program so that you do not need to rely on knowing the name of the calling property. You didn't post details about your problem domain so this is just a fun little thought experiment; to wit:
JSFiddle demo: http://jsfiddle.net/tv9m36fr/
Runnable snippet: (scroll down and click Run code snippet)
function getCallerName(ex) {
// parse the call stack to find name of caller; assumes called from object property
// todo: replace with regex (left as exercise for the reader)
// this works in chrome on win7. other browsers may format differently(?) but not tested.
// easy enough to extend this concept to be browser-specific if rules are known.
// this is only for educational purposes; I would not do this in production code.
var stack = ex.stack.toString();
var idx = stack.indexOf('\n');
var lines = ex.stack.substring(idx + 1);
var objectSentinel = 'Object.';
idx = lines.indexOf(objectSentinel);
var line = lines.substring(idx + objectSentinel.length);
idx = line.indexOf(' ');
var callerName = line.substring(0, idx);
return callerName;
}
var Factory = {
getFunction: function () {
return function () {
var callName = "";
try {
throw up; // you don't *have* to throw to get stack trace, but it's more fun!
} catch (ex) {
callName = getCallerName(ex);
}
alert(callName);
};
}
}
var obj1 = {
'callName2': Factory.getFunction(),
'callName3': Factory.getFunction()
};
var obj2 = {
'callName4': Factory.getFunction(),
'callName5': Factory.getFunction()
};
obj1.callName2(); // should alert 'callName2'
obj1.callName3(); // should alert 'callName3'
obj2.callName4(); // should alert 'callName4'
obj2.callName5(); // should alert 'callName5'

javascript - help me understand this structure (lexical scoping)

Below is simplification of some code I am trying to understand.
What are we trying to do in this javascript fragment? It seems we are creating object(?) called myCompany if not already created, then adding child object myProject to myCompany.
Then creating a local variable withinmyCompany.myProject and another local to function myCompany.myProject.myfunction. The () at the end make it execute immediately. And we are doing this to keep localVariable_1 out of global space?
var myCompany= myCompany || {};
if (!myCompany.myProject) {
myCompany.myProject = {};
}
myCompany.myProject = function () {
var localVariable_1;
function myFunction(){
var anotherlocalVariable;
// .. do some stuff
}
}();
The first line checks if the object exists, if not use shorthand definition {} to create an Object. || compares. If argument one is null set argument two.
The if on the next line checks if the property myProject isn't set on the object. ! is the operator. If myCompany.myProject returns undefined this if clause returns true. When true create object as property myProject.
Third part: myProject gets replaced by a function object. This function is defined between { and }, but is immediately called upon by the () behind the function declaration.
localvariable_1 will never be in the global scope since it has the var statement. Binding it to the scope of myCompany.myProject function. Maybe this function is directly called to set up some initial values, but wrap them in a function that could be reused to change the values at another moment.
One piece at a time...
var myCompany= myCompany || {};
if myCompany exists you set it to it, otherwise you create an empty object and set myCompany to an empty object.
NOTE: if myCompany already exists you have no indicator of what it is
if (!myCompany.myProject) {
myCompany.myProject = {};
}
Now that you know myCompany is an object you verify it has a project property on it. if not you set myProject to an empty object.
NOTE: you have tested nothing about myProject so again there is no indicator of what it is
myCompany.myProject = function () {
var localVariable_1;
function myFunction(){
var anotherlocalVariable;
// .. do some stuff
}
}();
Here you are assigning myCompany.myProject. Notice at the bottom the () before the ; That makes this function get executed immediately. Inside of the function you are creating another function that currently isn't doing anything. Where you aren't returning from the function I think it will set myProject to undefined.
You may already know what an immediate function is but if not it is basically a function that is called right away. It is also standard to wrap it in a () so that it is easier to read for example
var someFunction = (function () {
/*whatever*/
} ());
You said this was simplified from the original so I am guessing you removed an important part of the code that actually does things but the confusion is probably due to the JavaScript's way of scoping. It uses what is called Lexical scoping. You can think of it as scoping by functions.
Another thing that may be tripping you up is how JavaScript uses truthy evaluation for logical comparisons.
The last thing to mention that might be confusing the way you read the code is javascript's hoisting.
Hopefully that helps or at least points you to a few things you can look into to figure out the parts you don't exactly understand.
Sorry I just hate writing in comments lol.
If you are trying to help prevent your global scope from getting polluted then you might want to use objects and a something similar to what you are doing. Depending on how crazy you want to get you could look into Prototypical Inheritance.
A common pattern is to do something like this
var company = (function() {
var name;
var getName = function() {
return name;
};
var setName = function(n) {
name = n;
};
return {
getName : getName,
setName : setName
}
}())
Now you can do company.setName("yoda") or whatever.
This will give you a basic getter and setter where no one can change the companies name without going through your getter and setter and it also doesn't pollute the global scope. You can have whatever you want on company this way and you also encapsulate the data within the object.
Notice how var company = a function that is called immediately which returns an object that has whatever you want to encapsulate on it.
Is that what you are talking about?

Question about Javascript model construction

I'm working on implementing a Javascript model on a web app that I'm working on. The purpose of the model is to simply hold information about the state of the page. I have come across two different implementations for creating the model and I was wondering which one was the best to use. The first implementation:
var PageInfo = function () {
this._info = {};
};
PageInfo.prototype = {
getInfo: function () {
return this._info;
},
setInfo: function (updatedInfo) {
this._info = updatedInfo;
}
};
The 2nd implementation:
var pageInfo = function () {
var info = {};
return {
getInfo: function () {
return info;
},
setInfo: function (updatedInfo) {
info = updatedInfo;
}
}
};
Another question I have is about the setInfo() function. When I find myself updating the model, I often want to have the info that I just changed immediately available to me. This has led me to write the setter function as such:
setInfo: function(updatedInfo) {
info = updatedInfo;
return info;
}
which I implement in the code like so:
var info = pageInfo.setInfo(newInfo);
Is this ok or should I be implementing it like this?:
pageInfo.setInfo(newInfo);
var info = pageInfo.getInfo();
Just trying to follow best practices and avoid any issues that may come up from using the wrong implementation.
Both implementations are perfectly acceptable. The former will be faster, albeit by a negligible amount, but exposes its internals to the world. This means that any variable that holds a reference to an instance of PageInfo will be able to manipulate the _info property. Generally this is a non-issue as properties that being with an underscore (_) are considered to be private and should be left alone.
The latter implementation makes use of a concept called closure. A closure is formed when a value is returned that maintains a reference to its defining scope. Essentially it means that the info variable is kept alive. Since the variable is "closed over" it's impossible for it to be modified outside of the interface methods that you provide. In my experience this is rarely needed.
In regards to your second question, again either is acceptable. I like the interface for accessor methods to be consistent so I would say that setInfo should not return anything but there are exceptions to every rule. The exception to the rule occurs when the the value returned by getInfo will not be congruent with what was passed to setInfo. That is, if getInfo returns different value than the value passed to setInfo you might want to return the value out of setValue. Otherwise, the caller could simply re-use the value that was passed to setValue instead of calling getValue.
1st implementation is better, as in 2nd implementation every time you call pageInfo function, you are defining 2 new functions (or set up a closure), while 1st implementation is defining them in prototype and reusing.
For other question, if you only do this to preserve lines, i might suggest something like:
var info = pageInfo.setInfo(newInfo) || pageInfo.getInfo();
assuming setInfo returns undefined.

Categories

Resources