Binding Two Variables Together - javascript

qpo.activeGame.teams.blue
qpo.blue
Above are two references/identifiers. I create an object and have the first identifier (qpo.activeGame.teams.blue) point to it. Then, I want to have the second identifier (qpo.blue) point to the same object (which will change, and both identifiers need to keep pointing to the newest version of that object.)
Do I achieve this like this?
qpo.blue = qpo.activeGame.teams.blue
Or, is it more complicated?
I apologize for my lack of a computer science background. (Is data binding even the right term for this?)

You cannot cause two variables to become "married" so that an assignment to one is effectively an assignment to the other. (There's one weirdness that could possibly be construed as that situation, but it's not something you'd ever do in practice.)
However, if two variables (or object properties) refer to the same object, then changes to the constituent properties and sub-properties of that object will be visible via either reference. That's because a reference to an object is, in fact, just a reference. Two variables sharing the same reference value both refer to the same single object.

Related

How to create an opaque object in JavaScript?

I want to create an object and hide some of its properties.
How do I do this?
For example, to this object:
console.log(new Path2D()); // Path2D {} empty*
In this image, the console is very crowded and confusing.
It depends why you want to do that, it's hard to give a precise answer without more details. In most cases there is no need to hide properties (what are you afraid of?), but here are two ways if you really need to:
you can use Symbol properties (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol), that is new Path2D() would return an object where the keys are not strings but Symbols. This has the advantage that a user of this object can add its own properties to the object without risking clashing with internal properties that your library relies on. It is still possible for someone to access those properties, though, if they really want to.
You can hide things in a local variable in a closure. It is much more hidden than with Symbol properties, but it might require thinking about the API differently.

Javascript reference object by an identifier or reference it directly?

I am creating quite many objects in Javascript, which I need to be able to reference to retrieve later, for example through an array. Now I am wondering how to save the object reference in the array.
The objects will interract with an external library, which can function either with object IDs or the object itself. I know Javascript treats object variables like pointers and not object copies, so is it safe to reference the objects directly ?
At first I was thinking "if I save the IDs of the objects, that would keep memory usage low", but is this true ? How much memory does an object variable* consume versus an integer variable ?
*the pointer to the object, not the object data
Also, if saving the objects directly is the way to go, is it ok to use array.push() to add the new object to the array ? Is array.push() creating a copy or does it work like a variable ?
Yes, you can reference the objects directly. If you really care about memory usage, I'd say the way of passing the ids will use more memory since you'll have to maintain another set of mappings.
Passing the objects directly will let the JavaScript engine to work directly with the object references. That's not affecting the memory usage, as long you don't to any cloning.
I believe the relevant question is weather or not saving an integer and using that as an identifier later is more effective than saving a reference to the object.
I'd go with the reference in an array. the size of a reference vs a number is going to be negligible.

javascript: can I do the equivalent of call but for a property?

I understand that call allows you to pass in an object in place of the 'this' that the method was invoked upon.
"abc".charAt.call("defgh",1);
"e"
But suppose I want the length property to be applied to that object
I can't say
"abc".length.call("defgh");
i'll get an error
Can I do it for a property e.g. length?
Added [since this addition, the 3 answers I see to this question are all good]
It appears some people have thought I was questioning how to invoke a property (which makes no sense). I am not.
And some have thought that I was suggesting that "z".charAt("asdf",0) is better than "asdf".chatAt(0) I am not.
What I am saying is that you can use call on a method to cause it to execute/evaluate on a different object. I could give a more useful example if you really need to see a more useful example.
[1].forEach.call("asdf",function(x){console.log(x+x);});
or
Array.prototype.forEach.call("asdf",function(x){console.log(x+x);});
So forEach can be more concise than a For loop.
So there, even though initially the example I gave for call was not useful, lo and behold, a useful example can exist.
So too, that may be the case with a property
I may want to apply a different object, for a property e.g. 'length' to evaluate on. That should not be impossible in theory(as one answerer suggested before deleting his answer). I don't have a particular use I can come up with that would be beneficial for evaluating a property on a different object, but it should not be impossible.
And just because I don't have a use for it, doesn't mean it should be thrown away. Remember that prior to giving a good usage for call on a method, some said it's pointless, then I gave potentially be a use for it. And that's no argument for it being impossible in theory/principle.
There is no equivalent way to take the functionality behind the .length property and apply it to a different object. Javascript does not have that feature.
Part of the reason is because a property can be just a static value stuck in a property on an object, so there's meaning to evaluate the "ttt".length property on another object. You can access the .length property on another object, but there's no semantic meaning to using the "ttt" object's .length property on another object. The only semantic thing you have is a name. You can use that name on another object as in obj2["length"] or obj2.length, but all you've borrowed from the "ttt" object is the name of the property. It's different with functions that are methods on objects. They are executable code that is passed a this value as context. .call() allows you to take any function (whether a method or not) and specify the value of this when it is executed by using .call(). That's why you can take a method on one object and call it in the context of another object. But, a plain (non-function) property just doesn't have that capability. There's nothing to "execute" in a different context. The property just has a name and a value. You can use the name on any other object, but there's no code you can execute in a different context for that property.
Also, keep in mind once you've retrieved "ttt".length, all you have at that point is a number. That number has no context about where it came from so there isn't really any way to apply the logic that generated that number to some other object.
As for .call(), it is a method of a Function object. So, you can only use it with functions. That's why it works fine with the .charAt() method because that's a function.
But the .length property is not a function (it returns a number) so it does not have a .call() method. That's why what you're trying does not work.
Because .length is not a function, you cannot take the functionality behind it and arbitrarily apply it to another object the way you tried to do with .charAt(). That simply isn't supported with non-functions.
You can, of course, just use the .length property that is already on your other string as in:
console.log("defgh".length);
If you can describe what you're really trying to accomplish, we can probably offer a different way to do it that is supported, but your current description of what you're trying to do does not really seem logical so it's hard to figure out what the actual problem is you're trying to solve.
FYI, there's really no reason to have done this either:
"abc".charAt.call("defgh",1);
You might as well just do the much more direct scheme of calling a method on the desired object:
"defgh".charAt(1); // "e"
It is technically impossible in JS since after the "abc".length expression is evaluated the property name is lost (and only the value is carried over next), hence you cannot re-apply it to the another context.
So even if you extended the primitive type wrapper prototypes - you still would not be able to extract something more but the value.
So it just does not fit into the current language specification.
The purpose of call and apply is to set the this object within a function call. They are necessary for calling functions as methods of objects that don't have that method. However, the caveat is that the object supplied as this can be used by the function.
Applying that principle to properties means trying to read a property of an object that doesn't have it, using the algorithm from some other object that does.
If you consider the length property that many objects have, the algorithm for determining it is very different for each type of object:
String: number of characters
Number: undefined
Function (built–in): as defined in ECMA-262
Function (native, not built–in): number of arguments
Array: whatever has been set, but always at least 1 greater than highest index if there is one
and so on. So which should be the generic version returned of there was an equivalent of call for properties? So There is a very large matrix of property algorithms and objects to apply them to.
However don't despair! If you wish to use, say, the String version of length for some object, then convert it to a string and get its length. E.g. the string version of length for an array might be:
someArray.join('').length;
So you can define the algorithm for such properties any way you like. ;-)
PS. getters allow you to do this on a per object basis, but they can't be shared.

Correct Approach: Always Passing all Variables as Function Arguments?

I am thinking about the correct programming approach:
As I write my JavaScript code, I refer to many dynamically created global objects and variables from within my functions and objects, although I did not pass them as function arguments. This way, I am losing function versatility and independence, as the functions and objects depend on another global objects in my application. I am aware of this fact, however, my objects/functions often need many variables to work with.
Would you advice, whether I should always strive to pass all the variables and objects as function arguments? This way it will be clear, what variables the function needs, and if I supply the correct arguments, the function will always work
Alternatively, don't I need to be so strict, and as long as my functions/object work, despite they refer to global objects, do not I need to bother with this question anymore?
I need to know correct programming approach, so I do not get used to wrong things.
Yes you want to use global variables as little as possible. If as a result you find that you're passing a lot of parameters into each function then you should look at the parameters and ask what they have in common. Quite often, adding additional objects helps. You can combine parameters into instance variables of an object and pass the one object. Then, rather than extracting the instance variables, you delegate operations to that object.
For example, suppose you have the following code:
drawLine(fromX, fromY, toX, toY, thickness, color, canvas)
You can create a Point to hold the x,y values and a graphics context to hold the thickness, color and canvas. The resulting call becomes:
drawLine(from, to, context)
You've reduced the number of parameters and created reusable objects that contain commonly used operations.

Which is the fastest way of accessing JavaScript object?

I want to know what is the best way of accessing a JavaScript object, dot operator or []:
data.property or data["property"]?
Both are more or less the same, except in Safari in which case dot notation is significantly faster.
You're much better off concentrating on DOM manipulation, DOM size, and CSS complexity as major sources of performance problems in Javascript applications.
That said, if you are doing a lot of property access in a loop, a local variable will be much faster than either property access or array lookup. Copy an object property into a variable if it is going to be accessed repeatedly. Do not use the "with" statement, incidentally. It can slow down local variable access by introducing another object into the scope chain.
Variables defined in local scope will be accessed far more quickly than those in global, as the Javascript engine first looks through all of the variables locally, then checks all of the variables in global scope. Scopes can nest as well, so the farther up the nesting chain the variable resides the longer it will take to find. That's why it's best to cache something like "document" in a local variable if it is going to be accessed more than once.
Both are the same speed. Also, if you are concerned with the level of speed in accessing a field attached to a reference, I think you might be going down the wrong path to tuning your code.
I would venture to guess that data.property is ever-so-slightly faster, but it may be difficult to measure. Indeed, JSPerf shows no distinction
The best way of accessing object properties has generally nothing to do with speed. Dot operator is used for syntactic sugar (I.E. this.hasElements() is easier to read, write and process in your brain than this["hasElements"]()) whenever possible and the brackets are used when the key name is a variable or has illegal characters.

Categories

Resources