Access Return Object in Javascript - javascript

For a project I'm working on, I'm building some data objects with the following lay-out (it's a binary file that I'm reading with ArrayBuffers:
AFile.prototype = {
p: new BufferPack(),
filedata: null,
position: 0,
label_records: null,
closestmultipleof: function(n,v) {
return Math.ceil((v / n) * n);
},
r: function(size) {
result = new Uint8Array(this.filedata,this.position,size);
this.position += size;
return result;
}
readValueLabel: function() {
return {
value: this.rS(8),
len: this.rS8(),
label: this.rS(this.closestmultipleof(8, this.len + 1))
};
},
readLabelRecords: function() {
return {
rec_type: this.rS32(),
label_count: this.rS32(),
value_labels: _.map(_.range(this.label_count), function(num) {
console.debug(num);
},this)
};
},
loadFile: function(blob) {
this.filedata = blob;
this.label_records = this.readLabelRecords();
}
};
However, I seem to have problems with accessing the values in the return scope. In some return scopes, I need to access the variables from the same scope in order to manipulate the data a little bit (see the definition of value_labels).
Only, it doesn't seem to be able to access the variable label_count there (probably because it is in the same return scope). How would I be able to do this?
The only way that I can get it to work is if I do this:
ret = {}
ret['a'] = 5;
ret['b'] = ret['a'] * 2
return ret;
But that seems ugly enough. Any ideas?
And yes, it is a singleton! I'm only going to use this once.
Let me make clear: The problem is within the following code:
return {
a: functionreturn(),
b: this.a * s
};
This.a doesn't seem to exist there.

[update]
You can create a closure to label_count.
function AFile(){};
AFile.prototype ={
readLabelRecords: function() {
label_count=this.rS32();
return {
label_count:label_count,
log:console.log(label_count)//'return from rs32'
};
},
};
AFile.prototype.rS32=function(){
return "return from rs32";
}
var o = new AFile();
o.readLabelRecords();
That answer was based on the code provided, the simplest code to re produce:
function complicatedCalculations(){
return 22;
}
function returnObject(){
var cacheComplicated=complicatedCalculations();//closure variable will
// be available within the entire body of returnObject function
// but never outside of it.
return{
calculated:cacheComplicated,
twiceCalculated:cacheComplicated*2//you could not access calculated
// here so using a cache closure variable
}
}
Or have your returnObject function return a new instance of an object created with a constructor function:
function returnObject(){
return new (function(){
this.calculated=complicatedCalculations();
this.twiceCalculated=this.calculated*2;
})();
}

You forgot a comma before readValueLabel which makes the structure is invalid.
Update:
Too bad that the other answer was deleted, it had a valid point even if it didn't "compile".
Reference to this is problematic inside inner scopes in JS, but it can be worked around by doing something like that:
readLabelRecords: function() {
var that = this;
return {
rec_type: that.rS32(),
label_count: that.rS32(),
value_labels: _.map(_.range(that.label_count), function(num) {
console.debug(num);
},that)
};
}

Related

Function definition cannot understand

I know some javascript function declarations. Like exression function, anonymous function, but I do not understand what kind of syntax of these two functions? Can anybody tell me what is the name of these two functions? I mean "manipulateData: function (input)" and "getDataById: function (id)".
Why return statement can have this syntax to return two functions? Why not return one function in one time instead of two functions? It will be great if you can give me some reference documents? Thanks.
app.service('MyService', function ($http, $q, $angularCacheFactory) {
var _dataCache = $angularCacheFactory('dataCache', {
maxAge: 3600000 // items expire after an hour
});
/**
* #class MyService
*/
return {
manipulateData: function (input) {
var output;
// do something with the data
return output;
},
getDataById: function (id) {
var deferred = $q.defer();
if (_dataCache.get(id)) {
deferred.resolve(_dataCache.get(id));
} else {
// Get the data from the server and populate cache
}
return deferred.promise;
}
};
});
These functions are just anonymous functions that happen to be values in an object. Consider this:
var object = {
add: function(x, y) {
return x + y;
}
};
object.add(1, 2); // = 3
This is the same as:
function addFunction(x, y) {
return x + y;
}
var object = {
add: addFunction
};
object.add(1, 2); // = 3
There's nothing special about these functions, as they're just normal properties of an object.
You are not returning a function in this case but an Object.
When you define a service in angularjs you have to provide its implementation in the callback (the second argument of app.service)
This callback has to return methods you want to make available to other parts of your application.
Then in a controller or in another service you will be able to write:
app.controller("MyCtrl", ["MyService", function(MyService) {
MyService.getDataById('an id');
}]);
Angular Service returns an instance of the service you bind to the app namespace, those functions in the return statement are public methods that can be worked with. Basically an Object that contains two methods manipulateData, and getDataById.
It's similar to this
function company() {
let product; // This is private
// Public Methods
return {
setLatestProduct: function(value) {
product = value;
console.log(product, ' set');
},
getLatestProduct: function() {
return product;
}
}
}
const apple = company();
console.log(apple); // { setLatestProduct: function, getLatestProduct: function }

Needing some visitor-like design pattern

I will give you a sample example of my problem to remove the logical complexity and let you be focus on the important part. Of course, this example will be a bit useless...
I have a tree structure where node are like that
{
path: "...",
childs : []
}
Now, I have to write all the full paths from root to each leaf in an array.
My design is very poor:
function listPaths(node) {
var result = [];
function listForNode(n, parentFullPath) {
var thisPath = parentFullPath + "/" + n.path;
result.push(thisPath);
n.childs.forEach(function (child) {
listForNode(child, thisPath);
});
}
listForNode(node, "");
return result;
}
It could be nice but I can't write the test with Mocha without having an insane 600 line code test file. At this moment, you should be asking why. The reason is the complexity of the real purpose, that's not relevant for my question. My goal is to having something 'mockable' cause I'm used to. (Java dev). But I fail.
Do you have any pattern that I can use to resolve this one? I'm not really good at JS patterns. :/
Visitor? Making an Y Combinator? So many possibility...
Thank you for reading me
You need to remember that functions are first class citizens in javascript.
I see that essentially what you have is something like
function createVisitor(parentsAccumulatorInitialValue, parentsAccumulator){
var visitor = function myVisitor (node) {
var result;
function listForNode(n, parentsAcc) {
var thisPath = parentsAccumulator(parentsAcc, n);
result.push(thisPath);
n.childs && n.childs.forEach(function (child) {
listForNode(child, thisPath);
});
}
result = [];
listForNode(node, parentsAccumulatorInitialValue());
return result;
}
return visitor;
}
var listPaths = createVisitor(
function parentInit () {
return "";
},
function parentAcc (parentFullPath, n) {
return parentFullPath + "/" + n.path;
});
But that's not the only abstraction you could take care of:
function createVisitor2(
totalAccumulatorInitialValue,
totalAccumulator,
parentsAccumulatorInitialValue,
parentsAccumulator){
var visitor = function myVisitor (node) {
var total;
function listForNode(n, parentsAcc) {
var thisPath = parentsAccumulator(parentsAcc, n);
total = totalAccumulator(total, thisPath, n);
n.childs && n.childs.forEach(function (child) {
listForNode(child, thisPath);
});
}
total = totalAccumulatorInitialValue();
listForNode(node, parentsAccumulatorInitialValue());
return total;
}
return visitor;
}
var listPaths2 = createVisitor2(
function totalInit() {
return [];
},
function totalAcc(total, thisPath, n){
total.push(thisPath);
return total;
},
function parentInit () {
return "";
},
function parentAcc (parentFullPath, n) {
return parentFullPath + "/" + n.path;
});
Which might be pretty reasonable, but as you can see, I'm already beginning to have trouble finding appropriate names for these variables. In fact, I'd say the name of our function is bad, as doesn't create anything strictly like a visitor object I know of. However, it does work (BTW, I've slightly modified it to handle nulls as well as empty arrays):
> listPaths( { path:"foo",
childs: [{path:"bar", childs: null}, {path:"bob", childs: null}]})
["/foo", "/foo/bar", "/foo/bob"]
It can be modified even further so that your trees don't strictly even have the same structure... but we're already at 4 parameters, which isn't great. It'd be better if your visitor creator were passed a single extensible object with all the necessary methods or values. For instance, maybe (pseudocode):
function createVisitor3(opts) {
//assume we've defined GetDefaults() somewhere local to createVisitor3
// as well as assume that extend is defined somewhere that copies properties
// into a new object like various previously existing libraries do.
opts = extend({}, GetDefaults(), opts);
var totalAccumulatorInitialValue = opts.totalAccumulatorInitialValue;
var totalAccumulator = opts.totalAccumulator;
var parentsAccumulatorInitialValue = opts.parentsAccumulatorInitialValue;
var parentsAccumulator = opts.parentsAccumulator;
var childrenGetter = opts.childrenGetter;
/// etc.
...
}

Pointers and array class in javascript [duplicate]

This question already has an answer here:
Double-Queue Code needs to be reduced
(1 answer)
Closed 9 years ago.
Is there any way for me to shorten this code by using pointers?
I need to make a class that has mostly the same function as a given array class unshift,shift,push and pop but with different names.
var makeDeque = function()
{
var a= [], r=new Array(a);
length = r.length=0;
pushHead=function(v)
{
r.unshift(v);
}
popHead=function()
{
return r.shift();
}
pushTail=function(v)
{
r.push(v);
}
popTail=function()
{
return r.pop();
}
isEmpty=function()
{
return r.length===0;
}
return this;
};
(function() {
var dq = makeDeque();
dq.pushTail(4);
dq.pushHead(3);
dq.pushHead(2);
dq.pushHead("one");
dq.pushTail("five");
print("length " + dq.length + "last item: " + dq.popTail());
while (!dq.isEmpty())
print(dq.popHead());
})();
Output should be
length 5last item: five
one
2
3
4
Thanks!
Maybe I'm oversimplifying, but why not just add the extra methods you need to the Array prototype and call it directly?
I need to make a class that has mostly the same function as a given array class unshift,shift,push and pop but with different names.
I suppose you could add these "new" methods to Array.prototype.
Like this perhaps?
var makeDeque = (function (ap) {
var Deque = {
length: 0,
pushHead: ap.unshift,
popHead: ap.shift,
pushTail: ap.push,
popTail: ap.pop,
isEmpty: function () {
return !this.length;
}
};
return function () {
return Object.create(Deque);
};
})(Array.prototype);
DEMO
If it's still too long, you can always directly augment Array.prototype like others already mentionned. We agree that it's all experimental here and the only goal is to save characters.
!function (ap) {
ap.pushHead = ap.unshift;
ap.popHead = ap.shift;
ap.pushTail = ap.push;
ap.popTail = ap.pop;
ap.isEmpty = function () {
return !this.length;
};
}(Array.prototype);
function makeDeque() {
return [];
}
This can be compressed to 174 chars:
function makeDeque(){return[]}!function(e){e.pushHead=e.unshift;e.popHead=e.shift;e.pushTail=e.push;e.popTail=e.pop;e.isEmpty=function(){return!this.length}}(Array.prototype)
DEMO
Not sure why you need this, but my suggestions per best practice are:
Don't override the Array.prototype. The reason for this is because other libraries might try to do the same, and if you include these libraries into yours, there will be conflicts.
This code is not needed. var a= [], r=new Array(a);. You only need ...a = [];.
Ensure you are creating a real class. In your code, makeDeque is not doing what you want. It is returning this which when a function is not called with the new keyword will be the same as the window object (or undefined if you are using what is called as "strict mode"). In other words, you have made a lot of globals (which are usually a no-no, as they can conflict with other code too).
When you build a class, it is good to add to the prototype of your custom class. This is because the methods will only be built into memory one time and will be shared by all such objects.
So I would first refactor into something like this:
var makeDeque = (function() { // We don't need this wrapper in this case, as we don't have static properties, but I've kept it here since we do want to encapsulate variables in my example below this one (and sometimes you do need static properties).
function makeDeque () {
if (!(this instanceof makeDeque)) { // This block allows you to call makeDeque without using the "new" keyword (we will do it for the person using makeDeque)
return new makeDeque();
}
this.r = [];
this.length = 0;
}
makeDeque.prototype.setLength = function () {
return this.length = this.r.length;
};
makeDeque.prototype.pushHead=function(v) {
this.r.unshift(v);
this.setLength();
};
makeDeque.prototype.popHead=function() {
return this.r.shift();
this.setLength();
};
makeDeque.prototype.pushTail=function(v){
this.r.push(v);
this.setLength();
};
makeDeque.prototype.popTail=function() {
return this.r.pop();
this.setLength();
};
makeDeque.prototype.isEmpty=function() {
return this.r.length === 0;
};
return makeDeque;
}());
Now you could shorten this as follows, but I wouldn't recommend doing this, since, as it was well said by Donald Knuth, "premature optimization is the root of all evil". If you try to shorten your code, it may make it inflexible.
var makeDeque = (function() {
function makeDeque () {
if (!(this instanceof makeDeque)) {
return new makeDeque();
}
this.r = [];
this.length = 0;
}
makeDeque.prototype.setLength = function () {
return this.length = this.r.length;
};
for (var i=0, methodArray = [
['pushHead', 'unshift'], ['popHead', 'shift'], ['pushTail', 'push'], ['popTail', 'pop']
]; i < methodArray.length; i++) {
makeDeque.prototype[methodArray[i][0]] = (function (i) { // We need to make a function and immediately pass in 'i' here because otherwise, the 'i' inside this function will end up being set to the value of 'i' after it ends this loop as opposed to the 'i' which varies with each loop. This is a common "gotcha" of JavaScript
return function () {
var ret = this.r[methodArray[i][1]].apply(this.r, arguments);
this.setLength();
return ret;
};
}(i));
}
makeDeque.prototype.isEmpty=function() {
return this.r.length === 0;
};
return makeDeque;
}());
If you need to get the length by a length property, as opposed to a method like setLength() which sets it manually after each update, either of the above code samples could be shortened by avoiding the setLength() method, but you'd need to use the Object.defineProperty which does not work (or does not work fully) in older browsers like IE < 9.

javascript closure: protecting inner variable

I'm using the revealing module pattern somewhat like this:
var SomeClosure = function () {
var SomeInnerVar = 4;
function InnerGetTheVar() {
return SomeInnerVar;
}
function InitClosure() {
// there's something else happening here that requires me to
// wait for document.ready before initializing the closure
setInterval(IncreaseSomeInnerVar, 10000);
}
function IncreaseSomeInnerVar() {
SomeInnerVar = SomeInnerVar + 1;
}
InitClosure();
return {
GetTheVar: InnerGetTheVar
}
}
$(document).ready(function () {
SomeClosure = SomeClosure();
});
Now why is it that if in the console I type this:
SomeClosure.GetTheVar = 2;
SomeClosure.GetTheVar; // outputs 2!
Why doesn't the closure keep SomeInnerVar protected? I don't want the outer scope to be able to change SomeInnerVar like that.
Thanks for your suggestions.
Actually, SomeInnerVar is still 'protected', in this sense. However, you are overwriting SomeClosure's GetTheVar attribute with the value 2, which isn't 'protected' in the same sense. In other words, you aren't modifying SomeInnerVar, you're modifying GetTheVar.
Instead of just returning an object literal, use Object.defineProperty:
var out = {};
if ( Object.defineProperty ) {
Object.defineProperty(out, 'GetTheVar', {
value: InnerGetTheVar,
writable: false
});
} else {
out.GetTheVar = InnerGetTheVar;
}
return out;

Can you alter a Javascript function after declaring it?

Let's say I have var a = function() { return 1; }. Is it possible to alter a so that a() returns 2? Perhaps by editing a property of the a object, since every function is an object?
Update: Wow, thanks for all the responses. However, I'm afraid I wasn't looking to simply reassign a variable but actually edit an existing function. I am thinking along the lines of how you can combine partial functions in Scala to create a new PartialFunction. I am interested in writing something similar in Javascript and was thinking that the existing function could perhaps be updated, rather than creating an entirely new Function object.
You can do all kinds of fun stuff with javascript, including redefining functions:
let a = function() { return 1; }
console.log(a()); // 1
// keep a reference
let old = a;
// redefine
a = function() {
// call the original function with any arguments specified, storing the result
const originalResult = old.apply(old, arguments);
// add one
return originalResult + 1;
};
console.log(a()); // 2
Voila.
Edit: Updated to show this in a crazier scenario:
let test = new String("123");
console.log(test.toString()); // logs 123
console.log(test.substring(0)); // logs 123
String.prototype.substring = function(){ return "hahanope"; }
console.log(test.substring(0)); // logs hahanope
You can see here that even though "test" is defined first, and we redefine substring() afterwards, the change still applies.
Side note: you really should reconsider your architecture if you're doing this...you're going to confuse the crap out of some poor developer 5 years down the road when s/he's looking at a function definition that's supposed to return 1, but seems to always return 2....
So you want to modify the code of a function directly, in place, and not just reassign a different function to an existing variable.
I hate to say it, but as far as I have been able to figure it out - and I have tried -, it can't be done. True, a function is an object, and as such it has methods and properties which can be tweaked and overwritten on the object itself. Unfortunately, the function body is not one of them. It is not assigned to a public property.
The documentation on MDN lists the properties and methods of the function object. None of them gives us the opportunity to manipulate the function body from the outside.
That's because according to the spec, the function body is stored in the internal [[Code]] property of the function object, which can't be accessed directly.
I used something like this to modify an existing function whose declaration was not accessible to me:
// declare function foo
var foo = function (a) { alert(a); };
// modify function foo
foo = new Function (
"a",
foo.toSource()
.replace("alert(a)", "alert('function modified - ' + a)")
.replace(/^function[^{]+{/i,"") // remove everything up to and including the first curly bracket
.replace(/}[^}]*$/i, "") // remove last curly bracket and everything after<br>
);
Instead of toSource() you could probably use toString() to get a string containing the function's declaration. Some calls to replace() to prepare the string for use with the Function Constructor and to modify the function's source.
let a = function() { return 1; }
console.log(a()) // 1
a = function() { return 2; }
console.log(a()) // 2
technically, you're losing one function definition and replacing it with another.
How about this, without having to redefine the function:
var a = function() { return arguments.callee.value || 1; };
alert(a()); // => 1
a.value = 2;
alert(a()); // => 2
I am sticking to jvenema's solution, in which I don't like the global variable "old". It seems better to keep the old function inside of the new one:
function a() { return 1; }
// redefine
a = (function(){
var _a = a;
return function() {
// You may reuse the original function ...
// Typical case: Conditionally use old/new behaviour
var originalResult = _a.apply(this, arguments);
// ... and modify the logic in any way
return originalResult + 1;
}
})();
a() // --> gives 2
All feasible solutions stick to a "function wrapping approach".
The most reliable amongst them seems to be the one of rplantiko.
Such function wrapping easily can be abstracted away. The concept / pattern itself might be called "Method Modification". Its implementation definitely belongs to Function.prototype. It would be nice to be backed
one day by standard prototypal method modifiers like before, after, around, afterThrowing and afterFinally.
As for the aforementioned example by rplantiko ...
function a () { return 1; }
// redefine
a = (function () {
var _a = a;
return function () {
// You may reuse the original function ...
// Typical case: Conditionally use old/new behaviour
var originalResult = _a.apply(this, arguments);
// ... and modify the logic in any way
return originalResult + 1;
};
})();
console.log('a() ...', a()); // --> gives 2
.as-console-wrapper { min-height: 100%!important; top: 0; }
... and making use of around, the code would transform to ...
function a () { return 1; }
console.log('original a ...', a);
console.log('a() ...', a()); // 1
a = a.around(function (proceed, handler, args) {
return (proceed() + 1);
});
console.log('\nmodified a ...', a);
console.log('a() ...', a()); // 2
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
(function(d){function f(a){return typeof a==e&&typeof a.call==e&&typeof a.apply==e}function g(a,b){b=null!=b&&b||null;var c=this;return f(a)&&f(c)&&function(){return a.call(b||null!=this&&this||null,c,a,arguments)}||c}var e=typeof d;Object.defineProperty(d.prototype,"around",{configurable:!0,writable:!0,value:g});Object.defineProperty(d,"around",{configurable:!0,writable:!0,value:function(a,b,c){return g.call(a,b,c)}})})(Function);
</script>
This is a Clear Example based on a control timepicker eworld.ui
www.eworldui.net
Having a TimePicker eworld.ui where JavaScript is unreachable from outside, you can't find any js related to those controls. So how can you add a onchange event to the timepicker ?
There is a js function called when you Select a time between all the options that the control offer you. This function is: TimePicker_Up_SelectTime
First you have to copy the code inside this function.
Evaluate...quikwatch...TimePicker_Up_SelectTime.toString()
function TimePicker_Up_SelectTime(tbName, lblName, divName, selTime, enableHide, postbackFunc, customFunc) {
document.getElementById(tbName).value = selTime;
if(lblName != '')
document.getElementById(lblName).innerHTML = selTime;
document.getElementById(divName).style.visibility = 'hidden';
if(enableHide)
TimePicker_Up_ShowHideDDL('visible');
if(customFunc != "")
eval(customFunc + "('" + selTime + "', '" + tbName + "');");
eval(postbackFunc + "();");
}
Now
Using the code that you have saved before reassign the same source code but add whatever you want..
TimePicker_Up_SelectTime = function (tbName, lblName, divName, selTime, enableHide, postbackFunc, customFunc) {
document.getElementById(tbName).value = selTime;
if (lblName != '')
document.getElementById(lblName).innerHTML = selTime;
document.getElementById(divName).style.visibility = 'hidden';
if (enableHide)
TimePicker_Up_ShowHideDDL('visible');
if (customFunc != "")
eval(customFunc + "('" + selTime + "', '" + tbName + "');");
eval(postbackFunc + "();");
>>>>>>> My function >>>>> RaiseChange(tbName);
}
I've added My Function to the function so now I can simulate an onchange event when I select a time.
RaiseChange(...) could be whatever you want.
If you're debugging javascript and want to see how changes to the code affects the page, you can use this Firefox extension to view/alter javascripts:
Execute JS firefox extension:
https://addons.mozilla.org/en-US/firefox/addon/1729
You can change functions like other objects
var a1 = function(){return 1;}
var b1 = a1;
a1 = function(){
return b1() + 1;
};
console.log(a1()); // return 2
// OR:
function a2(){return 1;}
var b2 = a2;
a2 = function(){
return b2() + 1;
};
console.log(a2()); // return 2
Can you not just define it again later on? When you want the change try just redefining it as:
a = function() { return 2; }
const createFunction = function (defaultRealization) {
let realization = defaultRealization;
const youFunction = function (...args) {
return realization(...args);
};
youFunction.alterRealization = function (fn) {
realization = fn;
};
return youFunction;
}
const myFunction = createFunction(function () { return 1; });
console.log(myFunction()); // 1
myFunction.alterRealization(function () { return 2; });
console.log(myFunction()); // 2

Categories

Resources