Assign value in javascript - javascript

I have two objects : $scope.objectA and $scope.objectB.
I assign value from $scope.objectA to $scope.objectB like this:
$scope.objectB.value1 = $scope.objectA.value1;
then I make value1 of $scope.objectB to null;
$scope.objectB.value1 = null;
My question is why when I assign $scope.objectB.value1 to null, $scope.objectA.value1 is null too. How can I keep value of $scope.objectA.value1 while changing value of $scope.objectB.value1?

Make copy of object B and assign it to the object A. Use angular.copy function. It will creates a deep copy of source.
For more information Visit Angular copy doc
$scope.objectA.value1 = angular.copy($scope.objectB.value1);

Because this is how it works. You make these two variables "bound" together.
If you want to keep value of objectA, then use
$scope.objectB.value1 = angular.copy($scope.objectA.value1);

I think this can happen only if ObjectA and ObjectB refer to the same object on the heap, i.e. it ObjectA and ObjectB are the same objects
$scope['object1'] = {};
$scope['object1']['val'] = {};
$scope['object2'] = {};
$timeout(() => {
this.$scope['object2']['val'] = this.$scope['object1']['val'];
$timeout(() => {
this.$scope['object2']['val'] = null;
console.log(this.$scope['object1']['val']); // Object {}
})
});
-
$scope['object1'] = {};
$scope['object1']['val'] = {};
$scope['object2'] = {};
$timeout(() => {
this.$scope['object2']['val'] = this.$scope['object1']['val'];
$timeout(() => {
this.$scope['object2']['val'] = null;
console.log(this.$scope['object1']['val']); // null
})
});

The reason is when you assign object to a variable, the assignment will be by reference, so the old and new will be a reference to the original object
So when you edit an object, you're actually editing the original object.
The solution
Angular: use object = angular.copy(myObject1)
jQuery: object = $.extend({}, myObject1);

Related

Javascript Arrays as an object field

I am running into a problem with using an array as a Javascript field.
var Object = function () {
var admins = [];
this.addAdmin = function(admin){
this.admins.push(admin)
}
}
Normally I would expect admin to be pushed into the array admins but instead I get a 'cannot read property 'push' of undefined'.
If I'm not mistaken when I initialized the Object with new Object(), admins = []; should initialize the array. Is this a limitation of Javascript?
Thank you in advance.
var array creates a local variable. It does not create a property on the object.
You need:
this.admins = [];
or
admins.push(admin) /* without this */
In your function admins is a local variable to the function. You need to declare admins as a property on the instance.
function Obj(){
this.admins = [];
}
Obj.prototype.addAdmin = function(admin){
this.admins.push(admin);
}
obj = new Obj();
obj.addAdmin('tester');
Also, because Object is the global base object, don't create functions or objects named Object.
I suspect you've gotten confused (which is easy :-) ) because you've seen code like this:
class Obj {
admins = [];
addAdmin(admin) {
this.admins.push(admin);
}
}
That uses the modern class and class fields syntax to puts an admins property on the object constructed via new Obj. (Note there's no var before admins = [];.) But in your code, you've used the older function-based syntax. Within your function, var admins = []; just creates a local variable, not a property.
I'd suggest that if you want to create constructor functions, using the new class syntax above is the simpler, more powerful way to do that. If you want to use the older syntax, though, other answers have shown how, but for completeness either make admins a property of the object:
let Obj = function() {
this.admins = []; // ***
this.addAdmin = function(admin){
this.admins.push(admin)
};
};
or perhaps with addAdmin on the prototype:
let Obj = function() {
this.admins = []; // ***
};
Obj.prototype.addAdmin = function(admin){
this.admins.push(admin)
};
or use the fact addAdmins closes over the call to Obj, and thus the local admins:
let Obj = function() {
const admins = [];
this.addAdmin = function(admin){
admins.push(admin) // <=== No `this.` here, you want to close over the
// `admins` local
};
};
I am assumming Object is a placeholder, because it is a reserved keyword.
What is happening is, your variable var admins = []; is created locally and can noot be accesed with the this. as a result when you set the value in this.admins.push(admin) the admins there is undefined. you should modify your function to read this way
var Obj = function () {
this.admins = [];
this.addAdmin = function (admin) {
this.admins.push(admin);
};
};
const object = new Obj();
object.addAdmin(1);
you should not omit the this keyword like this(no pun intended) if you plan to new the function. Stick to the code above.
var Obj = function () {
var admins = [];
this.addAdmin = function (admin) {
admins.push(admin);
};
};
const object = new Obj();
console.log(object)

How to append properties in an object in Vuejs

I have Data in vuejs like following:
params: {
comment: Object,
state: "",
deleteAppointment: false,
appointmentId: null,
}
I am filling data from two functions. First function is just assigning following lines:
this.params.state = "BLACKLIST";
this.params.deleteAppointment = true;
this.params.appointmentId = this.appointmentId;
But, in the second function when I am assigning following:
const comment = {};
fd.forEach(function(value, key){
comment[key] = value;
});
const data = {};
Object.keys(this.lead).map((key) => {
if (this.lead[key] != this.orginal[key]) {
data[key] = this.lead[key];
}
});
this.params = data; // May be the problem is here, data is overwriting existing properties of params
this.params.comment = comment;
When assigning data in params, previous properties are vanishing!
May be I need object copy or something! I couldn't understand what I have to do actually right now.
You should inherit the previous object using Spread Operator, try this
this.params = {...this.params, ...data};

Merge objects dynamically - Object Property Name Issue

I'm trying to merge objects together, or add new objects to existing objects.
I've already got it working as for merge using jQuery, but it's the name of the property that wont work dynamically.
The parameter filters is an object, such as {test:123}.
When invoking filter({test:123});, I want the filter function to dynamically add objects to a global object. (and of course can't use push() since its not an array)
this.filter = function(filters) {
for (var key in filters) {
$.extend( settings.filter, {key:filters[key]} );
}
};
The problem is that "key" turns into "key" as the name of the property. When it should be "test" as the property name; I can not get the property name to be created dynamically.
The goal would be to allow the user to fire the function like this:
filter({test:123,test2:1321,test55:4})
and dynamically add objects to the global settings object without the user meddling with the object itself.
Your code does not work because key is not being interpreted as a variable when being directly set in the object.
$.extend( settings.filter, {key:filters[key]} );
Considering:
var keyName = "Test";
var badObj = { keyName: "Hello World" };
You would get undefined when calling newObj.Test because it is actually newObj.keyName.
In order to use a variable to create a property name, you need to use different syntax.
var keyName = "Test";
var newObj = {};
newObj[keyName] = "Hello World";
You could then reference and use newObj.Test to get "Hello World"
To fix the method you provided, you can adjust it to:
this.filter = function(filters) {
for (var key in filters) {
if (filters.hasOwnProperty(key)) {
var newObj = {};
newObj[key] = filters[key];
$.extend(settings.filter, newObj);
}
}
};
Keep in mind you can simplify this and just use the extend method. This would be better, unless you are looking to do your own filtering as the method name suggests.
this.filter = function(filters) {
$.extend(settings.filter, filters);
};
Demos
You should create temp obj before extend :
this.filter = function(filters) {
for (var key in filters) {
var obj = {};
obj[key] = filters[key];
$.extend( settings.filter, obj );
}
};

JavaScript class to populate object

I am trying to populate an object by using a JavaScript class. I am not even sure if I am doing it correctly, I am very new to JavaScript OOP.
var ImagesViewModel = {}; // Global object
function ImagesClass() {
this.addImage = function (iUrl) {
ImagesViewModel.push({ "ImageUrl": iUrl }) //< Error is here
}
}
var k = new ImagesClass()
k.addImage("http://www.yahoo.com")
k.addImage("http://www.xbox.com")
Basically I need an easy way to populate ImagesViewModel with multiple properties. Do I need to specify properties within ImagesViewModel? Maybe I can do all of this without having to specify a global variable?
I am getting the error
Object has no method PUSH
What you want is an array and not an object, push is a method on Array prototype and you are trying to use it on object.
Change:
var ImagesViewModel = {};
To:
var ImagesViewModel = [];
You can do it this way as well so that each instance of ImagesClass has its own set of images.
function ImagesClass() {
var _images = [];
this.addImage = function (iUrl) {
_images.push({ "ImageUrl": iUrl }) //< Error is here
}
this.getImages = function(){
return _images;
}
}
and use it as:
var k = new ImagesClass();
k.addImage("http://www.yahoo.com");
k.addImage("http://www.xbox.com");
var ImagesViewModel = k.getImages(); //You can either set it directly or as a property of object
console.log(ImagesViewModel);
Demo
the push method is only for Arrays, here you are trying to push() to an object, which is why it isn't working.
You will need to change var ImagesViewModel = {}; to var ImagesViewModel = [];
From a design perspective, you probably don't want your viewmodel to just be a flat array (even though you declared it as an object, as other posters pointed out).
I'd suggest declaring an array declaration to hold the images inside of your ImagesViewModel object.
var ImagesViewModel = { // ViewModel generic OBJECT
this.Images = new Array(); // prototype ARRAY object
};
function ImagesClass() {
this.addImage = function (iUrl) {
ImagesViewModel.Images.push({ "ImageUrl": iUrl })
}
}

Javascript function, objects

I got an object defined global way:
window.myobj = {};
Then new elements are being added and finally it is being saved via ajax to database by SaveData(obj) function. The problem is, that I am making it alot of times in short period, and it seems that what is being passed to function is only a pointer to one single object, so when another event occures, it changes inside a save function even when it was changed outside. In PHP, you have to use &$obj for it... so how do I do it properly, so the obj passed to the function would not be only a pointer?
Edit:
The problem appeared in here:
Lets say that event = {time:123,type:blah}
function SaveData(event){
obj = jQuery.extend({}, event); // doesn't seem to replicate event
$.post('save',obj,function(res){
if(res) console.log(obj);
});
if(obj.type == 'blah'){
newobj = jQuery.extend({}, obj);
newobj.type = 'newtype';
newobj.time = 234;
SaveData(newobj);
}else if(obj.type == 'newtype'){
newobj = jQuery.extend({}, obj);
newobj.type = 'lasttype';
newobj.time = 345;
SaveData(newobj);
}
}
This returns 3 objects that are the same:
{time:345,type:lasttype}
Assuming your Object myobj does not contain any functions, but only values and further objects, one very easy way to clone the Object (and thus get rid of the problem with pointers) would be:
var clonedObj = JSON.parse(JSON.stringify(window.myobj));
Now you can pass the clonedObj to your SaveData Function.
If you're using jQuery, the answer is as simple as;
var myCopy = $.extend(true, {}, window.myobj);
If not, this function will create a deep copy the object - including functions and nested objects;
function clone(original) {
if (original == null || typeof(original) !== 'object')
return original;
var theClone = original.constructor.call(this);
for (var property in original) {
theClone[property] = clone(original[property]);
}
return theClone;
}

Categories

Resources