why the program's result is undefined? - javascript

var foo = {};
foo.c = foo = {};
console.log(foo.c);
why the result is undefined?
i thought it is supposed to be '[object Object]'

Strange things are happening here in the assignments:
foo.c = (foo = {})
The reference to foo.c is resolved first and points to the old foo object, before the inner expression is evaluated where foo is re-assigned with the {} emtpy object literal. So your code is equivalent to
var foo1 = {};
var foo2 = {};
foo1.c = foo2;
console.log(foo2.c) // obviously undefined now
You can also try
var foo = {}, old = foo;
foo.c = foo = {};
console.log(old, foo, old.c===foo); // {c:{}}, {}, true

JavaScript engine splits such assignment:
a = b = c = 1;
As follow:
a = 1;
b = 1;
c = 1;
And not as:
c = 1;
b = c;
a = b;
There is a slightly but important difference – mostly, it involves getters, please check Multiple variable assignments in one row for further details – and that's mostly why your code doesn't behave like expected, because the initial expectations are based on false assumptions.

Related

how to get more than one return with eval method? [duplicate]

I am trying to return two values in JavaScript. Is this possible?
var newCodes = function() {
var dCodes = fg.codecsCodes.rs;
var dCodes2 = fg.codecsCodes2.rs;
return dCodes, dCodes2;
};
No, but you could return an array containing your values:
function getValues() {
return [getFirstValue(), getSecondValue()]
}
Then you can access them like so:
const [first, second] = getValues()
This is called destructuring assignment and is supported by every major JS environment. It's equivalent to the following:
const values = getValues()
const first = values[0]
const second = values[1]
You can also return an object if you want to assign a name to each value:
function getValues() {
return {
first: getFirstValue(),
second: getSecondValue(),
}
}
And to access them:
const {first, second} = getValues()
Which is the same as:
const values = getValues()
const first = values.first
const second = values.second
It is highly recommended to return an object instead of an array unless the values make sense as a simple tuple, e.g. a coordinate pair [x, y]. With an array, it's easy to forget which value is which, it's harder to add more values later, and it's marginally more difficult to correctly type with TypeScript or JSDoc.
You can do this from ECMAScript 6 onwards using arrays and "destructuring assignments". Note that these are not available in older Javascript versions (meaning — neither with ECMAScript 3rd nor 5th editions).
It allows you to assign to 1+ variables simultaneously:
var [x, y] = [1, 2];
x; // 1
y; // 2
// or
[x, y] = (function(){ return [3, 4]; })();
x; // 3
y; // 4
You can also use object destructuring combined with property value shorthand to name the return values in an object and pick out the ones you want:
let {baz, foo} = (function(){ return {foo: 3, bar: 500, baz: 40} })();
baz; // 40
foo; // 3
And by the way, don't be fooled by the fact that ECMAScript allows you to return 1, 2, .... What really happens there is not what might seem. An expression in return statement — 1, 2, 3 — is nothing but a comma operator applied to numeric literals (1 , 2, and 3) sequentially, which eventually evaluates to the value of its last expression — 3. That's why return 1, 2, 3 is functionally identical to nothing more but return 3.
return 1, 2, 3;
// becomes
return 2, 3;
// becomes
return 3;
Just return an object literal
function newCodes(){
var dCodes = fg.codecsCodes.rs; // Linked ICDs
var dCodes2 = fg.codecsCodes2.rs; //Linked CPTs
return {
dCodes: dCodes,
dCodes2: dCodes2
};
}
var result = newCodes();
alert(result.dCodes);
alert(result.dCodes2);
Since ES6 you can do this
let newCodes = function() {
const dCodes = fg.codecsCodes.rs
const dCodes2 = fg.codecsCodes2.rs
return {dCodes, dCodes2}
};
let {dCodes, dCodes2} = newCodes()
Return expression {dCodes, dCodes2} is property value shorthand and is equivalent to this {dCodes: dCodes, dCodes2: dCodes2}.
This assignment on last line is called object destructing assignment. It extracts property value of an object and assigns it to variable of same name. If you'd like to assign return values to variables of different name you could do it like this let {dCodes: x, dCodes2: y} = newCodes()
Ecmascript 6 includes "destructuring assignments" (as kangax mentioned) so in all browsers (not just Firefox) you'll be able to capture an array of values without having to make a named array or object for the sole purpose of capturing them.
//so to capture from this function
function myfunction()
{
var n=0;var s=1;var w=2;var e=3;
return [n,s,w,e];
}
//instead of having to make a named array or object like this
var IexistJusttoCapture = new Array();
IexistJusttoCapture = myfunction();
north=IexistJusttoCapture[0];
south=IexistJusttoCapture[1];
west=IexistJusttoCapture[2];
east=IexistJusttoCapture[3];
//you'll be able to just do this
[north, south, west, east] = myfunction();
You can try it out in Firefox already!
Another worth to mention newly introduced (ES6) syntax is use of object creation shorthand in addition to destructing assignment.
function fun1() {
var x = 'a';
var y = 'b';
return { x, y, z: 'c' };
// literally means { x: x, y: y, z: 'c' };
}
var { z, x, y } = fun1(); // order or full presence is not really important
// literally means var r = fun1(), x = r.x, y = r.y, z = r.z;
console.log(x, y, z);
This syntax can be polyfilled with babel or other js polyfiller for older browsers but fortunately now works natively with the recent versions of Chrome and Firefox.
But as making a new object, memory allocation (and eventual gc load) are involved here, don't expect much performance from it. JavaScript is not best language for developing highly optimal things anyways but if that is needed, you can consider putting your result on surrounding object or such techniques which are usually common performance tricks between JavaScript, Java and other languages.
function a(){
var d = 2;
var c = 3;
var f = 4;
return {d: d, c: c, f: f};
}
Then use
const {d, c, f} = a();
In new version:
function a(){
var d = 2;
var c = 3;
var f = 4;
return {d, c, f}
}
A very common way to return multiple values in javascript is using an object literals, so something like:
const myFunction = () => {
const firstName = "Alireza",
familyName = "Dezfoolian",
age = 35;
return { firstName, familyName, age};
}
and get the values like this:
myFunction().firstName; //Alireza
myFunction().familyName; //Dezfoolian
myFunction().age; //age
or even a shorter way:
const {firstName, familyName, age} = myFunction();
and get them individually like:
firstName; //Alireza
familyName; //Dezfoolian
age; //35
Other than returning an array or an object as others have recommended, you can also use a collector function (similar to the one found in The Little Schemer):
function a(collector){
collector(12,13);
}
var x,y;
a(function(a,b){
x=a;
y=b;
});
I made a jsperf test to see which one of the three methods is faster. Array is fastest and collector is slowest.
http://jsperf.com/returning-multiple-values-2
In JS, we can easily return a tuple with an array or object, but do not forget! => JS is a callback oriented language, and there is a little secret here for "returning multiple values" that nobody has yet mentioned, try this:
var newCodes = function() {
var dCodes = fg.codecsCodes.rs;
var dCodes2 = fg.codecsCodes2.rs;
return dCodes, dCodes2;
};
becomes
var newCodes = function(fg, cb) {
var dCodes = fg.codecsCodes.rs;
var dCodes2 = fg.codecsCodes2.rs;
cb(null, dCodes, dCodes2);
};
:)
bam! This is simply another way of solving your problem.
You can also do:
function a(){
var d=2;
var c=3;
var f=4;
return {d:d,c:c,f:f}
}
const {d,c,f} = a()
Adding the missing important parts to make this question a complete resource, as this comes up in search results.
Object Destructuring
In object destructuring, you don't necessarily need to use the same key value as your variable name, you can assign a different variable name by defining it as below:
const newCodes = () => {
let dCodes = fg.codecsCodes.rs;
let dCodes2 = fg.codecsCodes2.rs;
return { dCodes, dCodes2 };
};
//destructuring
let { dCodes: code1, dCodes2: code2 } = newCodes();
//now it can be accessed by code1 & code2
console.log(code1, code2);
Array Destructuring
In array destructuring, you can skip the values you don't need.
const newCodes = () => {
//...
return [ dCodes, dCodes2, dCodes3 ];
};
let [ code1, code2 ] = newCodes(); //first two items
let [ code1, ,code3 ] = newCodes(); //skip middle item, get first & last
let [ ,, code3 ] = newCodes(); //skip first two items, get last
let [ code1, ...rest ] = newCodes(); //first item, and others as an array
It's worth noticing that ...rest should always be at the end as it doesn't make any sense to destruct anything after everything else is aggregated to rest.
I hope this will add some value to this question :)
You can use "Object"
function newCodes(){
var obj= new Object();
obj.dCodes = fg.codecsCodes.rs;
obj.dCodes2 = fg.codecsCodes2.rs;
return obj;
}
All's correct. return logically processes from left to right and returns the last value.
function foo(){
return 1,2,3;
}
>> foo()
>> 3
I would suggest to use the latest destructuring assignment (But make sure it's supported in your environment)
var newCodes = function () {
var dCodes = fg.codecsCodes.rs;
var dCodes2 = fg.codecsCodes2.rs;
return {firstCodes: dCodes, secondCodes: dCodes2};
};
var {firstCodes, secondCodes} = newCodes()
I know of two ways to do this:
1. Return as Array
2. Return as Object
Here's an example I found:
<script>
// Defining function
function divideNumbers(dividend, divisor){
var quotient = dividend / divisor;
var arr = [dividend, divisor, quotient];
return arr;
}
// Store returned value in a variable
var all = divideNumbers(10, 2);
// Displaying individual values
alert(all[0]); // 0utputs: 10
alert(all[1]); // 0utputs: 2
alert(all[2]); // 0utputs: 5
</script>
<script>
// Defining function
function divideNumbers(dividend, divisor){
var quotient = dividend / divisor;
var obj = {
dividend: dividend,
divisor: divisor,
quotient: quotient
};
return obj;
}
// Store returned value in a variable
var all = divideNumbers(10, 2);
// Displaying individual values
alert(all.dividend); // 0utputs: 10
alert(all.divisor); // 0utputs: 2
alert(all.quotient); // 0utputs: 5
</script>
Few Days ago i had the similar requirement of getting multiple return values from a function that i created.
From many return values , i needed it to return only specific value for a given condition and then other return value corresponding to other condition.
Here is the Example of how i did that :
Function:
function myTodayDate(){
var today = new Date();
var day = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
var month = ["January","February","March","April","May","June","July","August","September","October","November","December"];
var myTodayObj =
{
myDate : today.getDate(),
myDay : day[today.getDay()],
myMonth : month[today.getMonth()],
year : today.getFullYear()
}
return myTodayObj;
}
Getting Required return value from object returned by function :
var todayDate = myTodayDate().myDate;
var todayDay = myTodayDate().myDay;
var todayMonth = myTodayDate().myMonth;
var todayYear = myTodayDate().year;
The whole point of answering this question is to share this approach of getting Date in good format. Hope it helped you :)
I am nothing adding new here but another alternate way.
var newCodes = function() {
var dCodes = fg.codecsCodes.rs;
var dCodes2 = fg.codecsCodes2.rs;
let [...val] = [dCodes,dCodes2];
return [...val];
};
Well we can not exactly do what your trying. But something likely to below can be done.
function multiReturnValues(){
return {x:10,y:20};
}
Then when calling the method
const {x,y} = multiReturnValues();
console.log(x) ---> 10
console.log(y) ---> 20
It is possible to return a string with many values and variables using the template literals `${}`
like:
var newCodes = function() {
var dCodes = fg.codecsCodes.rs;
var dCodes2 = fg.codecsCodes2.rs;
return `${dCodes}, ${dCodes2}`;
};
It's short and simple.

Swapping object variables in Javascript without using a 3rd variable

There is a well known method to swap 2 numeric variables without using a 3rd variable with simple arithmetic operations.
a = 3;
b = 5;
b += a;
a = b - a;
b -= a;
console.log(a); //5
console.log(b); //3
No mystery here. But I need to swap two variables that are objects and I have no idea how to tackle this.
The objects are very complex with properties of different data types and methods. Here is an example for simplification:
a = {
label: "xxxxxxx",
active: false,
doThatThang: function(val) {
//some code
}
};
I'm currently using a 3rd variable to perform the swap but the objects are really big and it's messing with the animation where the variables are swapping values.
Use ES6 array destructuring.
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a);
console.log(b);
Ref: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
Try ES6 Array Destructing assignment.
DEMO
let a = {
label: "111111",
active: false,
doThatThang: function(val) {
//some code
}
};
let b = {
label: "222222",
active: false,
doThatThang: function(val) {
//some code
}
};
console.log("Before swap");
console.log(a);
console.log(b);
[a, b] = [b, a];
console.log("After swap");
console.log(a);
console.log(b);
var a=1,
b=2,
output=document.getElementById('output');
output.innerHTML="<p>Original: "+a+", "+b+"</p>";
b = [a, a = b][0];
output.innerHTML+="<p>Swapped: "+a+", "+b+"</p>";
<div id="output"></div>
Use a third variable when swapping objects. There is no simpler way to do it in ES5.
var first = {property: 'value'}
var second = {more: 'stuff'}
console.log('Before')
console.log(first)
console.log(second)
var temp = first
first = second
second = temp
console.log('After')
console.log(first)
console.log(second)
Let Say a = 3 and b=5.
Then
a = a+b (ie 8)
b= a-b (ie 8-5 = 3)
a= a-b (ie 8-3 = 5).
Now these are swapped without using 3rd variable.

How to turn an undefined var to an object, inside a function

There is something I can't find an answer or an explanation for. Let's take for example the following code:
function fn(x){
x = {value: 10};
}
var a;
fn(a);
alert(a.value); //a is undefined
Shouldn't a = {value: 10}; as we passed it through that function?
The x is locally scoped. You are passing only values and not references. So you might need to return and assign like this:
function fn(x){
x = {value: 10};
return x;
}
var a;
a = fn(a);
From an awesome article:
When passing in a primitive type variable like a string or a number, the value is passed in by value. This means that any changes to that variable while in the function are completely separate from anything that happens outside the function.
function myfunction(x)
{
// x is equal to 4
x = 5;
// x is now equal to 5
}
var x = 4;
alert(x); // x is equal to 4
myfunction(x);
alert(x); // x is still equal to 4
Passing in an object, however, passes it in by reference. In this case, any property of that object is accessible within the function.
function myobject()
{
this.value = 5;
}
var o = new myobject();
alert(o.value); // o.value = 5
function objectchanger(fnc)
{
fnc.value = 6;
}
objectchanger(o);
alert(o.value); // o.value is now equal to 6

nestet object instances

I have a problem with nested object and prototyping.
In following example I'm creating 2 instances of the object "o"
var o = function(){};
o.prototype = {
val : 1,
test : {
val2 : 1
}
};
var t1 = new o();
var t2 = new o();
t1.val = 5;
t2.val = 20;
t1.test.val2 = 5;
t2.test.val2 = 10;
console.log(t1.val) //5
console.log(t2.val) //20
console.log(t1.test.val2) //10
console.log(t2.test.val2) //10
My question is why t1.test.val2 === t2.test.val2, where t1 and t2 are different variables,
shouldn't they be totally separate ??
how to fix that code to have all objects and variables inside separate ?
When you define a new object, the prototype is copied, but objects in the prototype are not deep copied; they are copied by reference. Thus, each new o instance has a copied reference to the exact same member objects of the prototype.
Instead, make the test object in your constructor so each instance has its own copy:
var o = function(){
this.test = {
val2 : 1
}
};
o.prototype = {
val : 1 // this is fine, since primitive values aren't copied by reference
};
This happens because you are modifying a property of shared object (i.e. the prototype). Your code is basically the same as:
var val = 1;
var test = {
val2 : 1
};
var t1 = {
val: val,
test: test
};
var t1 = {
val: val,
test: test
};
t1.val = 5; // changing property
t2.val = 20; // changing property
t1.test.val2 = 5; // changing property of shared object
t2.test.val2 = 10; // changing property of shared object
To fix that simply don't use prototype, i.e.
var o = function(){
this.val = 1;
this.test = {
val2 : 1
};
// test is no longer shared, exists per instance
};

Quick way to globalise a lot of variables in JavaScript?

I need to do a bit of quick testing with my code (getting the value of some variables inside a function), and I want to globalise them, so I can access them through the console.
I know this method:
function foo() {
var foo = 'foo';
window.foo = foo; // Make foo global
}
But what if I had something like this:
function foo() {
var foo1 = 'foo';
var foo2 = 'foo';
var foo3 = 'foo';
var foo4 = 'foo';
var foo5 = 'foo';
var foo6 = 'foo';
var foo7 = 'foo';
var foo8 = 'foo';
}
What would be a quicker way to globalise all those variables, without going window.foo1 = foo1, window.foo2 = foo2, etc.?
I don't wish this to be a code golf question, just a normal programming question.
I don't think there's a way to do this. See this:
Access all local variables
Have you tried simply debugging in the console? With Chrome, you can set a breakpoint and then inspect all values. Check out this tutorial:
https://developers.google.com/chrome-developer-tools/docs/scripts-breakpoints
Why not a single globals object instead of a bunch of variables?
function foo() {
window.globals = {
foo1 = 'foo',
foo2 = 'foo',
foo3 = 'foo',
foo4 = 'foo',
foo5 = 'foo',
foo6 = 'foo',
foo7 = 'foo',
foo8 = 'foo'
};
}
If they're all simply named like that, you can take advantage of a little known trick, variables are actually dictionaries:
function foo() {
var foo1 = 'foo';
var foo2 = 'foo';
var foo3 = 'foo';
var foo4 = 'foo';
var foo5 = 'foo';
var foo6 = 'foo';
var foo7 = 'foo';
var foo8 = 'foo';
for (var i = 1; i <= 8; i++) {
window["foo" + i] = eval("foo" + i);
}
}
document.write("Running foo...<br/>");
foo();
document.write("Printing foo...<br/>");
for (var i = 1; i <= 8; i++) {
document.write(window["foo" + i]);
}
document.write("<br/>Just one: " + foo3);// Normal variable notation

Categories