I had an incident in my Angular 6 application the other day involving some code that looked like this:
console.log('before:', value);
this.changeValue(value);
console.log('after:', value);
changeValue() modifies value in some way. I expected to see the unmodified value in the console before the call to changeValue() then the modified value after. Instead I saw the modified value before and after.
I guess it proved that my changeValue() function worked, but it also indicated to me that console.log() is asynchronous--that is, it doesn't print out the value to the console right away; it waits for a bit... and when it finally does print the value, it's the value as it is at that moment. In other words, the first call to console.log() above waited until after the call to changeValue() before printing, and when it did, the value had already changed.
So am I correct in inferring that console.log() is asynchronous. If so, why is that? It causes a lot of confusion when debugging.
No, console.log() is synchronous. It's actually your changeValue() function that doesn't work the way you think.
First, JavaScript doesn't pass variables by reference, but by pointer to object (as do many other languages). So although the variable value inside your function and the variable value in the outer scope both hold the same object, they are still separate variables. Mutatin the object affects both variables, but direct assignments to one variable do not affect the other. For example, this obviously wouldn't work:
function changeValue(x) { x = 123; }
Second, in JavaScript the shorthand assignment a += b does not mutate the existing object stored in a. Instead it works exactly like a = a + b and assigns a new object to the variable. As mentioned above, this only affects the variable inside the function, but doesn't affect the one outside, so your changes are lost after the function returns.
More examples:
function willwork(obj) { obj.foo = "bar"; }
function willwork(obj) { obj["foo"] = 1234; }
function willwork(obj) { obj.push("foo"); }
function wontwork(obj) { obj = "foo"; }
function wontwork(obj) { obj += 123; }
function wontwork(obj) { obj = obj + 123; }
Related
I am searching for an answer/solution why my JS function with get attribute() doesn't work in live mode? In GTM debug mode, everything is ok, all events based on this function are sent normally.
Thank You
function() {
var x = Array.prototype.slice.call(document.querySelectorAll("div[data-product]"))
for (i=0; i< x.length;i++) {
if(Number.isInteger(i/2) && Number.isInteger(i/3)) {
x[i].setAttribute("seen-product", "");
}
}
return undefined;
}
This looks like a variable template. In preview mode, all variables are evaluated, no matter if they are used or not. In the live version, variables are only evaluated when they are being used (in a tag, template, or trigger).
Since you do not use the variable to return any data, I suspect that you not actually use it anywhere, so it would not be evaluated (i.e. the function would not be run) in live mode.
A variable changing things instead of returning a value is called a "side effect". Variables should not have side effects (read e.g.here: https://www.simoahava.com/analytics/variable-guide-google-tag-manager/ (half way down the page under the headline "Variables must never have side effects"). You could do this e.g. in a custom tag.
If I use this code, the function returns me null as the Resolve worked sometimes and failed sometimes (based on when this was called)
Platform::WeakReference wr(this);
Windows::Foundation::Collections::IAsyncOperation<Object1^>^ asyncTask =
concurrency::create_async(
[wr, timeoutMS](concurrency::cancellation_token token) -> Object1^
{
if (auto refToThis = wr.Resolve<CurrentClass>())
{
// Do something
}
else return null; // The code took this path if the call was made
// immediately, if the call was made from inner
// page or
// even after 5 sec in Main Page init – It always
// worked
}
Where as if I pass this reference in lambda expression it always resolves
Platform::WeakReference wr(this);
Windows::Foundation::Collections::IAsyncOperation<Object1^>^ asyncTask =
concurrency::create_async(
[this, wr, timeoutMS](concurrency::cancellation_token token) -> Object1^
{
if (auto refToThis = wr.Resolve<CurrentClass>())
{
// Do something - It resolves always now
}
else return null;
}
Any clue why this happens? I am new to C++/Cx, I read that its not good to pass this ref in lambda expressions, but the resolve fails if I dont pass
Why the second example always work:
You are capturing this in the lambda closure [], means you are doing a copy of this inside the lambda scope. Since this is probably a ref class it means you increment the reference counter of the pointer on it, meaning this will not be destroyed. When resolving the weak reference, since this is still alive, you are able to retrieve it from the weak reference.
In the first example, you are passing only the weak reference to the lambda closure, since you are probably working with some UI element, if this is destroyed, the weak reference resolution will return nullptr.
You should either pass a weak reference or directly this in the lambda closure, but in the case where you pass this, you should ensure that you will be called by this lambda in order to avoid keeping a reference on an object causing it to never be deleted, creating a memory leak.
I understand what var keyword means inside functions, but now I am trying to understand what is the purpose of var keyword outside function. I made some tests (see below) and it makes no difference. So when it makes any difference if you put var keyword outside functions?
1.
example = 1;
function test(){
var example = 2;
}
test();
alert(example); //alert 1 no matter if example=1 or var example=1 before function
2.
example = 1;
function test(){
example = 2;
}
test();
alert(example); //alert 2 no matter if example=1 or var example=1 before function
3.
var example = 1;
function test(){
alert(example);
}
test(); //always alert 1, no matter if var example=1 or example=1 before function
The keyword var declares a variable in the current scope (well, technically in the same closure but lets keep it simple for now)
Since both your function (test) and your variable (example) were declared in the 'global' scope they both have access to each other meaning the function test could access the variable example
In your first example you have declared a new var called example, this means that now when you call the var example (inside the method) it will reference this variable instead.
There is a difference!
See this answer https://stackoverflow.com/a/1471738/211070, but basically:
Since variable declaration creates property with DontDelete flag, the
difference between var x = 1 and x = 1 (when executed in global scope)
is that former one - variable declaration - creates DontDelete'able
property, and latter one doesn't. As a consequence, property created
via this implicit assignment can then be deleted from the global
object, and former one - the one created via variable declaration -
can not be.
There isn't a real difference in the global space as long as you're not in strict mode.
That said, you should still use var as good programming practice. Auto-defined variables are evil.
I believe if you put a var within a function it can only be used within that function alone like a PHP IF statement where as if you put a var outwith the function then it can be used in more than one function - like a variable within that scope of the page.
The var-Keyword does exactly the same when used within functions as it does outside of them: It binds a new variable to the current scope. In the case of a function the scope is the function. Outside of a function the global scope is used. In a browser, that global scope is usually the window-Object.
lg,
flo
The var keyword declares a variable in the current scope. Without it, you are automatically declaring a new property on the window object, or accessing and modifying a same-named variable in a higher scope if one exists. In your example, there is only the global scope and the inner function scope, so var example = 1 in the global scope is, for your purposes, technically identical to just example = 1. However, if all of your above code was executed inside some other function scope, the first 2 examples would declare a global example property, whilst the third would declare a variable local to that scope.
1) The reason this alerts 1 is because even though you are invoking the test() function beforehand, it itself is invoking and creating its own closure and declaring a separate var example = 2; inside of it. (So your alert can't see it, it only sees 1). Now if you did: return example = 2; you would notice alert(example) === 2. This is because you brought the example out from the closure and it effected the previous example variable.
example = 1;
function test(){
var example = 2;
}
test();
alert(example);
2) Here, you aren't creating a new variable inside of the function, so it is able to access (through closure) the variable example outside of it, and change it to 2.
example = 1;
function test(){
example = 2;
}
test();
alert(example); //alert 2 no matter if example=1 or var example=1 before function
3) This last one is a good example of how 'closure' works here. Variables, unlike let's say the function () must be declared above something that tries to access them. Functions on the other hand don't. So although var example = 1 might be below the function test() { } itself, it doesn't matter. What's important is that it is declared before the CALL to test(). This is when the closure is created and it wraps itself around any variables etc it can see/access.
// so this ...
var example = 1;
function test(){
alert(example);
}
// and this work ...
function test(){
alert(example);
}
var example = 1; // <-- notice it's still above the test() func call, it can still see example
test(); //always alert 1, no matter if var example=1 or example=1 before function
// if var example = 1; was down here below it, it would alert "undefined", this is because
// the variable was not available within the scope when test() was called.
I'm looking for method to create Vector and push some values without defining variable Vector. For example:
I have function:
public function bla(data:Vector.<Object>):void { ... }
this function expects Vector as parameter. I can pass parameters this way
var newVector:Vector.<Object> = new Vector.<Object>();
newVector.push("bla1");
newVector.push("bla2");
bla(newVector);
Can I do it in one line in Flex? I'm looking for something like:
bla(new Vector.<Object>().push("bla1").push("bla2"));
I've also tried this:
bla(function():Vector.<Object> { var result:Vector.<Object> = new Vector.<Object>(2, true); result.push("bla1"); result.push("bla2"); return result; });
But it complains:
1067: Implicit coercion of a value of type Function to an unrelated type __AS3__.vec:Vector.<Object>...
Thanks
You can't chain Vector.push() calls as they return uint's -- the new vector length.
The coercion problem, on the other hand, happens because you are passing a function to the bla function, which expects a Vector.<Object>.
You could fix that easily:
bla((function():Vector.<Object> {
var result:Vector.<Object> = new Vector.<Object>(2, true);
result.push("bla1");
result.push("bla2");
return result; })()
);
However, there's already a top level function in AS3 that helps you creating vectors.
The Vector() function expects either an Array or a Vector and returns a Vector. So, for example, you could use:
bla(Vector.<Object>(['bla1', 'bla2']));
Visit the AS3 Reference for more info.
EDIT: I forgot to mention that the fix on the function approach was simply adding a () to it, meaning we actually called the anonymous function and passed it's return to the bla function.
Just want to mention push takes multiple arguments, and each one is pushed onto the stack sequentially:
function getVector():Vector.<String>
{
var newVector:Vector.<String> = new Vector.<String>();
newVector.push("blah1","blah2","blah3","blah4");
return newVector;
}
I'm not really sure why you'd need to do it one line. You could always write a wrapper class if you happen to do this often. The wrapper class could have a push method that returns a reference to the original object so you can use the first method you wanted.
You could also write a helper function which created a new vector and added the elements to the vector and then returned the vector.
Is there a particular need for wanting this on one line?
You are not able to do this:
bla(new Vector.<Object>().push("bla1").push("bla2"));
because the "push" method returns the length of the Vector. So what this means is that you are trying to push the String "bla2" onto the int 1. This won't work!
And your next example is passing a function to the bla method, not calling that function and passing the returned Vector.
Also you are saying the Vector type is "Object" but you are passing in Strings. You should do this:
Vector.<String>
You could do something like this:
function getVector():Vector.<String>
{
var newVector:Vector.<String> = new Vector.<String>();
newVector.push("bla1");
newVector.push("bla2");
return newVector;
}
bla( getVector() );
What is the syntax to declare a type for my compare-function generator in code like the following?
var colName:String = ""; // actually assigned in a loop
gc.sortCompareFunction = function() : ??WHAT_GOES_HERE??
{
var tmp:String = colName;
return function(a:Object,b:Object):int { return compareGeneral(a,b,tmp); };
}();
Isn't "Function" a data type?
In order to understand what the data type is, we must know what the intended outcome of the return is. I need to see the code block for compareGeneral, and I still don't believe this will help. You have two returns withing the same function "gc.sortCompareFunction", I believe this is incorrect as return gets a value and then acts as a break command meaning the rest of the anything withing the same function block is ignored. The problem is that I don't know which return is the intended return, and I don't know that flash knows either. You can use * as a data type, but this should only really be used in specific situations. In this situation I believe you need only the one return value that merely returns whatever the value of compareGeneral.
Now if this is a compareGenerator it really should either return a Boolean TRUE or FALSE, or a int 0 or 1, lets use the former. Also I believe we can use one less function. Since I have not seen all of your code and I am not exactly sure what your trying to accomplish, the following is hypothetical.
function compareGeneral(a:object,b:object):Boolean
{
//Check some property associated to each object for likeness.
if(a.someAssignedPropery == b.someAssignedPropery)
{
return true;
}
return false;
}
var objA:Object = new Object();
objA.someAssignedProperty = "AS3";
objB.someAssignedProperty = "AS3";
compareGeneral(objA,objB);
In this case compareGeneral(objA,objB); returns true, though we haven't done anything useful with it yet. Here is a way you may use it. Remember that it either returns a value of true or false so we can treat it like a variable.
if(compareGeneral(objA,objB)) //same as if(compareGeneral(objA,objB)) == true)
{
trace("You have found a match!");
//Here you can call some other function or set a variable or whatever you require functionality wise based on a match being found.
}
else
{
trace("No match could be found!");
}
I hope that this is able to help you understand data types and return values. I do not know what you were doing with tmp, but generally functions that return a value deal with that one thing and only that thing, so it is best that the compare function compare one thing against the other and that be the extent of the call. Whatever functionality you require with tmp can go inside its own function or method, and be called when needed.