Haxe Javascript: get and set property by its name without using Reflect - javascript

I want to be able to set and get a property value by its name without using the Reflect API.
I'm making some sort of a tween engine, animating hundreds of objects and the call to the function Reflect.getProperty and setProperty is taking quite some CPU time.
Is there a way to bypass the Reflect API without having to inject raw javascript inside my Haxe code ? (so it can also be used on other platforms than js)
So instead of doing this:
finalValue = Reflect.getProperty(object, propertyName);
I would like to be able to do this:
finalValue = object[propertyName];
thanks.

What about going untyped?
// set
untyped object[propertyName] = 15;
// get
var value = untyped object[propertyName];
Try it yourself: http://try.haxe.org/#5b61e
Warn Going untyped lets you omit the type system and is more error prone. If you use instances with Haxe properties (getter/setters) it might give unexpected results. That's why using Reflect is considered safer.

You need to be careful when using "untyped" with properties that are getters/setters and standard properties, because the calls are slightly different.
eg:
// set
untyped object["set_" + propertyName] = 15;
// get
var value = untyped object["get_" + propertyName];
Typically what we do with our tween library is do a check up front when the property is mapped to see if it is a getter/setter and store this information for runtime use.

Related

Partial garbage collection of objects possible? (server-side JS)

Assume a server-side JavaScript environment, that provides a function like so:
var parseIsoDuration = /... complex regex .../
function dateDiff(date, isoDurationStr){
var duration = parseIsoDuration.exec(isoDurationStr);
return timeLibrary.add(date, duration);
}
That function will be called from outside, on hundreds of dates, but mostly the same ISO duration. Because RexExp parsing is not a cheap operation, an application-level cache could be implemented:
var parseIsoDuration = /... complex regex .../
var durationCache = {}
function dateDiff(date, isoDurationStr){
var duration;
if (durationCache[isoDurationStr] === undefined){
duration = parseIsoDuration.exec(isoDurationStr);
durationCache[isoDurationStr] = duration;
} else {
duration = durationCache[isoDurationStr];
}
return timeLibrary.add(date, duration);
}
The problem: the server may run for a year straight, and the cache object never goes out of scope. If the function is called with a lot different ISO duration strings, the cache will grow over time and never reduce its size.
Is there a way to tell V8 that it may clear "old" entries from the cache object as needed (i.e. has grown too large)? Or at least make it clear it entirely as the need arises? (Solution may depend on ES6/7 features)
ES6 WeakMaps sound interesting, but they accept objects as keys only. Wrapping a string in an array to make it an object will not work, because doing that again will result in a different object. I would need something like Symbol(str), but that returns an identical reference for two identical inputs (Ref(str) === Ref(str)).
edit: There's actually Symbol.for("str") === Symbol.for("str"), but it's not accepted as WeakMap key.
I'm also not sure when entries would actually be garbage-collected in case of a WeakMap - it might be more or less immediately, because there would be no reference to the object right after it was added to the WeakMap. So a double no.
Unsetting individual keys would require additional book-keeping when they were added and some algorithm to determine a sensible TTL.
Is it necessary to cache the RegExp results even? Is there some built-in cache? For literal expressions or if created via constructor only, or both?
What you are talking about sounds like Java's SoftReference and no, there is nothing like this in v8. Instead you should manage cache yourself or use one of the modules like lru-cache

Set property value

I need to change the value of a javascript property but nothing seem to work. This is what I tried:
var test = allProducts[i]; // allProducts[i] comes from the database
console.log("TestProp BEFORE = " + test.get("TestProp"));
This prints out my TestValue.
Now I try to change the value and I tried all 3 syntax suggestions below (not at the same time of course):
test.TestProp = "kisses";
test["TestProp"] = "kisses2";
test['TestProp'] = "kisses3";
console.log("TestProp AFTER = " + test.get("TestProp"));
But this once again prints my TestValue.
What am I missing? Could it be that the object is somehow locked?
Usually, when you see something like SomeObject.get('attrName') in the code, it's a sure-sign SomeObject is actually not a plain JS object. Many popular frameworks (including Backbone) and libraries (jQuery) use the following approach: instead of enhancing native/host Objects, they put those into properly formed containers ('favor composition over inheritance' principle).
The bottom line is that while it might be possible to assign properties to these wrapper-objects (with bracket or dot notation), it's meaningless. Instead one has to use proper setter methods - most commonly, it's set().
In your case, that resolves to...
test.set('TestProp', 'some_kisses_value');
... where the first param is the name of attribute/property, the second one is its value.

Javascript prototype reflection function

I'm not exactly sure of the name of what I'd like to do but it goes like this:
Currently, I have a bunch of variables in my javascript context that look like $A126 or $B15.
Before running, I have to load in all 9000 of these variables and their current values so later parts of the code can just reference $xxx for the value.
The preloading is not efficient at all and is causing a bottleneck.
As there is a substantial amount of code that uses this $xxx notation I was wondering if it would be possible to make a universal change to $.xxx where $ is a function that performed a lookup of the value passed to it via what was after the period.
So $.xxx would be analogous to GetItem(xxx)
This is for a javascript environment in C# using clearscript, though I don't think that would impact the answer.
It looks like
function Field(val){
var value = val;
this.__defineGetter__("xxx", function(){
return value;
});
this.__defineSetter__("value2", function(val){
value = val;
});
}
var field = new Field("test");
console.log(field.xxx)
---> 'test'
That is almost an example of what I'm looking for. The problem is that I would like to have a general defineGetter that doesn't look for a particular getter by name.

Dynamically Setting a JavaScript Object's Method's Source

I've recently been working on a nice little JavaScript game engine that works a lot like Game Maker, but lets people create basic JavaScript games within a browser. Every instance of every object will have it's own preset methods, which the runner will iterate through and execute. I'm trying to find a way to let the user / creator dynamically edit any of the methods source code. When I say 'preset methods', I mean blank methods stored under specific preset names within the objects / object instances. Here's a basic example:
var newObject = object_add("object_name"); // Adds a new object 'blueprint' and returns the reference.
The function object_add(); creates a JavaScript object, and adds a number of preset methods to it, such as:
create
destroy
step
draw
.. and many more
Each of these methods will have no code in them to start with. I need to let the creator dynamically change any of the methods source code. I could simply overwrite the variable that points towards the method, with a new method, but how can you set method's source code using a string?
I know that something like:
newObject.create = function(){textbox.innerHTML};
definitely wouldn't work. Any ideas?
Many thanks,
Dan.
Looks like you want to use eval function, but it's generally a bad idea.
The answer was found at: Creating functions dynamically in JS
Here's the answer (copied from the other page).
Well, you could use Function, like in this example:
var f = new Function('name', 'return alert("hello, " + name + "!");');
f('erick');
//This way you're defining a new function with arguments and body and assigning it to a variable f. You could use a hashset and store many functions:
var fs = [];
var fs['f1'] = new Function('name', 'return alert("hello, " + name + "!");');
fs['f1']('erick');
//Loading xml depends if it is running on browser or server.
Thanks, #CBroe https://stackoverflow.com/users/1427878/cbroe

Change meaning of ["foo"] in Javascript?

I'd like to make foo["bar"] return the bar field value normally, but if it doesn't exist, look it up in another object to find it there. Is it possible to replace how [] works?
Why? I am porting a 6 year old Javascript application to AngularJS. In the existing app, there's (of course) one global variable (let's call it i2) that's used as a namespace that has everything in the app attached to it.
i2.models.fooModel.bar += 1; //and the rest of the app is similar
If that's not enough responsibility, i2 is also used as a registry of application "cells" like so:
var myCell = i2["MyCell"];
I'm breaking the global's fields into AngularJS services. The cell lookup feature is also broken out into another servicer "cell registry" service. Since this application has existing plugins that we'd like to be backwards compatible with, I'd like the code in the existing plugins like:
var myCell = i2["MyCell"];
... to still work (though deprecated). Is there a way I can replace the [] function in i2 to look up the field in i2, and if it doesn't exist, look it up in another object (the cell registry)?
No, you cannot directly and literally change the meaning of
i2["MyCell"]
because this is the design of the language and that typically can't be changed (and it would be terrible if you could). However, you can do something like this:
function lookupVar(key) {
var value = i2[key];
if(typeof value !== "undefined") {
return value;
}
// do whatever you want to do now that it couldn't be found
}
var myCell = lookupVar("MyCell");
Of course this can be extended to handle other things than just a single variable i2. It might also not be needed at all and a simple
var myCell = typeof i2["MyCell"] !== "undefined" ? i2["MyCell"] : somethingElse["MyCell"];
might be enough (though it contains annoying duplication). If you know that if they key exists in i2["MyCell"], it won't be a falsy value (0, "", false, …), then this will suffice
var myCell = i2["MyCell"] || somethingElse["myCell"];
Though it's not very future-proof.
Yes, you can use getters (don't work in IE8) or Proxy (not recommended for production code)...
Is there a way I can replace the [] function in i2 to look up the field in i2, and if it doesn't exist, look it up in another object (the cell registry)?
Or just think about prototypes.

Categories

Resources