I have
class A{
users = new B().users;
}
class B{
users : Array<any> = [];
}
at the first run the users fields are the same in both classes , but when users in class B changed the users in A isn't changed .
example : at first A.users and B.users are [user1]
when I add new user to B.users ([user1, user2]) A.users still the same .
Any idea ?
Thanks in advance ...
Any idea
Depends on how you add them. If you are doing something like b.users = b.users.concat([another]); then b.users will be a new array distict from the one that is referenced by A.
NOTE: Having two classes point the same array seems like a bad idea where mutation will quickly get out of hand and you will not know what moved your cheese. But there isn't more architecture advice I can give without a larger context that you can present in a separate question if you want.
Related
I just started learning Linked List for a technical interview, so this question might seem a little weird.
I was reading an introduction article about Linked List from freecodecamp, and this is what the article
In JavaScript, a linked list looks like this:
const list = {
head: {
value: 6
next: {
value: 10
next: {
value: 12
next: {
value: 3
next: null
}
}
}
}
}
};
My question is, is this a real Linked List? Say I get a question "Print out all the elements in the following linked list, and implement a Linked List yourself." Can I just use the above code? I do know how to use classes to implement a linked list, but I am just wondering if the above code counts as a linked List.
I am asking this question because I only know how to solve the array algorithm question so far.
Say I want to print out all the elements in the array. I will need three steps.
Create an array. // Nums = [1,2,3];
write a function to print it out. // function printNums(Nums){ for (...){console.log(Nums[i]}}
call the function. // printNums(Nums);
So now, I want to do a Linked List version of this. How should I do it?
New Update:
So this is my LinkedList version of printing out all the elements. As a comment mentioned, what I did in the code is in fact a linked list, but it's not called implementation. But what if I just want to test my function? Does the following code make sense to you guys?
My question is, is this a real Linked List?
Yes, it is. You have a collection of data elements, where each data element points to the next.
Say I get a question "Print out all the elements in the following linked list, and implement a Linked List yourself." Can I just use the above code?
When asked to print a specific linked list, we should assume that it is made clear what the exact interface is of that linked list (e.g. nodes are linked via a property called next, and their values are accessed via a property called value). In case of the example list, that is clear. So yes, you could use the piece of code you provided.
The question to implement a Linked List yourself, is a different one. Although it could be understood to define one particular list, that is not how most would interpret that question. It is more likely that this means you should implement a linked list interface: i.e. write code that not only provides easy ways to construct any linked list, but also for using it (find a value, insert a node, delete a node, move a node, ...)
I am just wondering if the above code counts as a linked List.
Yes, the object literal you provided is (one particular instance of) a linked list.
Say I want to print out all the elements in the array. I will need three steps.
Create an array. // Nums = [1,2,3];
Here you make use of a feature of the JavaScript language. Implicitly a constructor is behind this: new Array(1, 2, 3). This constructor is provided as part of the core language. You also get access to methods like push, pop, indexOf, slice, splice, ...etc. All out of the box.
The difference with linked lists is that core JavaScript does not offer an implementation for it. You have to throw your own. Sure, you can use an object literal to create one linked list, but it is quite a verbose way (imagine a list with 100 numbers), and error prone (what if you misspelled next somewhere half way?)
So now, I want to do a Linked List version of this. How should I do it?
If the purpose is only to print the content of a linked list, and nothing else, you can do it like you did. But to get something that offers an interface like you get out of the box for arrays, you would write a class with some useful methods, so you could write:
let myList = LinkedList.from(6, 10, 12, 3);
console.log(...myList.values()); // outputs 6 10 12 3
But what if I just want to test my function? Does the following code make sense to you guys?
Yes, that is fine. If you know that your print function will get either null or an object that has value and next properties, where the next property can be null or another such object, ... then it is fine. In other words: you need to know the interface.
var l = head;
while (l != null) {
console.log(l.value);
l = l.next;
}
Trick is to use while loop until next element is null.
let prev: LinkedListElement<T> | null = this._start;
let finalEl: LinkedListElement<T> = prev;
let counter = 0;
while (prev !== null) {
const retVal = callback(prev, counter);
if (!retVal) {
break;
}
finalEl = prev;
prev = prev.next;
counter++;
}
Let me know if this works.
Also look at this LinkedList class I have created, traverse function is matching the requirement you have.
Class GitHub
NPM package - #dsinjs/linked-list
Complete documentation
I am not sure if it´s a react issue or not but I am struggling a lot with this issue. I tried to create just a simple example to post out of my project:
https://codepen.io/as3script/pen/VMbNdz?editors=1111
There are four buttons on the example.
To reproduce the problem press each of the first three buttons to create a text input from and enter a value. For example enter 100 into the first one, 200 into the second and 300 into the third. Now press the fourth button to remove the first input.
It should keep the second and third with their respective values, 200 and 300, but instead it´s showing 100 in the second and 200 in the third.
This code is the same as it is on CodePen, it just didn't allow the link to be posted without this.
class ButtonComponent extends React.Component {
constructor(props) {
super(props);
this.state = {filtersArr:[]}
this.addButtons = this.addButtons.bind(this);
this.removeButtons = this.removeButtons.bind(this);
this.getInput = this.getInput.bind(this);
this.onChangeHandler = this.onChangeHandler.bind(this);
}
addButtons(e){
let tempArr = this.state.filtersArr;
tempArr.push({comp:this.getInput(e.target.id), id:e.target.id});
this.setState({filtersArr:tempArr});
}
removeButtons(e){
console.log(e.target.id);
let newArr = this.state.filtersArr.filter((filter)=>{
return (filter.id !=='FirstButton')
})
this.setState({filtersArr:newArr});
}
onChangeHandler(e){
console.log(e.target.value);
}
getInput(id){
return (
<div>
<h6>{id}</h6>
<input
id="min"
type="text"
placeholder="min"
onChange={this.onChangeHandler}/>
</div>
)
}
render() {
let styles = {
display:'inline-block'
}
return (
<div>
<p>Add three buttons and enter the number in each input, and remove amt.</p>
<button id="FirstButton" onClick={this.addButtons}>FirstButton</button>
<button id="SecondButton" onClick={this.addButtons}>SecondButton</button>
<button id="ThirdButton" onClick={this.addButtons}>ThirdButton</button>
<button id="FirstButton" onClick={this.removeButtons}>Remove firstButton</button>
<ul>
{this.state.filtersArr.map((filter, index)=>{
return <li style={styles} key={index}>{filter.comp}</li>
})
}
</ul>
</div>
);
}
}
ReactDOM.render(
<ButtonComponent/>,
document.getElementById('root')
);
The problem is that you're using the array index as your key, so React will reuse the first two li elements and drop the last one. Change key={index} to key={filter.id}, and it works as you would expect.
Update concerning the comment & downvote: I assumed uniqueness on filters in the actual code, given that the field is called id. The CodePen seems more of a stripped down version to show the problem. But if you do actually wish to let each button create multiple text fields, you'd indeed need to add something extra to distinguish the keys (e.g. a counter). This doesn't affect the problem as stated in the question though.
Looking at the code again, I noticed getInput would be an ideal candidate to extract into a separate (stateless) component, e.g. FilterInput. This fits better with the react model than keeping child renderings in the component state.
The code produces 3 textboxes in divs. These textboxes are updated by entering the numbers (100, 200, 300). When you click the RemoveFirstButton, the state, which stores these components, is updated and render is called.
The render function does a diff of the current state and the previous state and removes the last div, which contains the number 300. This is because, for the render function, the first element of the array changed from FirstButton to SecondButton, the second element changed from SecondButton to ThirdButton and the third element does not exist anymore.
To make it work as expected, you need to change the key of the elements from the index of the array to the id of the element, so that the render method can tell the difference between the elements.
Edit:
Please avoid using your ids as keys as the other answers suggest if multiple of the same elements can be added as your initial example suggests because keys need to be unique and this way they can (and will) be repeated!
Your problem lies in the fact that you are using the key attribute wrongly.
React expects your components to have constant keys, so it can decide when and which ones it needs to update.
If you are modifying an array, the keys of the objects are changing, and the element that had the key '1' before the removal is gone afterwards and the component that previously had key '2' becomes the one with key '1' and so forth.
The React documentation advises against using the index as key as well:
"We don’t recommend using indexes for keys if the items can reorder"
To avoid this you should use some sort of unique key generation and store each components key in it's own object, for example like this:
In the constructor:
this.nextKey = 0
When adding a new component:
tempArr.push({comp: comp, id: e.target.id, key: this.nextKey++});
In the render function:
return <li style={styles} key={filter.key}>{filter.comp}</li>
I modified your example to include these lines, you can find it here:
https://codepen.io/Isti115/pen/MEmMZP?editors=1111
Also, some other tips:
When creating an object that has a key with a value assigned from a variable with the same name, you can shorten it so that this:
{comp: comp, id: e.target.id}
becomes this:
{comp, id: e.target.id}.
If you need something more robust, you could use a separate unique key generator like this:
Create GUID / UUID in JavaScript?
or this:
https://gist.github.com/gordonbrander/2230317
ps.: The switch statement you are using is completely useless right now. What have you tried to accomplish with it?
i got something here that bogs my mind a bit.
let's say i write me this API (in TS), check out some of these properties:
export class MyAPI{
propertyThatShouldContainSuffix:Array<string>; // like .jpg or .mp3
somethingElses:Array<SomethingElse>; //instances of some class
enumProperty:SomeEnum; // enum SomeEnum{a,b,c,d}
constructor(object){
/*
this object is input by the API consumer,
and its properties will be assigned to the new fields of
the new instance
*/
}
}
valid usage example:
var myApi = new MyAPI({
propertyThatShouldContainSuffix : ["img.jpg","video.mp4" ...],
somethingElses : [new SomethingElse(/*yada yada*/),new SomethingElse(/* whateverrr*/) ...],
enumProperty:2
});
input that may cause problems:
var myApi = new MyAPI({
propertyThatShouldContainSuffix : ["img","video",5 ...],
somethingElses : [new SomethingElse(/*yada yada*/),new SomethingTotallyElse(/* whateverrr*/) ...],
enumProperty:6
});
as you can see, the first property is an array of strings that need to have a suffix, like an image, that should be .jpg or .png or whatever. there is an array of objects that should contain some fields, and finally an enum field,
let's say that it ranges from 0 to 3.
now, it all works fine and stuff when you input the expected values into it
(e.g all strings in first array has the right suffix and so on)
but then i thought that i should handle bad input, like a user that
will send all his image names without any suffix, or will give me a "9" as
input for the enum, send objects instead of arrays, and so on.
BUT! and here's the problem: how far should i go with this?
should i check that every property is correct(e.g what is supposed to be an array is really an array, that all "supposed to be suffixed" are suffixed,
that all "somethingelses" contain all correct fields?
because if i do, this is a whole mess of overhead on every creation of an instance of MyAPI object.
or should i only do something real basic like check if he didn't misspell some field in the object(therefore exposing helpless users to the perils of "but why isn't this working?? stupid stupid API!!!") ?
or anything inbetween?
thank you!
I created a pointer column (emailAddress) in parse and pointed it to the _User class. But how do I point this to a specific column(email) in the _User class? Is this done in the code or is this done in Parse? I'm building an app in Javascript.
Pointers are for references to Classes, you cannot create a Pointer for a Column on a Class.
If you want a copy of a column (e.g. a String emailAddress column), you can create an after-save Cloud Function for the User class that checks if the emailAddress is dirty, and if so updates your other class. I would recommend against this though unless there's a very good reason for doing this.
If you have another class that needs one or more column values from your User class the usual way to handle this is to just create a user column of type Pointer<_User>, then when querying your class just tell it to include the user column, e.g.:
query.include('user');
Then in your find() or whatever you use to run the query you can now do the following:
var user = results[i].get('user');
var email = user.get('emailAddress');
I am trying to use the extends for array ..what should I put in the constructor..Here is the code
class List extends Array
constructor: ()->
super arguments
this
list = new List("hello","world")
alert list[0]
Doesn't seem to work..
There is no easy way to "inherit" from the array prototype. You should use composition , i.e.
class List
constructor: ()->
this.array = new Array(arguments);
getArray :()->
this.array
list = new List("hello","world")
alert list.getArray()[0]
or you will spend your time implemented complicated solutions that will fail as soon as you try to parse the array or access its length value.
more on the issue :
http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/
I haven't been using coffee script lately, so this is just a guess, but maybe something like:
class List extends [].prototype
might work?
EDIT: Per "mu is too short"'s comment, it seems the problem isn't coffee script related at all. You might find this related SO post useful, as the selected answer provides two possible solutions to this problem:
Is this a reasonable way to 'subclass' a javascript array?