I'm trying to access the 'data-*' attributes on an element in the browser in Haxe.
var element = document.getElementById('#someId');
var dataLabel = 'label'; //'data-label'
element.dataset[dataLabel] = 5;
That code (which works in plain javascript) generates two compilation errors in HaxeDevelop.
"String should be Int"
"For function argument 'data'"
How can I access element datasets in Haxe? Is there a known proper way to do it?
I ended up using the Element#getAttribute and Element#setAttribute methods to accomplish the same functionality.
var element = document.getElementById('#someId')
var dataLabel = 'label'; //'data-label'
element.setAttribute('data-' + dataLabel, 5);
I think this is a downside of how the array access operator works in Haxe.
Only abstract types can define array access, as the manual states here.
Haxe's DOMStringMap is just an extern class, so it can't have array access that uses String as a key instead of Int.
Now, there are ways around this. The untyped keyword seen here is one way your initial example could work. untyped isn't recommended though, it's a slippery slope to fragile code that you should avoid whenever possible.
Related
anyone know how to use Reflection in Node.js/Discord I want to replace
my direct map property call:
Userlist.get(uid).Strength
with a more programic one like
var DamangeStateName = "Strength"
Userlist.get(uid).DamangeStateName
which would get the Strength property like the direct one.
The main reason I need reflection is because sometimes the Key attribute is "Agilty" not "Strength"
And while my code everwhere else works with the string variable my Map of the player data can't use those same tricks and i need to be able to use reflection os it synergies with the rest of my code
JavaScript, being a prototype-based language where everything is basically just a hashtable of strings to values, neither has nor needs reflection machinery in the sense that Java or C# have.
I think you want something like this:
Userlist.get(uid)[DamangeStateName]
I believe you don't need reflection for your stated problem. You want to be able to handle two keys that mean the same thing.
Extend the target item (object/class) with a method to wrap the logic.
Userlist.get(uid).DamangeStateName
User.prototype.NormalizedDamangeStateName = function() { /* ... */ }
My User is an assumption. You'll need to identify the correct object by determining what Userlist.get(...) returns... Regardless, the concept should be sound.
Let's say I define a couple of classes. Then I create object of each class. I want to save the objects in a map keyed by their classes, so that I can retrieve the object based on its class.
(I'm using ES6 syntax, however the question may remain the same for legacy Javascript with class replaced by function)
// Alternative 1
class Apple {
}
class Banana {
}
let fruitInBag = {};
fruitInBag[Apple] = new Apple();
fruitInBag[Banana] = new Banana();
Alternatively I could also write following with the same outcome
// Alternative 2
class Apple {
}
class Banana {
}
const FRUIT_TYPE_APPLE = 1;
const FRUIT_TYPE_BANANA = 2;
let fruitInBag = {};
fruitInBag[FRUIT_TYPE_APPLE] = new Apple();
fruitInBag[FRUIT_TYPE_BANANA] = new Banana();
The second alternative is awkward, because I've to define and maintain the constants separate from class definitions. Therefore I would prefer the first one. But is the first approach inefficient? Is the Object smart enough to implement the first alternative efficiently?
The Keys in a Javascript object are always strings. No Integers and no functions (Classes). Use a ES6 Map for this!
I updated the code snippet in the question to correctly reflect the problem. After having done that and taking the suggestions from the comments and deleted answer, I did some analysis in Chrome devtools as follows.
As you can see from the picture, I defined a class in both ES6 (class Apple) and ES5 (function FnApple) manner. Then I kept them in regular ES5 object (mapA) and later ES6 map (mapB). In all the cases the browser stringifies the class definition completely and uses that string as a key. This works, because complete stringification of class makes it distinct. (I was afraid the stringification will the a dump [Object] string).
However this also means that using the class or function object as key will make the map key of indeterminately long size. In real world scenario when classes have long definitions, the key can go upto few KBs. Given this, it makes sense that one should use independently defined integers for keys in maps.
Update
In case of ES6 map, my test above is incorrect. I assigned the key-value to the mapB object using [] syntax, which makes it store the key-value as member of object like ES5 (because even ES6 Map instance is an object). The right way to set key-value on ES6 map is to use get(),set() API. After doing that I see that the type of keys is indeed function and not String for ES6 Map.
Sometimes I need enum-like structures for fixed sets of string valus in Node.JS. Basically an object with keys for each enum value, and each value is a string equal to the key:
var State = {FOO: 'FOO', BAR: 'BAR', SOME_REALLY_LONG_NAME: 'SOME_REALLY_LONG_NAME'};
This enables me to type State.S and the IDE will suggest State.SOME_REALLY_LONG_NAME, and typos are practically eliminated. I can do if (x === State.FOO) etc.
The above syntax is however obviously not ideal due to the duplication of each literal during creation of the set of values. So I can do for example:
var State = _.indexBy(['FOO', 'BAR', 'SOME_REALLY_LONG_NAME'];
However, as soon as the object is created indirectly, the IDE (WebStorm in my case) will be unable to suggest/auto-complete the values. Sure, with JavaScript we're not very spoiled with working auto-complete anyway, but in my case it bugs me because the whole purpose of my "enum" is to simplify usage of a fixed set of strings.
There are also several enum utilities to create more proper enums, but they will suffer from the same thing. Also, if what I need is basically a fixed set of strings, more proper enums would force me into writing State.FOO.key to get the string value.
Is there a clever way to accomplish these really simple {key: 'key'} mappings without having to type each key twice during creation, but while still maintaining the IDE's understanding of which properties exist in the object? I'm guessing WebStorm only performs a static code analysis which goes out the window as soon as a function is called? Or is there some clever trick?
It's been a while that i used Webstorm, and it's macro-utilities, but maybe u can write a simple macro that expands your String-Array into the desired Structure.
Otherwise, you could try the Typescript-plugin. First of All: every valid JS should be valid TS (don't know exactly about ES7, and if some of the ES6 may bug the plugin).
But TS has a Enum-implementation and webstorm should therefore give you autocompletition and type-safety
This question already has answers here:
What are the Alternatives to eval in JavaScript?
(11 answers)
Closed 7 years ago.
I work mainly with javascript, Jquery, knockout, etc
The thing that attracted eval() to me is
var a = 5;
var b = 10;
eval("a+b");
//Gives me output 15
Note: I work in cases where the value of a and b changes dynamically
In my work I'm dealing with a lot of dynamic objects from json, knockout, etc. So eval solves most of my problems.
But as I read I found there are so many issues with eval() like slowing down etc.
I searched a lot and haven't found any substitute for eval() when i have to evaluate equation obtaining as string into equation as object.
Can anyone suggest a plugin or function alternative to eval() keeping in mind the example i have given above
Problem:
I'm creating a Table from Json data using knockout mapping. So that what ever the format of json is the table is generated. I also calculate some field using knockout computed.
Right now I use hard-coded
self.Salary = ko.computed(function(){ return self.salaryEqn() && eval(self.salaryEqn()).toFixed(2); })
self.salaryEqn(salEqnTxt);
I want to execute these equations dynamic. I can create it dynamicaly as string but to eval them is the issue I'm facing.
I want solution for
Is there a way to calculate a formula stored in a string in JavaScript without using eval?
Like a formula
"self.Salary = ko.computed(function(){ return self.salaryEqn() && eval(self.salaryEqn()).toFixed(2); })"
Javascript is a very flexible language in this regard. There are very very few cases where eval() is the right answer to any given question, and it certainly isn't necessary here.
If your a and b variables are part of an object, you can access them with string subscripts:
ie myobj.a could also be referenced as myobj['a'].
From that, you can use a variable for the subscript, and thus you can reference any element in myobj dynamically -- ie:
var myobj = {a : 5, b : 10};
var dynamicProperty1 = 'a';
var dynamicProperty2 = 'b';
//gives 15.
alert( myobj[dynamicProperty1] + myobj[dynamicProperty2] );
No eval() required. You can build the dynamicProperty strings however you wish, so there's virtually infinite flexibility.
If your a and b variables are globals, JS globals in the browser are actually children of the window object, so you can still use this technique even with globals.
ie your global variable a could also be accessed via window.a or window['a'], with the latter option allowing you to do the same dynamicProperty trick described above.
Hope that helps.
do you mean that you want to calculate an equation that you can't know until you've received it?
if so see Calculate string value in javascript, not using eval .
in short:
eval CAN be used sometimes, but only if the equation string comes from a trusted source, and there you need something like evaluating dynamic equations.
maybe using window['var' + num] might be more useful for you. i don't quite understand your question sorry.
If you can collect them under an object like root = {a: 1, b: 2}, then
Object.observe(root, function(newValues) {
res = newValues.object.a + newValues.object.b;
});
can keep your res variable up to date whenever the a or b changes
It looks like you are trying to do dynamic equations created by a user.
For example it could be 'a+b+c' or 'dog+cat', and you don't know.
The best way to handle user-input equations like that is to parse the text into tokens and then translate the tokens into values/operands.
That's a lot of work, but there are pre-rolled solutions. For example, math.js
Check more alternatives to eval in this question and another one here which both might be considered a duplicate...
I understand this is a link only answer, but it will for sure be helpful to others searching for alteratives to eval.
I've been looking through the Raphael source – source
They appear to use
object[apply](obj, args)
which I am assuming is equivalent to
object.apply(obj, args)
Am I assuming correctly? And if so why do they do this?
Thanks
Edit
As #deceze says apply is a variable and therefore it is not equivalent. However, on line 38 they assign the string "apply" to the variable apply so this makes it equivalent. Why would you do this?
Using the dot notation is really just syntactic sugar for for object[propertyname], but it has one disadvantage, the property name cannot be minified.
By doing
var apply = "apply";
foobar[apply](.....
foobar[apply](.....
foobar[apply](.....
foobar[apply](.....
this can actually be minified to
var a = "apply";
b[a](.....
b[a](.....
b[a](.....
b[a](.....
And there's your reason, Raphael uses the [] notation in order to provide better minification.
In that case apply should be a variable which holds the name of a method, so this is a way of calling object methods with variable names. As such it is not equivalent to object.apply(), since this always calls the apply() method.
var apply = 'foo';
object[apply](); // calls object.foo()