I have this code in Javascript:
function Camada(nome) {
Camada.prototype.nome = nome;
Camada.prototype.desenhar = function () {
};
};
var camadas = [];
for (var i = 0; i < 10; i++) {
var camada = new Camada('nome' + i);
camadas[i] = camada;
}
for (var i = 0; i < 10; i++) {
console.log(camadas[i]);
}
But this always prints 10 times the last object Camada, the problem looks like that camadas is keeping a reference to the var camada;
How can I solve this kind of problem using a for loop?
Issue with your code is that you're assigning to Camada.prototype in a constructor. Use this instead.
The difference is that assigning to prototype will make this property common among all the instances of Camada. Assigning to this will make it a property of the given instance only (which is what you want).
Difference between prototype and this is explained pretty well in this StackOverflow thread.
Try this:
function Camada(nome) {
// Since you're using Camada as a constructor, you can use 'this'
// and assign new objects properties to it.
this.nome = nome;
this.desenhar = function () {};
};
var camadas = [];
for (var i = 0; i < 10; i++) {
var camada = new Camada('nome' + i);
camadas[i] = camada;
}
for (var i = 0; i < 10; i++) {
console.log(camadas[i].nome);
}
Because in the constructor for Camada you are changing the prototype.
The prototype is like the class, and is shared by all Camadas.
This should be what you're after:
function Camada(nome) {
this.nome = nome;
this.desenhar = function () { };
};
You are passing your nome to the prototype. This means each time the constructor is called, it overwrites this property, and effects all instances.
Do not pass the nome value up to the prototype.
In the constructor you want to assign the param to the class property:
function Camada(nome) {
this.nome = nome;
};
Related
I am trying to create an array of objects. One object property is a function, which I want to change value of depending on which number in the array the object is.
When I try to use the 'i' value from the for loop, this is not being maintained in the function as a number. It is remaining a variable.
var array = [];
for (var i = 0; i<number; i++){
array[i].someFunction = function(i) {console.log(i)}}
However, when I call the value held in that property (i.e.):
console.log(array[2].someFunction)
It returns {console.log(i)} instead of {console.log(2)} which is what I want it to do.
Basically you had some problems in your code, like:
not defining number
using var instead of let
not defining the object
using the same value as parameter of the function
here you have the working solution.
var array = [];
// numbers was not defined.
const number = 10;
// use let instead of var
for (let i = 0; i < number; i++) {
// you are not instantiating your object, here is an example.
array[i] = {
"foo": "bar",
"index": i,
}
// you have to change i to j, because if you use i
// it will be the parameter of the function
array[i].someFunction = function(j) {
console.log('index: ', i);
console.log('parameter: ', j)
}
}
// we see the function
console.log(array[2].someFunction)
// we call the function succesfully
array[2].someFunction(100);
It's still referencing i, which has since changed to (number - 1). Save the value somewhere you know it's not subject to change- perhaps in the object itself:
var array = [{}, {}, {}];
for(var i = 0; i < array.length; i++){
array[i].index = i;
array[i].someFunction = function(){console.log(this.index);}
}
//and see that it's working...
for(var i = 0; i < array.length; i++){
array[i].someFunction();
}
I try to add function to the object. Why does't it work? The result is undefined. Please help.
<html>
<body>
<script>
var calc = function(){
this.num1 = 5,
this.num2 = 5,
compute = function( ) {
this.result = this.num1 * this.num2;
}
};
var myObj =[];
for(var i=0; i<5; i++){myObj.push(new calc())};
//calc.compute();
document.write(myObj.compute);
</script>
</body>
</html>
There are a couple of immediate issues. First, constructors should be written in the style function Calc(args) to distinguish them from other functions, and to also solve scope/context issues.
Second, your method should be this.compute.
Third, while adding the numbers to a result variable is fine, from the rest of your code you look like you want to return something from compute but you're not.
Finally, why do you want to create five identical objects? I've corrected but also updated your code a little bit below to show you what I mean.
function Calc(first, second) {
// assign the arguments to num1 and num2
this.num1 = first;
this.num2 = second;
this.compute = function() {
// we return the result rather than assigning it
return this.num1 * this.num2;
}
};
var myObj = [];
// here we use i and 5 as the new object parameters
for (var i = 0; i < 5; i++) {
myObj.push(new Calc(i, 5));
};
for (var i = 0; i < 5; i++) {
console.log(myObj[i].compute()); // 0, 5, 10, 15, 20
};
DEMO
Now, as deceze suggests, separating out the method and defining it on the prototype is also a good idea, so you'd end up with the following code:
function Calc(first, second) {
this.num1 = first;
this.num2 = second;
};
Calc.prototype.compute = function() {
return this.num1 * this.num2;
}
DEMO
Try associating the function with the object with this keyword. Currently compute function is not associated with the object.
Also you need to return the result and accessing object by index
So correct one will be
var calc = function() {
this.num1 = 5,
this.num2 = 5,
this.compute = function() {
this.result = this.num1 * this.num2;
return this.result;
}
};
var myObj = [];
for (var i = 0; i < 5; i++) {
myObj.push(new calc())
};
//calc.compute();
document.write(myObj[0].compute());
Issues:
Missing parenthesis document.write(myObj.compute);. It should be document.write(myObj.compute());.
myObj is an array of objects of type Calc. So you will need index to access any property of object. myObj[0].compute().
Missing return statement in compute function. You are assigning value to this.results but not returning anything. I have removed results and have added return statement.
Following code represents the same:
var calc = function() {
// Store current context
var self = this;
self.num1 = 5,
self.num2 = 5,
compute = function() {
return self.num1 * self.num2;;
}
// public properties...
return {
compute: compute
}
};
var myObj = [];
for (var i = 0; i < 5; i++) {
myObj.push(new calc())
};
//calc.compute();
document.write(myObj[0].compute());
I would like to make objects, with earlier created objects as the prototypes. This way I would be able to make additions to existing objects without modifying them.
Methods which interact with the earlier created objects (so using there attributes and perhaps mutating them) could also be applied to the newly derived objects.
I thought this could be done with the following code, but it doesn't...
objs = [];
for (var i = 0; i < 5; i++) {
objs.push({
index: i
});
}
for (var i = 0; i < 5; i++) {
var newObj = {};
newObj.prototype = objs[i];
alert(newObj.index);
}
http://jsfiddle.net/q5bu25L1/2/
A prototype comes into play when you use a constructor to create an instance of an object. In order to get your approach to work, you can do this:
for (var objI in objs) {
var obj = objs[objI];
var newObj = function() {};
newObj.prototype = obj;
newObj = new newObj();
console.log(newObj.i);
}
http://jsfiddle.net/q5bu25L1/3/
Or you could just use Object.create(), which accomplishes pretty much the same thing.
Note that neither of these approaches can completely prevent the contents of the parent objects from being modified if they themselves contain objects. For example:
var a = { n: 8, myObj: { i: 7 }};
var b = Object.create(a);
b.n = 10;
console.log(a.n); // still 8
console.log(b.n); // 10
b.myObj.i = 15;
console.log(a.myObj.i); // changed to 15!
console.log(b.myObj.i); // 15
http://jsfiddle.net/0f5ydL6u/
what about using native Object.create() ECMA5 spec
look at the full support comparison
objs = [];
for (var i = 0; i < 5; i++) {
objs.push({
index: i
});
}
for (var i = 0; i < 5; i++) {
var newObj = Object.create(objs[i]);
alert(newObj.index);
}
DEMO
I am trying to dynamically build an object for every iteration of a for loop using the i as part of the object name. based on the example below I would like 19 objects with names: obj0, obj1, obj2... obj18.
so I have an array with a length:
console.log(foo.length); // 19
for (var i = 0; i < foo.length; i++) {
var bar+i = {};
};
console.log(bar1);
console.log(bar2);
// ...
console.log(bar18);
I can't figure out the correct syntax for "var bar+i = {};", obviously it does not work.
EDIT
I really need objects because I am constructing data to be used in D3.js that needs to be an array of many objects
Unless bar{i} is an array value / object property itself the only way to do this is to bind it to the window or root object.
window[bar+i] = {};
Or to the root object
this[bar+i] = {};
Much better to bind it to an array / object itself though rather than bind senselessly to the root/window.
var array = [];
array[bar+i] = {};
There are some hacks how you can achieve this. However I advice you to use arrays instead of that method you are trying to use:
console.log(foo.length); // 19
var variables = [];
for (var i = 0; i < foo.length; i++) {
variables[i] = {};
};
console.log(variables[0]);
console.log(variables[1]);
// ...
console.log(variables[18]);
You can't create variables like this.
What you can do is add properties of the global scope, which you can use as variables:
for (var i = 0; i < foo.length; i++) {
window['bar'+i ] = {};
};
or use another object to hold everything:
var container = {};
for (var i = 0; i < foo.length; i++) {
container['bar'+i] = {};
};
You can't dynamically write variable names, but you can do the same on object properties:
console.log(foo.length); // 19
var obj = {};
for (var i = 0; i < foo.length; i++) {
obj[ 'bar' + i ] = {};
};
console.log(obj.bar1);
console.log(obj.bar2);
// ...
console.log(obj.bar18);
You can use eval:
eval('var bar'+i+' = {};');
But really, you shouldn't be doing this, unless you know for sure you can't do it the other way.
I'm trying to implement a duplicate method to the js Array prototype which concats a duplicate of the array to itself like so:
[11,22,3,34,5,26,7,8,9].duplicate(); // [11,22,3,34,5,26,7,8,9,11,22,3,34,5,26,7,8,9]
Here's what I have, but it causes the browser to crash:
var array = [11,22,3,34,5,26,7,8,9];
Array.prototype.duplicate = function() {
var j = this.length;
for(var i = 0; i < this.length; i++) {
this[j] = this[i];
j++;
}
return this;
}
I'm trying to do this using native JS as practice for iterations and algorithms so I'm trying to avoid built-in methods, if possible, so that I can get a clearer understanding of how things are being moved around.
Any ideas on why it is crashing and how I can optimize it?
The code inside the loop changes the length of the array, so it will just keep growing and you will never reach the end of it. Get the initial length of the array in a variable and use in the loop condition. You can use that as offset for the target index also instead of another counter:
var array = [11,22,3,34,5,26,7,8,9];
Array.prototype.duplicate = function() {
var len = this.length;
for (var i = 0; i < len; i++) {
this[len + i] = this[i];
}
return this;
}
The length of the array is increasing with each element added so you can not use this as a terminator. Try this.
var j = this.length;
for(var i = 0; i < j; i++) {
this[i+j] = this[i];
}
Here's simplest code
Array.prototype.duplicate = function () {
var array = this;
return array.concat(array);
};
Using Spread syntax;
In a method, this refers to the owner object.
Array.prototype.duplicate = function () {
return [...this, ...this]
};
let array = [1,2,3,4,5];
Array.prototype.duplicate = function () {
return [...this, ...this]
};
console.log(array.duplicate());