var number = 12345;
var obj = {};
do something like
obj.look ((((((some operator or function to get a reference of number ))))) number
anyway, let's think now obj has a reference to number.
so I would like to wanna do it this way.
obj.look = 'abc';
console.log (number); // hopefully 'abc'
i would like it's gonna be:
not method ( like obj.look() )
but can refer in property ( like obj.look )
all I'm asking is how to get a reference of primitive value.
I believe there must be some way. please help me out.
You can use Object.defineProperty:
var number = 12345;
var obj = {};
Object.defineProperty(obj, 'look', {
get() {
return number;
},
set(value) {
number = value;
}
});
document.write(obj.look + '<br>');
obj.look = 'abc';
document.write(number);
You can have an object, copy that reference to another variable, mutate the object and since both variables hold a reference to the same object any changes done from one variable will also be accessible from the other variable.
Primitive values can be wrapped into objects (new Object) but they can not be referenced otherwise. String objects are immutable (all properties are non-configurable, non-writable) and Number objects values are not accessible either. So you can't change the value of either object.
That means when you do:
obj.look = 'abc';
You are wiping the old reference and setting up a new string there (object or primitive). number will still hold the old reference and will remain unchanged.
So, no. I don't think this is possible to do in Javascript.
Related
I am having trouble maintaining the original value of a variable after making new changes to the original variable.
Code:
(...)
data = Illumination.calculate_N(data)
data = Illumination.calculate_pi(data)
data = Illumination.calculate_kwh(data)
data = Illumination.calculate_ca(data)
let data_base = data
let ca_base = data.ca
let kwh_base = data.kwh
let pi_base = data.pi
(...)
data = Illumination.calculate_N(data)
data = Illumination.calculate_pi(data)
data = Illumination.calculate_kwh(data)
data = Illumination.calculate_ca(data)
let data_proposto = data
let ca_proposto = data.ca
let kwh_proposto = data.kwh
let pi_proposto = data.pi
-----------------------------------
EXAMPLE:
static calculate_ai(data){
data.ai = data.areaTotal*data.au
return data
}
It was expected that the original variable (date) would have its values changed, and this happens correctly, however, the variables data_base and data_proposto are not keeping their values
Both variables at the end of the calculation have the same values as the variable date
The variables ca_proposto, ca_base, and the like store their values correctly
Any idea?
The only interactions of the variables data_base and data_proposto were their creations with the data variable and their return of the function
OBS: If I use console.log () to view the value of the data_base variable before redoing the new calculations (Illumination.calculate_N (data)), the value of the variable appears correctly as it should, it is changed shortly after these calculations.
Because in both cases you are assigning not the object itself in the current state, but a reference to that object. What you need to do is to clone the object so the state is frozen at that point.
Simple Clone (Shallow Copy)
let data_base = Object.assign({}, data); //you get a clone of data
let data_proposto = Object.assign({}, data);
The limitation here is that it only does a shallow copy. See Deep Copy below for further explanation.
JSON Clone
This is a quick-and-dirty way to clone as it converts a JSON object to a string, and then back. i.e. you are no longer getting a reference, but a new object.
let data_base = JSON.parse(JSON.stringify(data));
let data_postero = JSON.parse(JSON.stringify(data));
But this won't work if your object is not JSON-safe.
Deep Copy
The least elegant method is probably safest. It deep copies the properties over into a new object. The key difference with Object.assign() is that it copies the values of nested properties, whereas Object.assign() copies the reference to nested objects.
So with Object.assign() any subsequent changes in your nested objects will affect all versions of your "clones". This won't happen if your clones only have property values of those nested objects at the time of cloning – these values are not affected by any changes to the nested objects.
const deepCopy = function(src) {
let target = {};
// using for/in on object also returns prototype properties
for (let prop in src) {
// .hasOwnProperty() filters out these prototype properties.
if (src.hasOwnProperty(prop)) {
target[prop] = src[prop]; //iteratively copies over values, not references
}
}
return target;
}
let data_base = deepCopy(data);
let data_postero = deepCopy(data);
#chatnoir Defined the problem very well, But I do not agree with his JSON serialization solution due to the below probleam:
You will lose any Javascript property that has no equivalent type in
JSON, like Function or Infinity. Any property that’s assigned to
undefined will be ignored by JSON.stringify, causing them to be missed
on the cloned object.
My suggestion to perform deep copy is to rely on a library that’s well
tested, very popular and carefully maintained: Lodash.
Lodash offers the very convenient clone and deepclone functions to perform shallow and deep cloning.
Lodash has this nice feature: you can import single functions separately in your project to reduce a lot the size of the dependency.
Please find the running sample code here: https://glitch.com/edit/#!/flavio-lodash-clone-shallow-deep?path=server.js:1:0
You are using the same variable data inside and outside functions.
ie; data is in the global scope.
static calculate_ai(data){
data.ai = data.areaTotal*data.au
return data
}
even though you are expecting the scope of the variable data inside the method calculate_ai to be limited to that method, it is not the case. data is in global scope and therefore, the value changes inside the method for the variable affects outside as well.
An effective solution is to use a different variable inside the method.
A variable is like an octopus tentacle, and not as a box (as it’s commonly described). In this analogy, the variable's name can be thought of as the name of a tentacle.
A variable (tentacle) holds on to a value in what’s called a binding. A binding is an association of a variable to a value: x = 1.
In JavaScript, if a variable b holds on to variable a, changing the value to which variable a holds onto, will change the value to which variable b holds onto, as b and a are referencing to the same value:
let a = {key: 1}
let b = a
console.log(`a: ${a.key}`) // -> 1
console.log(`b: ${b.key}`) // -> 1
a.key = 2
console.log(`a: ${a.key}`) // -> 2
console.log(`b: ${b.key}`) // -> 2
a = {key: 3} // This will point variable 'a' to a new object, while variable 'b' still points to the original object.
console.log(`a: ${a.key}`) // -> 3
console.log(`b: ${b.key}`) // -> 2
I am trying to get into Fuse to create mobile apps and they use JavaScript for their logic. I never used JavaScript before and just recently completed their getting started course. Most of the stuff is pretty easy to understand, but I am having trouble with the way they use variables at one point. It would be nice, if somebody could explain how variables behave in JavaScript.
So the problem I have goes as follows:
for (var i = 0; i < hikes.length; i++){
// A new variable gets the value of the array
var hike = hikes[i];
if (hike.id == id){
// The variable gets a new value
hike.name = "foo";
break;
}
}
So, in my understanding of programming, the array hikes should be unchanged and only the variable hike should have foo as the name value. But in reality, the array now also has the name foo.
I guess the variable works as a pointer to the address of the arrays value, but maybe somebody can help me to better understand that concept.
Yes you're right, objects and arrays are always passed as references:
a = {}; // empty object
b = a; // references same object
b.foo = 'bar';
a.foo; // also 'bar'
You can create a deep copy of the array using JSON.parse(JSON.stringify(hikes)); and then use that copied array for manipulation:
var hikes = [
{
'id': 10
}
];
var id = 10;
var tempHikes = JSON.parse(JSON.stringify(hikes));
for (var i = 0; i < tempHikes.length; i++){
// A new variable gets the value of the array
var hike = tempHikes[i];
if (hike.id == id){
// The variable gets a new value
hike.name = "foo";
console.log('hike is ', hike);
break;
}
}
console.log(hikes);
arrays in javascript are passed by reference, whenever you modify an element in an array that change will occur anywhere you are accessing that array, to avoid such issues you have to use Array.from(arg) which creates a new array of from the arg parameter. This also applies to objects, to avoid such issues with objects, you have to use Object.create(obj) to create a new obj of from obj parameter or you can use let newObj = Object.assign( {} , obj ) , whenever you make any modification to the members of newObj the obj object does not see it, in other words there is no direct linkage between this two object, same thing applies for array
Boolean, null, undefined, String, and Number values are called primitive types.
When you assign something that is not a primitive type, namely arrays, functions and objects you are storing a reference to that.
That means that hikes[i] contains a reference to the object, where reference roughly means a pointer to it's location in memory.
When you assign hike = hikes[i] you are copying over the reference and not the actual object. So in fact hike still points to the same object as hikes[i], so any changes to that object are visible on both occasions.
If you want to copy the underlying object, there are different ways of doing so. One of them is Object.assign:
var hike = Object.assign({}, hikes[i])
This is because of pass by reference. All you need to do is create a new object (string, number ...) that you can work on.
for (var i = 0; i < hikes.length; i++){
var hike = hikes.slice(i,i+1)[0];
if (hike.id == id){
hike.name = "foo";
break;
}
}
slice also create a deep copy. you can use splice or assign or ((key1, key2)=>(key1, key2))(obj) etc.
Can anyone explain objects and properties to me in Javascript in layman's terms? The Javascript MDN documentation is confusing me.
I am trying to solve a problem in a Javascript tutorial about objects and properties The question is below and my attempt at the code, I think I followed the MDN as far as I can grasp it. Any help would be appreciated!
Question: Add the value of the property argument as a key on the object argument.
The value of the new property should be set to null.
Return object after adding the new property.
Input Example:
{}, 'hello'
{ x: 5 }, 'y'
Output Example:
{ hello: null }
{ x: 5, y: null }
note: the property name is NOT 'property'. The name is the value of the argument called property (a string).
My code:
//NOTE: the function addProperty(object, property) was already in the console and I have to write the solution inside of it.
function addProperty(object, property) {
// code here
let result = addProperty({x: 5}, 'y');
obj[property] = null;
return obj;
}
addProperty(x, 'y');
Layman's explanation:
An object is a collection of properties. You can give a name to the object to keep things organized. For example, lets create a person object.
var person = {};
The object has no properties right now. To further describe the person we can add properties to the object.
person.Name = 'Zim';
person.Age = 29;
person.Gender = 'Male';
person.Weight = 80;
Now this object has some properties to help describe it. A different way to write the same thing:
var person = { Name: 'Zim', Age: 29, Gender: 'Male', Weight: 80 };
If we had to create a program that displays a list of people, storing all of our information inside objects would help keep things organized.
Object properties are sometimes referred to as keys.
Adding properties to objects:
You can add a property to an object using brackets, just like you had in your addProperty function. If you just need it to add a property, set that property to null and return the result it would look something like this:
function addProperty(object, property) {
// code here
object[property] = null;
return object;
}
This would let us create a properies on our object from above by calling
addProperty(person, 'Occupation');
addProperty(person, 'Income');
addProperty(person, 'Height');
I think you're over-thinking it.
First the question:
Add the value of the property argument as a key on the object
argument. The value of the new property should be set to null. Return
object after adding the new property.
emphasis added
So, property will be the KEY (of a key/value pair), and the VALUE will be null of object, which we are also passing in as an argument.
One way to interrogate key/value pairs on a javascript object is through the square-brackets []. So, if you have a key/value pair: { foo: "bar" }, you can get "bar" by: object['foo']. You can also create new key/value pairs like this, so your function can look like:
function addProperty(object, property) {
object[property] = null;
return object;
}
var obj = {};
obj = addProperty(obj, "hello");
console.log(obj);
console.log(addProperty({x: 5}, 'y'));
What our function is doing is taking the object passed into it (as an argument), creating a new KEY with our property argument, and setting its VALUE to null, and simply returning the object.
*Side note -
Be careful, the code you have posted will create an endless recursive loop, as you keep calling the same function with no way to break out of it.
This particular example is simple:
var one={};
var two={x:5};
function addProperty(object property){
obj[property]=null;
return obj;
}
addProperty(one, 'hello');
addProperty(two, 'y');
Objects in javascript are really flexible, their properties can be added or removed, even when set from the very beginning.
If you take:
var x={};
x will be an object with nothing in it, but if instead of that you write:
var x={
inner:'b'
};
x will be an object with a property called inner which value is 'b', now, if we want to access that property we could do something like this:
var valueOfInner=x.inner;
or
var valueOfInner=x['inner'];
The same if we want to change the value of that property:
x.inner=8;
or
x['inner']=8;
Now, you'll notice that when we use x.['inner'], we could very well use instead:
var propertyName='inner';
x[propertyName]=8;
So you can access and modify a property of an object without actually knowing exactly which property you're manipulating.
Finally, if you're (willing or by accident) trying to set the value of a property that doesn't exists, the property will be automatically be created, for example:
x['blah']=456;
Will create the property blah even when it wasn't defined at first.
Edit: yes, you can define the object and define its properties later:
var x={};
//more code or something
x['y']=777;//now x has a y property with the value 777
a property is a key:
let obj = {
name: 'Jordan',
age: 15
}
obj.name is a property, same goes for obj.age.
I have been using this for a while as a really nice workaround for how to declare static members for my objects but I really don't understand why they become static so I need somebody to explain to me the following behavior.
I have the following declarations:
// Primitive so nothing interesting here
Array.prototype.someMember = "My value is not static";
// Object containing a primitive, now this is the deal
Array.prototype.someOtherMember = {
value: "My value is static"
};
Array.prototype.changeMember = function (newValue) {
// Change the primitive value
this.someMember = newValue;
// Change the primitive value inside the object
this.someOtherMember.value = newValue;
};
And if this is tested the following way:
var arr1 = [], arr2 = [], arr3 = [];
arr1.changeMember('I changed');
alert(arr1.someMember + ', ' + arr2.someMember + ', ' + arr3.someMember);
alert(arr1.someOtherMember.value + ', ' + arr2.someOtherMember.value + ', ' + arr3.someOtherMember.value);
The result is:
I changed, My value is not static, My value is not static
I changed, I changed, I changed
Now if I reassign the entire object in the changeMember method like this:
Array.prototype.changeMember = function (newValue) {
// Change the primitive value
this.someMember = newValue;
// Change the object
this.someOtherMember = { value: newValue };
};
Then someOtherMember is no longer static, but instead the first instance of Array gets its own. I don't understand the behavior because after all I am accessing someOtherMember through this in both cases, so I can't figure out why it's static in the first case and it's not static in the second.
There's no such thing as a static property in JS. What you're seeing is the normal behaviour of prototypal inheritance. The key concept is this: Arrays, and indeed all objects, are sparse An instance doesn't have a property unless it's explicitly assigned to that instance. as long as that doesn't happen, the prototype holds all properties:
The first case
Why are you seeing I changed, My value is not static, My value is not static? Simple: When arrays are instantiated, all instances will appear to have a property called someMember, but in fact, they don't. When you try to access anArray.someMember JS will first scan the instance for that property, if that instance doesn't have that property defined, JS will turn to the prototype and look for someMember there. In your snippet the changeMember method uses this, to refer to the instance that invokes the method, not Object.getPrototypeOf(this).someMember. The latter being the way to change the property on the prototype level. In short:
arr1.changeMember('I changed');
// is the same as doing:
arr1.someMember = 'I changed';
arr1.someOtherMember.value = 'I changed';
The assignment to someMember is a straightforward assignment, setting a property of an instance.
The second case
The second assignment is reassigning a property of an object, that is referenced by Array.prototype.someOtherMember. The Reference to the object literal doesn't change, only the object itself. Just as in any other language: when dealing with references, the object can change as much as it likes, the reference will remain the same (its value might change, but its memory address doesn't). When you redefine the changeMember method to reassign a new Object literal to a property, you're in essence creating the same situation as in case one: straightforward assignment of a new object to a property, that causes JS not to scan the prototype, but merely assign the property on an instance-level. You could use Object.getPrototypeOf(this) or (for older browsers) this.prototype:
Array.prototype.changeMember = function (val)
{
this.someMember = 'I changed At instance level';
Object.getPrototypeOf(this).someMember = 'Reassing prototype property to '+ val;
Object.getPrototypeOf(this).someOtherMember = {value:val};//changes proto only
};
Having said that, if you want something like a static property, you're better of using Object.defineProperty:
Object.defineProperty(Array.prototype,'sortofStatic',{value:'I cannot be changed',writable:false,configurable:false});
More examples of this can be found on MDN
In someOtherMember one instance of Object is shared between all instances of Array.
In the first case you are changing the value of that object, so the value changes for all instances of Array.
In the second case you are changing an object itself. So the instance of an Array will contain another object that the others.
The first case is well understood.
The second case (where someOtherMember isn't static member), you are overwritting the someOtherMember every time you call changeMember (deleting the static member value) therefore ceases to exist the static member.
Array.prototype.someMember = "My value is not static";
// Here `someOtherMember` is simply a property which points to a memory location
// So initially it will point to the same memory location for all instances of `Array`
Array.prototype.someOtherMember = {
value: "My value is static"
};
Array.prototype.changeMember = function (newValue) {
this.someMember = newValue;
// Here we change a value stored in the memory location pointed by `someOtherMember`
// As all instances point to the same memory location this change will reflect in all instances
this.someOtherMember.value = newValue;
};
Array.prototype.changeMember = function (newValue) {
this.someMember = newValue;
// Here for this particular instance we make `someOtherMember` point to a new memory location.
// All instances will point to the old memory location until `changeMember` is invoked.
this.someOtherMember = { value: newValue };
};
While reading a book about JavaScript I stumbled across an example:
var names = new Array("Paul","Catherine","Steve");
var ages = new Array(31,29,34);
var concatArray;
concatArray = names.concat(ages);
My question is, why doesn't the variable concatArray need to be define as a new Array() in order to store the concatenated data for both arrays name and ages , but when I try to treat the concatArray as an array by adding another line of code "document.write(concatArray[0])", it works just like an array and shows me the data stored in the first element. I just wonder why I'm not declaring the concatArray as a new array, yet it still works as one.
You are declaring concatArray as a new array but the declaration is implicit. The concat function returns a new array which contains concatenated copies of the original two arrays. The type of concatArray is inferred from the return type of the concat function.
Variable don’t have a specific data type in Javascript like in other languages. You can assign a variable every value you want.
That means var concatArray; declares the variable but the value is undefined:
var concatArray;
alert(typeof concatArray === "undefined");
Only when assigning the return value of names.concat(ages) (an array) to concatArray it get’s that type:
var names = new Array("Paul","Catherine","Steve");
var ages = new Array(31,29,34);
var concatArray;
alert(typeof concatArray === "undefined");
concatArray = names.concat(ages);
alert(concatArray.constructor === Array);
Javascript doesn't care what the contents of the var are when it is declared; that is why you can declare var concatArray without needing to specify it as an array. Once you assign it a value and a type (as the result of the concat() function) javascript treats the var as an array.
Simply put, w3schools says it pretty concisely:
The concat() method is used to join two or more arrays.
This method does not change the existing arrays, it only returns a copy of the joined arrays.
w3schools
Looks like Andrew and Matthew beat me to it anyway.
Because Javascript is dynamically typed. A variable doesn't have a specifuc type, and an array is an object that you can assign to any variable.
When you declare a variable without assigning it a value, it just exists with an undefined value:
var answer;
// now the variable exists, but it doesn't have a value
answer = 42;
// now the variable has the numerical value 42
answer = "hello";
// now the numerical value has been replaced with the string value "hello"
answer = [];
// now the variable contains an empty array
answer[0] = 1337;
// now the variable contains an array that contains an item with the value 1337
answer = -1
// now the array is gone and the variable contains the value -1
I would make an answer slightly different of Andrew's one.
JavaScript variables are not strongly typed. You can put a string, then a number, then an object in the same variable. When you use the variable, the interpreter checks its current type is suitable for the usage you try to make. If you write:
var a = 45;
alert(a[0]);
a = [ 5 ];
alert(a[0]);
you will get successively undefined then 5.