I'm developing a HTML 5 application.
In Javascript I have defined a custom class and a HashTable implementation:
function Card(newId, newName, newDescription)
{
this.id = newId;
this.name = newName;
this.description = newDescription;
}
function HashTable()
{
var hashTableItems = {};
this.SetItem = function(key, value)
{
hashTableItems[key] = value;
}
this.GetItem = function(key)
{
return hashTableItems[key];
}
}
I use HashTable to add Card's objects. I use this code to add cards:
...
var card = new Card(id, name, description);
$.viacognitaspace.cards.SetItem(id, card);
...
My problem is when I call HashTable.GetItem and I don't know how to cast object returned to Card class.
var cardObject = $.viacognitaspace.cards.GetItem(cardNumber);
Here, cardObject is undefined.
If I do this:
$('#cardName').text(cardObject.name);
I get an error.
How can I fix this?
Try modifying your code to the following:
$.viacognitaspace = {} /* define namespace if not already defined... */
var card = new Card(id, name, description);
/* the "new" keyword creats an instance of your HashTable function
which allows you to reference and modify it later on... */
$.viacognitaspace.cards = new HashTable();
$.viacognitaspace.cards.SetItem(id, card);
You also need to create an instance of the HashTable function.
Example:
http://jsfiddle.net/3BWpM/
Related
I haven't be able to use the push() method to use the new Food constructor to create new items in my pantry array. I need a function to call that will add objects to the array, and I would like for the id value to be calculated based on the current length of the array.
I have tried to create functions like
groceries = function ()
{
pantry.push(new Food)};
var pantry =
[
egg = new Food (1, "Egg", ...)
...
...
];
function Food (id, name,...)
{
this.id = id;
this.name = name;
...
};
this.inquiry = function() {
return '\n' + this.name +
'\n' +
};
I can go to the browser and pantry.push(chicken = new Food(... arguments...); but I'm coming up short on knowledge in how to construct a function that would make the process cleaner. I'm not sure if this is just how it is. Maybe I can't do this with a constructor in mind. I'm very new.
I expect there is a way to type in a function that will use my constructor to format new variables and then push them to the end of my pre made variable pantry. I'd like to be able to use this function in the browser.
so far i'm getting errors like function not defined or syntax error.
I think you mean class instead of function. new can only use for class. Like below.
class Food {
constructor(id, name) {
this.id = id;
this.name = name;
}
inquiry() {
return '\n' + this.name + '\n';
}
}
var pantry = [ new Food(1, "Egg") ];
console.log(pantry);
console.log(pantry[0].inquiry());
Here is yet another solution you could use
class FoodStore{
constructor() {
this.data = [];
}
add(name){
this.data.push({id: this.data.length,name});
}
toList(){
return this.data;
}
}
var store = new FoodStore();
store.add("test");
//inquiry
console.log(store.toList()[0].name);
// All items
console.log(store.toList());
I am new in JavaScript/jQuery. Wondering if there is any better way to return an object by a function.
//this is the Object creator.
function makeNewPlayer(name, score) {
var player = {};
player.name = name;
player.score = score;
return player;
};
This is how I use the function.
var player_info = makeNewPlayer('Bob' ,100);
However, when I use the object, I need to call it like this:
player_info.player.name
player_info.player.score
It looks stupid, any way to use the object directly like this?
player_info.name
player_info.score
edit:
As I don't know how many object will be created by the function.
Let say there is a for loop to make score_1, score_2 etc.
function makeNewPlayer(name, score) {
var player = {};
player.name = name;
for(i=0, i<number_of_score, i++){
eval("player.score_" + i) = score[i];
};
return player;
};
You can use destructing assignment to declare global or locally scoped variables
//this is the Object creator.
function makeNewPlayer(name, score) {
var player = {};
player.name = name
player.score = score
return player;
};
var player_info = makeNewPlayer("Bob", 100);
{
let {name: _name, score} = player_info;
// do stuff with `_name`, `score`
console.log(_name, score);
}
Use new.
I copied some text from my blog that happened to resolve your doubts:
A constructor is a special function used for creating an object:
Example:
function StarkIndustries(name, birth) {
this.name = name;
this.birth = birth;
}
var iron1 = new StarkIndustries('iron01', 2017);
var iron2 = new StarkIndustries('iron02', 2017);
alert(iron1.name);
alert(iron2.name);
Result:
iron01
iron02
By adding new before a function, the function is turned into a
constructor that constructs an object.
But it is dangerous to call a function designed as a constructor
without new, because it will modify the global object window. So sanity check inside the constructor is required:
if (!(this instanceof StarkIndustries)) {
warn("StarkIndustries is a constructor and should be called with `new`");
}
Back to your code, it should be:
function makeNewPlayer(name, score) {
this.name = name
this.score = score
};
var iron1 = new makeNewPlayer('iron01', 2017);
Aside for the fact that "Bob" should be in quotes, it's working fine for me.
var player_info = makeNewPlayer('Bob', 100);
and then I am able to access it just fine like this:
player_info.name
player_info.score
function makeNewPlayer(name, score) {
return {name, score};
};
let players = [];
// in for loop -- sample code only, you need to supply name & score
{
players.push(makeNewPlayer(name, score));
}
You can use a temporary constructor function inside of your function :
function makeNewPlayer(name, score){
const Player = function(name, score){
this.name = name;
this.score = score;
};
return new Player(name, score);
}
You can also use an external function instead of a nested one.
With no change to your function, i am able to get the output the way you want it
player_info.name
player_info.score
Check out the snippet below
//this is the Object creator.
function makeNewPlayer(name, score) {
var player = {};
player.name = name
player.score = score
return player;
};
var player_info = makeNewPlayer("Bob", 100);
console.log(player_info.name);
console.log(player_info.score);
I'm kinda new with js + ES6 + class; I have problem with creating function inside constructor.
#1. I need to add new Hobby, a person allowed to have plenty hobbies ;
#2. I don't know how to show all the data of students;
another questions are in the comments ,in case if you want to answer it too, if not i'm also fine.
so here's my code :
class Student {
constructor(name,hobbies){
this.name = name;
var hobby = new Set(); //do I set here or inside the function ??
//since the function addHobbies also need, then it's fine to be global right ?
this.hobbies = (hobbies) => { //function ES6 like this right ??
this.hobbies = hobby.add(hobbies);
return this.hobbies; //can I return hobby instead of this.hobbies ??
};
}
setName(newName){
this.name = newName;
}
addHobbies(newHobbies){
this.Hobbies = hobby.add(newHobbies); //it should be like this to add >> to set ?
}
getName(){
return this.name;
}
getHobbies(){
return this.hobbies;
}
}
and how to return all the data ?
let andy = new Student("andy","dance");
let vince = new Student("vince","codding");
so it will show all students-attribute by getCode() ?
do I set here or inside the function ??
That depends on what you need. Do you want each Student instead to have one set of hobbies, or do you want to create a new set every time the function is called?
this.hobbies = (hobbies) => { //function ES6 like this right ??
this.hobbies = hobby.add(hobbies);
That doesn't work at all. You're creating the property with a function value, but when the method is called you're overwriting the property with the return value of the add method.
To make it work, I'd recommend making the .hobbies set an instance property instead of a local variable.
class Student {
constructor(name, ...hobbies) {
this.name = name;
this.hobbies = new Set();
this.addHobbies(...hobbies);
}
getName() {
return this.name;
}
setName(newName) {
this.name = newName;
}
getHobbies() {
return this.hobbies;
}
addHobbies(...newHobbies) {
for (const newHobby of newHobbies)
this.hobbies.add(newHobby);
}
}
Alternatively, if you insist on using a local constructor variable, it would look like this:
class Student {
constructor(name, ...hobbies) {
this.name = name;
this.hobbies = new Set(...hobbies);
this.getHobbies = () => {
return this.hobbies;
};
this.addHobbies = (...newHobbies) => {
for (const newHobby of newHobbies)
this.hobbies.add(newHobby);
};
}
… // further methods (for name etc)
}
Try this:
class Student {
constructor(name, hobbies) {
this.name = name;
// Allow passing both an array of hobbies and a single hobby
this.hobbies = Array.isArray(hobbies) ? new Set(hobbies) : new Set([hobbies]);
}
setName(newName) {
this.name = newName;
}
addHobbies(newHobbies) {
if (Array.isArray(newHobbies)) {
newHobbies.forEach((hobby) => this.hobbies.add(hobby));
} else {
this.hobbies.add(newHobbies);
}
}
getName() {
return this.name;
}
getHobbies() {
return this.hobbies;
}
}
let andy = new Student("andy","dancing");
let vince = new Student("vince",["codding", "running"]);
andy.addHobbies("slipping");
vince.addHobbies(["running", "eating"]);
You are in the correct direction. I have rewritten your class to do what I think is more similar to what you are trying to achieve.
Play with the code at: https://jsbin.com/vejumo/edit?js,console
And here's the rewritten class:
class Student {
constructor(name, hobbies = []){
this.name = name;
// new Set() is used to work with objects. It does not work with well with strings
// Let's use an array to store the hobbies.
// if a hobby or an hobbies array is passed, store it, otherwise set an empty array.
this.hobbies = this.parseHobbies(hobbies);
}
// This function will normalize the hobbies to an Array
parseHobbies(hobbies) {
if (typeof hobbies === "string") {
// hobbies is a string, means it's a single hobby and not an array
return [hobbies];
}
// Assuming the hobbies is a an Array
return hobbies;
}
setName(newName) {
this.name = newName;
}
// this function will allow you to add a single hobby to the array
addHobbies(hobbies = []) {
// Same logic like in constract, this can accept a string or an array
// We use Array.concat and push to append to array
this.hobbies = this.hobbies.concat(this.parseHobbies(hobbies));
}
getName() {
return this.name;
}
getHobbies() {
return this.hobbies
}
// This will return all student attributes.
getAttributes() {
// Return a copy of all the attributes instead of returning references
return Object.assign({}, this);
}
}
let george = new Student("George", "Sports");
george.addHobbies(["Singing", "Fishing"]);
george.addHobbies("Dancing");
console.log(george.getAttributes());
Firstly, sorry for my lack of terminology.
If I have a constructor
function myObject(name, value){
this.name = name;
this.value = value;
}
and I make a few objects from it
var One = new myObject("One", 1);
var Two = new myObject("Two", 2);
Can I loop through each new Object made from the myObject class, without putting each new Object into an Array?
would it be possible to add an Instantly Invoking Function to the constructor that adds the Object into an array?
e.g.
function myObject(name, value){
this.name = name;
this.value = value;
this.addToArray = function(){
theArray.push(this); // this is the IIFE
}();
}
that way any new objects created instantly run this function and get added to the array.
Is this possible? ( current syntax does not work, obviously )
EDIT Coming back to this one year later I can tell you that it IS possible. You just call the function inside the constructor like so:
function myObject(name, value){
this.name = name;
this.value = value;
this.addToArray = function(){
theArray.push(this);
};
this.addToArray();
}
Here is an example of this in JSFIDDLE, pushing each object into an array on instantiation and then calling each object's .speak() method directly from the array.
https://jsfiddle.net/Panomosh/8bpmrso1/
Without using an array, you can't, it is not the way it is meant to be used.
What you can do though, is watch over each instances created in a static member of myObject class
function myObject(name, value){
this.name = name;
this.value = value;
this.watch();
}
myObject.prototype.watch = function () {
if (myObject.instances.indexOf(this) === -1) {
myObject.instances.push(this);
}
};
myObject.prototype.unwatch = function () {
myObject.instances.splice(myObject.instances.indexOf(this), 1);
};
myObject.instances = [];
No, you cannot. You cannot do this with almost all programming languages.
You can, in the constructor, store a reference of every object you created into an array/map so that you can iterate over them any time. This, however, prevents all objects of this class from being garbage collected, so use it with care.
The WeakMap in JavaScript keeps only a week reference to the keys, but it, in turn, does not allow you to loop over all keys. So it is not an option either.
var MyClass = (function() {
var _instances = [];
function MyClass(name, value) {
_instances.push(this);
this.name = name;
this.value = value;
}
MyClass.each = function(cb) {
for (var i in _instances) {
if (_instances.hasOwnProperty(i)) {
cb(_instances[i]);
}
}
}
return MyClass;
})();
new MyClass('John', 10);
new MyClass('James', 20);
MyClass.each(function(item) {
console.log(item);
});
I need to migrate a code in java to javascript.
In java, I am maintaining a hashmap with key = string and value = arraylist of objects
I need to implement the same in javascript:
this.hashMap = new Hash();
this.hashMapArrayList =[];
...
var hashMapDataSet = new HashMapDataSet(id1,name1,type1);
this.hashMapArrayList[0] = hashMapDataSet;
...
this.hashMap.set(fileName1, this.hashMapArrayList);
var hashMapDataSet1= new HashMapDataSet(id2,name2,type2);
this.hashMapArrayList[0] = hashMapDataSet1;
this.hashMap.set(fileName2, this.hashMapArrayList);
But when I try to get the properties for a specified key
this.hashMap.get(fileName1).getId()
I get the value= id2 which is the last id that was set for HashMapDataSet object.
I have tried to mimic getters and setters in javascript as specified in the following link:
http://javascript.crockford.com/private.html
Here is the HashMapDataSet class
function HashMapDataSet(pId, pName, pType) {
var id = pId;
var name = pName;
var type = pType;
function getId1() {
return id;
}
function setId1(mId) {
id = mId;
}
....
this.getId = function () {
return getId1();
};
this.setId = function (id) {
setId1(id);
};
...
}
where getId1, setId1 are private methods and
getId, setId are priviledged methods
I am new to javascript, so I am unable to correlate java object with javascript. Kindly help.
I'm not quite sure what you're trying to do there, but in javascript you don't need all this java wiring, because the language has built-in maps and lists. Your snippet can look like this in js
this.hashMap = {};
this.hashMapArrayList =[];
...
this.hashMapArrayList.push({id: id1, name: name1, type: type1});
...
this.hashMap.fileName1 = this.hashMapArrayList;
this.hashMapArrayList.push({id: id2, name: name2, type: type2 });
this.hashMap.fileName2 = this.hashMapArrayList;
The javascript-closure-loop problem is very common.
I would take a lot to: http://www.javascriptkata.com/2007/04/11/a-common-problem-with-the-powerful-javascript-closures/
Regards.
for the class you needn't private functions, you can use directly privileged functions:
function HashMapDataSet(pId, pName, pType)
{
var id = pId;
var name = pName;
var type = pType;
this.getId = function ()
{
return id;
};
this.setId = function (pId)
{
id = pId;
}
}