Array with method that sets itself - javascript

I'm trying to make an array object that can set itself.
Something like this...
array = new Array(10)
array.someMethod = function () {
this = new Array(20)
}
Except this doesn't work because this can't be set like that.
More or less I want an object that I use array[index] on.

Seems to me this could be accomplished by using an object and storing the array in one of the object's properties. I'm learning about the class syntax, so I did it that way, but I think the same approach would work with regular objects.
class MyArray {
constructor(num) {
console.log(`building MyArray with ${num} objects`);
this.innerArray = new Array(num);
}
update(num) {
console.log(`updating MyArray to have ${num} objects`);
this.innerArray = new Array(num);
}
get() { return this.innerArray }
}
let foo = new MyArray(10);
foo.get()[0] = "bar";
console.log(foo.get());
foo.update(20);
foo.get()[0] = "baz";
console.log(foo.get());

the way you asked your question is not quite right you should explain better.
not sure this is what you want.
you can't change the this in javascript.
but function in prototype will be called with the object as their context. so Array.prototype.length gives the length in arr.length by having arr as it's context. Array.prototype.splice
so
Array.prototype.testA = function() {
// this.splice(0,this.length);
var a = [3,5,7];
// new Array(23).fill().map( (a,_)=>_)
this.splice(0,this.length,...a);
}
Array.prototype.testAA = function() {
var a = [3,5,7];
this.splice(this.length,0,...a);
}
var a = [1];
a.testAA();
console.log(a);
a.testA();
console.log(a);

Related

Copy object functions and properties in new object by value not by reference - javascript

I want to copy the functions and properties of an object into new object. The old object should not effect by changing made in new Object.
Here is the object definition:
var Call = function() {
this.number="123";
}
Call.prototype.function1 = function() {
return this.number;
}
var callobj = new Call();
I can access function1 using callobj.function1().
What I have tried to copy it:
Javascript:
var newcallobj = Object.assign({}, callobj);
In this case, i am not able to access function1 but i can access number property directly.
JQUERY:
var newObj = jQuery.extend(true, {}, callobj); OR
var newObj = jQuery.extend({}, callobj);
In this case, i am able to access function1 and property but when i change number like that newObj.number="222". It also change the value of original object.
I know that there is couple of other posts. But all is not working for me. Please let me know if i am doing any thing wrong?
AFTER #gurvinder372 answer(I am updating question):
After #gurvinder372 answer. It is working for first level of property but if it has another object like i show below and i change the value of property of another object. Then it is effecting on original object also.
var ABC = function(){
this.number = "333";
}
var Call = function() {
this.number="123";
this.anotherobj = new ABC();
}
Call.prototype.function1 = function() {
return this.number;
}
var callobj = new Call();
var newcallobj = Object.create(callobj);
newcallobj.anotherobj.number= "123";
console.log(newcallobj.anotherobj.number);
console.log(callobj.anotherobj.number);
Output of both is 123. #gurvinder372. can you check th above code ?
Object.assign only copies the enumerable properties of an object.
Use Object.create instead of Object.assign
var newcallobj = Object.create(callobj);
var Call = function() {
this.number="123";
}
Call.prototype.function1 = function() {
return this.number;
}
var callobj = new Call();
var newcallobj = Object.create(callobj);
console.log(newcallobj.function1());
Ok. By the help of #gurvinder372. The following solution is working for me.
var ABC = function(){
this.number = "333";
}
var Call = function() {
this.number="123";
this.anotherobj = new ABC();
}
Call.prototype.function1 = function() {
return this.number;
}
var callobj = new Call();
var newcallobj = Object.create(callobj);
newcallobj.anotherobj = Object.create(callobj.anotherobj);
newcallobj.anotherobj.number= "123";
console.log(newcallobj.anotherobj.number);
console.log(callobj.anotherobj.number);
Please let me know if there is any better solution other than this?

Simulating Array Functionality

Good day! I have this code:
function MyArray() {}
MyArray.prototype.length = 0;
(function() {
var methods = ['push', 'pop', 'shift', 'unshift',
'slice', 'splice', 'join'];
for (var i = 0; i < methods.length; i++) (function(name) {
MyArray.prototype[ name ] = function() {
return Array.prototype[ name ].apply(this, arguments);
};
})(methods[i]);
})();
I need explanation. I understood that "methods" is array of real methods, which just "exported" to our new class. But, what is this: MyArray.prototype.length = 0; ? Author create new prototype property and assign it zero. And later use this new property!
var mine = new MyArray();
mine.push(1, 2, 3);
assert(mine.length == 3 ...
.....
How it is work? "length" have not instantiation in code above!
Its getting initialized at zero so that if you never call any of its functions, it will return zero (like a real array) and not undefined. Also it needs to start at zero so that the methods update it correctly. in your example, length its 3 because the push method did so.
You can't really subclass Array http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/
So if you create an instance of MyArray you can't do: MyArr[0]=...
You can wrap an array inside MyArray and take advantage of the Array functions:
var MyArray=function() {
this.arr=[];
[].push.apply(this.arr,arguments);
//following doesn't work in older browsers
Object.defineProperty(this,"length",{
get:function(){return this.arr.length;},
enumerable:true,
configurable:true
});
}
MyArray.prototype.valueOf=function(){return this.arr;};
(function() {
var methods = ['push', 'pop', 'shift', 'unshift',
'slice', 'splice', 'join'],i=methods.length
while(--i!==-1){
;(function(name) {
MyArray.prototype[ name ] = function() {
console.log(arguments);
return Array.prototype[ name ].apply(this.arr, arguments);
};
}(methods[i]));
}
}());
var mArr1=new MyArray(1,2,3);
console.log(mArr1.slice(0,1));
//you cannot do this: myArr1[0]=22;

Can you use custom objects as properties of an object in javascript?

Suppose I create a custom object/javascript "class" (airquotes) as follows:
// Constructor
function CustomObject(stringParam) {
var privateProperty = stringParam;
// Accessor
this.privilegedGetMethod = function() {
return privateProperty;
}
// Mutator
this.privilegedSetMethod = function(newStringParam) {
privateProperty = newStringParam;
}
}
Then I want to make a list of those custom objects where I can easily add or remove things from that list. I decide to use objects as a way to store the list of custom objects, so I can add custom objects to the list with
var customObjectInstance1 = new CustomObject('someString');
var customObjectInstance2 = new CustomObject('someOtherString');
var customObjectInstance3 = new CustomObject('yetAnotherString');
myListOfCustomObjects[customObjectInstance1] = true;
myListOfCustomObjects[customObjectInstance2] = true;
myListOfCustomObjects[customObjectInstance3] = true;
and remove custom objects from the list with
delete myListOfCustomObjects[customObjectInstance1];
but if i try to iterate through the list with
for (i in myListOfCustomObjects) {
alert(i.privilegedGetMethod());
}
I would get an error in the FireBug console that says "i.privilegedGetMethod() is not a function". Is there a way to fix this problem or an idiom in javascript to do what I want? Sorry if this is a dumb question, but I'm new to javascript and have scoured the internet for solutions to my problem with no avail. Any help would be appreciated!
P.S. I realize that my example is super simplified, and I can just make the privateProperty public using this.property or something, but then i would still get undefined in the alert, and I would like to keep it encapsulated.
i won't be the original object as you were expecting:
for (i in myListOfCustomObjects) {
alert(typeof i); // "string"
}
This is because all keys in JavaScript are Strings. Any attempt to use another type as a key will first be serialized by toString().
If the result of toString() isn't somehow unique for each instance, they will all be the same key:
function MyClass() { }
var obj = {};
var k1 = new MyClass();
var k2 = new MyClass();
obj[k1] = {};
obj[k2] = {};
// only 1 "[object Object]" key was created, not 2 object keys
for (var key in obj) {
alert(key);
}
To make them unique, define a custom toString:
function CustomObject(stringParam) {
/* snip */
this.toString = function () {
return 'CustomObject ' + stringParam;
};
}
var obj = {};
var k1 = new CustomObject('key1');
var k2 = new CustomObject('key2');
obj[k1] = {};
obj[k2] = {};
// "CustomObject key1" then "CustomObject key2"
for (var key in obj) {
alert(key);
}
[Edit]
With a custom toString, you can set the object as the serialized key and the value to keep them organized and still continue to access them:
var customObjectInstance1 = new CustomObject('someString');
var customObjectInstance2 = new CustomObject('someOtherString');
var customObjectInstance3 = new CustomObject('yetAnotherString');
myListOfCustomObjects[customObjectInstance1] = customObjectInstance1;
myListOfCustomObjects[customObjectInstance2] = customObjectInstance2;
myListOfCustomObjects[customObjectInstance3] = customObjectInstance3;
for (i in myListOfCustomObjects) {
alert(myListOfCustomObjects[i].privilegedGetMethod());
}
The for iteration variable is just the index, not the object itself. So use:
for (i in myListOfCustomObjects) {
alert(myListOfCustomObjects[i].privilegedGetMethod());
}
and, in my opinion, if you use an Object as an array index / hash, it just would be converted to the string "Object", which ends up in a list with a single entry, because all the keys are the same ("Object").
myListOfCustomObjects =[
new CustomObject('someString'),
new CustomObject('someOtherString'),
new CustomObject('yetAnotherString')
]
you will get access to any element by index of array.

Javascript - Copying array(by value) into prototype

I was trying to make a constructor function and within it, i had/wanted to place an array:
function Animal(s) {
this.myarr.push(s)
this.bark = function() {
console.log(this.myarr)
}
}
Animal.prototype = {
myarr: []
}
var a = new Animal('a');
a.bark()
var b = new Animal('b');
b.bark()
The problem is that the array will be passed by reference. The result will be:
["a"]
["a", "b"]
I then tried Dean Edwards base class:
var Animal = Base.extend({
constructor: function(s) {
this.some.push(s)
},
some: [],
bark: function() {
console.log(this.some)
}
});
var a = new Animal('a');
a.bark()
var b = new Animal('b');
b.bark()
The result was the same.
["a"]
["a", "b"]
I don't know if this is the way arrays should be handler in a javascript 'class' system... though i can re-initialize that property to [] every time i call the constructor.
So, does anyone know how to deal with this? Should i re-initialize the property(if it's an array)?
Thanks in advanced.
Edit:
The problem here is that whenever the constructor is called(this.myarr.push(s) for example) myarr will point to the same array - that's why after a new instance the array will grow in size.
So:
var a = new Animal('a')
var b = new Animal('ab')
var c = new Animal('abc')
var d = new Animal('abcd')
will result to:
["a", "ab", "abc", "abcd"]
I want(without defining myarr inside the constructor) myarr to have a default value everytime i call the constructor(through new Animal(()) which should be [ ].
If you attach your array to the prototype of the constructor, this array will be available to all instances, so everything an instance does to it, is reflected in .myarr in the other instances. If you want an array per instance, you should define it as a 'local' property, i.e. this.myarr. What you can do is define a method in the prototype that pushes a value into this.myarr.
So your constructor function (classes are non extistent in javascript) could look like:
function Animal(s) {
this.myarr = [];
this.bark = function() {
console.log(this.myarr)
}
this.myarrAdd(s);
}
Animal.prototype = {
myarrAdd: function(val){this.myarr.push(val); return this;}
}

How do i make a copy of an object? Javascript

I have a class in json format. I would like to make two instance. Right now (its pretty obvious why) when i 'make' two objects i really have 2 vars pointing to one. (b.blah = 'z' will make a.blah=='z')
How do i make a copy of an object?
var template = {
blah: 0,
init: function (storageObj) {
blah = storageObj;
return this; //problem here
},
func2: function (tagElement) {
},
}
a = template.init($('form [name=data]').eq(0));
b = template.init($('form [name=data2]').eq(0));
If you want multiple instances, sounds like a constructor might do you some good.
function Template(element) {
this.blah = element;
}
Template.prototype.func2 = function(tagElement) {
//...
};
var a = new Template($('form [name=data]').eq(0));
var b = new Template($('form [name=data2]').eq(0));
b.func2('form');
All methods on the function prototype (Template.prototype) will be accessible from each instance, and with each instance scoped accordingly. The new keyword will run the function and then return to you a brand new object, inheritting from the prototype.
You'll no longer have the exact same object point to a and b.
From the comments What is the most efficient way to deep clone an object in JavaScript?
var b = {}, key;
for (key in a){
if(a.hasOwnProperty(key)){
b[key] = a[key];
}
}

Categories

Resources