I have a constructor object in my code which is:
function Employee(){
this.name = names[Math.floor(Math.random() * names.length)];
this.age=1;
this.level=1;
this.production=400;
this.totalprod=0;
}
So when I create a new Employee I just say:
var employee1 = new Employee();
So then I can manipulate this instance of the object. Now, I want this objects to be created dynamically with the variable names: employee1, employee2, employee3 and so on.. Is there a way to achieve this or is it impossible?
And the other question that I have, say that I want to change the age of all instances at the same time, is there a way to do this? Thanks in advance and sorry if the question in silly, I'm learning!
EDIT: This is not the same as the other question as I'm using a constructor Object, not a literal Object, and, apart from that, I ask another question which is how to change a property of all instances at the same time, thanks!
This isn't really possible without the use of something like eval, which is bad practice.
Instead if you knew how many employees you wanted to make in advance you could do something like this.
Example: https://jsfiddle.net/dbyw7p9x/
function makeEmployees(n) {
var employees = new Array(n)
for (var i = 0; i < n; ++i) {
employees[i] = new Employee()
}
return employees
}
alternatively you could make also make it return an object which interestingly, while not exactly the same as the array, would be accessed in the same way as an array using numbers inside square brackets obj[0], obj[1], obj[2], obj[3] etc.
function makeEmployeesObj(n) {
var employees = {}
for (var i = 0; i < n; ++i) {
employees[i] = new Employee()
}
return employees
}
To change a property for each approach you can do:
// Array
for (var i = 0; i < e1.length; ++i) {
e1[i].age = 2
}
// Object
Object.keys(e2).forEach(function(key) {
e2[key].age = 2
})
Here is one way to do it, using an array, we push to new Employees to it, and return that array:
To add a specific value, in this case age, I recommend passing it in as a parameter to your Employee constructor, you can do this with all of the this parameters if you like:
Notice in the JsBin that all the ages are different, they are actually the value of n:
Working example: JSBin
function Employee(age){
this.name = 'something';
this.age= age;
this.level=1;
this.production=400;
this.totalprod=0;
}
function maker(n) {
var arr = [];
while (n > 0) {
arr.push(new Employee(n));
n--;
}
return arr;
}
Related
Basically I am trying to create an object property that will dynamically create an array based on the constructor. The following works if I remove the constructor and simply set testArray.length to some integer. But stops working when I try setting length with a constructor.
class TestArray {
constructor(length) {
this.length = length;
}
buildArray = function(length) {
let array = [];
for (let i = length; i > 0; i--) {
array.push("_");
}
return array;
}
array = this.buildArray(this.length);
}
let testArray = new TestArray(2);
console.log(testArray.array);
let testArray2 = new TestArray(2);
console.log(testArray2.array);
//[] is logged. Desired out put is ['_', '_']
Do I have syntax issue or a logic issue? Is there a plain better way to do this?
Class fields - assignments directly inside a class body - run before the body of the constructor runs (assuming there's no superclass). Your code is equivalent to
class TestArray {
constructor(length){
array = this.buildArray(this.length);
this.length = length;
}
See the problem? this.length hasn't been assigned to at the time you call buildArray, so it's undefined.
Remove the class field, and put that logic in the constructor, so that you can make use of the constructor's argument. Might as well ditch this.length entirely at that point too, it doesn't look to be doing anything useful.
class TestArray {
constructor(length){
this.array = this.buildArray(length);
}
buildArray = function(length){
let array = [];
for(let i = length ; i > 0; i--){
array.push("_");
}
return array;
}
}
let testArray = new TestArray(2);
console.log(testArray.array);
I'm trying to create an object that contains an array of objects. I'm using a jquery selector to determine the number of objects I want in the array. I'm having some issue here because when I enter the for loop Firefox says that "this.obj is undefined" I tried both the the this.obj = new Array() syntax as well as the this.obj[ ]; syntax.
function Base() {
this.n = document.querySelectorAll('transform').length /3;
this.obj = new Array(n); //array declaration
for (var i = 0; i < this.n; i++) {
this.obj[i] = new x3dSphere("b"+i);
}
}
I've only seen examples of arrays within objects that are declared like this.obj = [1,2,2,4] or the in the JSON form obj: [1,2,3,4]. I'm sure this is something really easy to do but I can't seem to find an example anywhere.
The following worked for me:
function Base() {
this.n = 5;
this.obj = [];
for (var i = 0; i < this.n; i++) {
this.obj.push(new Test());
}
}
Where Test was:
var Test = function () {};
It seems like the real problem is that it never created this.obj because n was undefined. If you want to declare the array how you did before, try new Array(this.n).
EDIT
Would new Array(this.n) be faster than the this.obj=[] syntax since it's pre-allocated?
Interestingly enough, the answer is no.
Additionally, the accepted answer on this question has a great discussion of lots of other aspects of JavaScript array performance: What is the performance of Objects/Arrays in JavaScript? (specifically for Google V8)
I've updated my answer to use Array.push() because it is apparently much, much faster than doing Array[i] = new Obj() (shout out to Jason, who used it in his original answer).
You can declare an array with
this.obj = [];
And then push objects into the array in a loop
for (var i =0; i < n; i ++) {
this.obj.push(new x3dSphere ());
}
I am learning Javascript and I am a C++ programmer. I have tried creating an object with a constructor with object.create and here is the result:
var PlayGround ={
initGrid : function(N) {
this.N=N;
this.grid = new Array(N);
for (var i = 0; i < N; i++) {
this.grid[i] = new Array(N);
for (var j = 0; j < N; j++) {
this.grid[i][j] = false;
}
}
return true;
}
};
var PlayGround_property = {
N:{
value: 100,
writable:true
},
grid:{
value:null,
writable:true
}
}
var board= Object.create(PlayGround, PlayGround_property);
It works as I want: the object board contains the object grid, and now I can use the set and get keyword to define the behaviour of the = and () operator.
Anyway I have read around the web that the
this
keyword in Javascript is not safe and I want to be sure that it is referring always to the board object and not to the global window object. Is there a way or I am overthinking?
Other question, are there other ways to write object with a constructor (and maybe other members) in Javascript?
I want to be sure that [this] is referring always to the board object
A function's this is set either by how you call the function, or bind. So just make sure you call methods the right way. If you always call functions as methods of board, then this within the methods will always reference board.
If you are only going to have one instance of board, there doesn't seem much point in using a constructor. If you have multiple instances of board, then you want this to reference the particular instance that called the method so you don't want to fix this using bind.
Crockford just doesn't like the use of new, so encouraged Object.create, it fits his idea of how inheritance should work.
Your pattern could be rewritten to use a constructor something like:
function PlayGround (N) {
this.N = N;
this.grid = []; // Use array literal, it's less to type
for (var i = 0; i < N; i++) {
this.grid[i] = [];
for (var j = 0; j < N; j++) {
this.grid[i][j] = false; // Not sure why you bother with this
}
}
}
var board = new Playground(100);
I'm not exactly sure what you're doing, but that should be close. Note that javascipt is loosely typed, so only initialise variables and properties if you have something useful to assign. Variables are created with a value of undefined, Array properties are only created if you actually assign something to them, creating an array with length N does not create any indexes, e.g.
var arr = new Array(10);
console.log(arr.length); // 10
console.log(arr.hasOwnProperty(0)); // false
jQuery has made my life easier but I'm still very beginner to JavaScript. So, may be, I'm asking a very stupid question here:
var t = {
rows: 3,
columns: 5,
getCellCount: function () {
return this.rows * this.columns;
}
};
var tn = t;
tn.rows = 6;
document.write(tn.rows + " , " + t.rows); // returns 6 , 6
I also tried var tn = new t(); // but seems wrong
So, How to retrieve old intrinsic value from object so that it results 6 , 3
tn and t are both pointing to the same object, that's why when you change tn.rows it also changes t.rows. There is no such thing as old intrinsic value.
You must copy the object in order to keep the old value. There are two: shallow copy and deep copy.
Copying the key-value pairs is pretty easy with Object.create.
var newObj = Object.create(oldObj);
Now if you change the values in newObj, it will not change the original one:
var a = {a:1}, b = Object.create(a);
b.a = 2;
console.log(a.a, b.a); //1,2
However, to perform a complete copy is really complicated. See more: How do I correctly clone a JavaScript object?
PS: The new keyword you mentioned is for creating an object as in classes.
function Car(n, y){ //This is called a "constructor"
var name = n, year = y; //Private variables
return {
getName: function(){ return name; }, //Getters
getYear: function(){ return year; }
};
}
var myNewCar = new Car("Toyota", 2010);
myNewCar.getName(); //"Toyota"
myNewCar.getYear(); //2010
(This is also how you create objects in Java, if you have taken those CS courses you would recognize this pattern.)
var tn = t;
simply makes both tn and t to point to the same object in memory. So, change in one object will reflect in other as well. You can clone the object, like this
function copyObject(sourceObject) {
var result = {};
for (var key in sourceObject) {
if (sourceObject.hasOwnProperty(key)) {
result[key] = sourceObject[key];
}
}
return result;
}
var tn = copyObject(t);
You are asking to clone a JSON object.
var tn={};
for (key in t) tn[key]=t[key];
There may be other "prettier" ways, but this guarantees the clone.
The = operator in javascript just changes what the object points to, so it will not create a copy of the original object. You can take a look here to see possible ways to create a clone of the object.
If you want to create a Javascript object, the conventional way is to create a function:
// Use capitalized names for Object-creating functions.
// I guessed that you wanted a matrix of some sort.
function Matrix(rows, columns) {
this.rows = rows;
this.columns = columns;
this.cellCount = function() {
return this.rows * this.columns;
}
this.dimensions = function() {
return this.rows, + ", " + this.columns;
}
this.copy = function() {
return new Matrix(this.rows, this.columns);
}
}
var t = new Matrix(6, 3);
There are more sophisticated ways to do this, using Object.create. Look at Javascript: The Good Parts.
I'm new enough to Javascript, and I have a small query about formulating variable names :
function createObjects(int length) {
var count;
for(count=0; count<length; count++;) {
var personObj + "" + count;
}
}
here I want to formulate a different personObj for each iteration of the for loop, is this the correct procedure? will this give me :
var personObj1
var personObj2
etc
Thanks!
Matt
If you want to have several instances of the same underlying data structure / logic you could use an approach like this:
Create a constructor function that generates an Object with the properties (also methods) that you need. For example:
function PersonObj(name, age) {
this.name = name;
this.age = age;
}
This enables you to create a new instance of PersonObj by using var n = new PersonObj('Fred',32);. Now you can use an Array to store multiple instancesof these objects:
var persons = []; // creates a new Array
for (var i = 1; i < 13; i++){
persons.push(new PersonObj('Alfred', i));
}
persons will now contain twelve Alfreds of age 1 to 12.
If you want to alter Alfred No. 3's age you could do:
persons[2].age = 99;
See a live demo
Don't. Dynamically generating variables is never a good idea. Use an object or an array instead. They are designed to structure groups of related data.
function createObjects(length) {
var count, people = [];
for(count=0; count<length; count++;) {
people.push('something');
}
return people;
}
Why not use an array for this instead?
if needs must, you can alwvays add a named property to the window object:
function createObjects(int length) {
var count;
for(count=0; count<length; count++;) {
window[personObj + "" + count] = new SomeObject();
}
}
Create the objects, add properties to objects and store the objects in an array.
var al = new Array();
function createObjects(int length) {
var o = new Object();
for(var count=0; count<length; count++;) {
o.count = 'some value';
}
al.push(o);
}