Javascript prototype from instance - javascript

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

Related

How to create a multidimensional array in JavaScript?

How can I create a multidimensional array in JavaScript?
I have:
var m = 4;
for (var i = 0; i < m; i++){
groupsData.name_of_bar = [];
groupsData.name_of_bar[i]['a'] = data[i].a;
groupsData.name_of_bar[i]['ab'] = data[i].ab;
groupsData.name_of_bar[i]['de'] = data[i].de;
groupsData.name_of_bar[i]['gh'] = data[i].gh;
groupsData.name_of_bar[i]['xy'] = data[i].xy;
}
If I do:
groupsData.name_of_bar[0]
I get errors:
TypeError: Cannot read property '0' of undefined
TypeError: Cannot set property 'a' of undefined
What am I doing wrong?
JavaScript doesn't support multidimensional arrays per se. The closest you can come is to create an array where the values in it are also arrays.
// Set this **outside** the loop so you don't overwrite it each time you go around the loop
groupsData.name_of_bar = [];
for (var i = 0; i < m; i++){
// Create a new "array" each time you go around the loop
// Use objects, not arrays, when you have named properties (instead of ordered numeric ones)
groupsData.name_of_bar[i] = {};
groupsData.name_of_bar[i]['a'] = data[i].a;
groupsData.name_of_bar[i]['ab'] = data[i].ab;
groupsData.name_of_bar[i]['de'] = data[i].de;
groupsData.name_of_bar[i]['gh'] = data[i].gh;
groupsData.name_of_bar[i]['xy'] = data[i].xy;
}
Each iteration through the loop, you are doing groupsData.name_of_bar = [];. This removes whatever else is already in there and replaces it with a blank array.
Also, when you do groupsData.name_of_bar[i]['a'], you need to create groupsData.name_of_bar[i] first.
A way to do this is:
groupsData.name_of_bar = [];
var m = 4;
for (var i = 0; i < m; i++){
groupsData.name_of_bar.push({
a: data[i].a,
ab: data[i].ab,
ab: data[i].ab,
de: data[i].de,
gh: data[i].gh,
xy: data[i].xy,
});
}
Note that in JavaScript, arrays can only be numerically indexed. If you want string indexes, you need to use an object.
Also, if there are no other values in data[i], then you can simplify this even further by doing:
groupsData.name_of_bar = [];
var m = 4;
for (var i = 0; i < m; i++){
groupsData.name_of_bar.push(data[i]);
}
Heck, why not just use groupsData.name_of_bar = data; and lose the loop altogether?
The way you are declaring your objects are a little off. It looks like you are attempting to create an array of objects.
var groupsData = {name_of_bar: []},
m = 4,
i = 0;
for(; i < m; i++) {
groupsData.name_of_bar.push({
a: data[i].a,
ab: data[i].ab,
de: data[i].de,
gh: data[i].gh,
xy = data[i].xy
});
}

Javascript: creating a array of objects inside a loop

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;
};

build objects in for loop with javascript

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.

merge two nodelist withtout duplicate

I try to merge two node list in one but when I concat in one array, there is two time the same node. Concat do not search if nodes to insert already exist in array...
var firstNodelist = document.querySelectorAll("#outter, #inner");
var finalArray = new Array();
for (var i = 0; i < firstNodelist.length; i++) {
var secondNodelist = firstNodelist[i].querySelectorAll("div");
var firstArray = new Array();
for (var x = 0; x < secondNodelist.length; x++) {
firstArray.push(secondNodelist[x]);
}
finalArray = finalArray.concat(firstArray)
}
console.log("FINAL", finalArray);
The jsfiddle exemple
Rather than building a second, unnecessary array within your loop, just use that inner loop to check whether the node is already in the array (Array#indexOf on all modern browsers) and only add it if it isn't.
var firstNodelist = document.querySelectorAll("#outter, #inner");
var finalArray = []; // `[]` rather than `new Array()`
for (var i = 0; i < firstNodelist.length; i++) {
var secondNodelist = firstNodelist[i].querySelectorAll("div");
for (var x = 0; x < secondNodelist.length; x++) {
// Get this node
var node = secondNodeList[x];
// Is it in the array already?
if (finalArray.indexOf(node) === -1) {
// No, put it there
finalArray.push(node);
}
}
}
console.log("FINAL", finalArray);
Be sure to test your target environment(s) to be sure they have Array#indexOf.
Having said that, there's a much better way for that specific situation: Live Example | Live Source
var finalArray = Array.prototype.slice.call(
document.querySelectorAll("#outter div, #inner div")
);
...since querySelectorAll won't include the same node more than once, even if #inner is inside #outter (or vice-versa). (The Array.prototype.slice.call(someObject) is a trick to get a true array from any array-like object.)

How to prototype a duplicate prototype method for Array in javascript

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());

Categories