why is there comma separator after a method of object? - javascript

i am trying to follow a tutorial class building a Game. where i found those mysterious commas. can anyone tell me why should i have to put comma after every methods in an object.
let GameManager = {
setGameStart: function(classType) {
this.resetPlayer(classType);
this.setPreFight();
},
resetPlayer: function(classType) {
switch (classType) {
case "Warrior":
player = new Player(classType, 200, 200, 100, 50);
break;
let getInterface = document.querySelector(".interface");
getInterface.innerHTML = '<div><h3>' + classType + '</h3></div>';
}, setPreFight: function() {
let getHeader = document.querySelector(".header");
getHeader.innerHTML = '<p>Task: Find and enemy!</P>'
},

Because GameManager is an object initializer & according to mdn
an object initializer is a comma-delimited list of zero or more pairs
of property names and associated values of an object, enclosed in
curly braces
let obj = {
prop1: 'someProp',
prop2: 'someProp2',
func1: function() {
console.log(`${this.prop1} ${this.prop2}`)
}
}
obj.func1()
GameManager is similar to the object obj & you call its method by GameManager.setGameStart and so

where i found those mysterious commas. can anyone tell me why should i
have to put comma after every methods in an object.
Ref
No this is not mysterious This is what syntax of object is
You need to seprate key/value pair by comma except the last key/value pair

You are getting confused with creating an object and creating a function. Here, you are creating an object. So the rules of creating objects are to be followed. Each property:value pair must be separated with comma-delimiter. Please note that you can assign function as value of a property as you are doing in the example.
let GameManager = {
//**THIS IS A PROPERTY:VALUE PAIR**
setGameStart: function(classType) {
this.resetPlayer(classType);
this.setPreFight();
},
//**THIS IS ALSO A PROPERTY:VALUE PAIR
someProperty: someValue,
When creating an independent function, you don't do that.
function printSomething(){
console.log("something");
}
function printSomethingElse(){
console.log("somethingElse");
}

Related

Can you create object property names using template literals in javascript?

I'm attempting to write a function that takes an array of Strings as its input. The function should return an object with (1) key, value pair. The first element of the array should be the property name and the last element of the array should be its key.
function transformFirstAndLast(array){
return {`${array[0]}`: array[length-1];}
}
The above gives me an error. Can someone provide a detailed explanation why this isn't working? I'd like to avoid creating separate variables to store the values from the first and last array indices.
Your question really boils down to, "Can I use expressions as keys in object literals?"
The answer is yes (since es6):
function yell(template, ...parts) {
return parts[0] + '!';
}
function foo() {
return 'bar';
}
class Person {
constructor(first, last) {
this.first = first;
this.last = last;
}
toString() {
return `${this.first} ${this.last}`;
}
}
let names = ['Abe'];
let my_obj = {
[3+5]: 'some_value',
[yell `${foo()}`]: foo(),
[names[0]]: 64,
[new Person('Rafael', 'Cepeda')]: 25
};
console.log(my_obj);
As long as the expression evaluates to a string, all is fair.
You are missing the { and you can't use a template strings as a key. To use a "variable" as a key in an object, you should use the brakets around the variable. Here's the working code.
function transformFirstAndLast(array){
return {[array[0]]: array[array.length-1]};
}
I guess template literal is unnecessary here simply try like this way after fixing this line array[length-1] because its wrong, correct one is array[array.length-1]. I've added more verbose code but you can also do the shorthand version like return {[array[0]]: array[array.length-1]}; on your transformFirstAndLast(array) function.
function transformFirstAndLast(array){
const result = {};
result[array[0]] = array[array.length-1];
return result;
}
console.log(transformFirstAndLast(['a','b','c','d','e']))
yes you can use string literals as key. But the thing is that they are calculated in the run time. So you need to treat them as expressions. And to have variables/expressions as your keys you need to wrap them inside []
let a = {
`key`: value
} // is not allowed
let a = {
[`key`]: value
} // is allowed since you have wrapp
for your case
return {[`${array[0]}`]: array[array.length-1]};
Now since you have wrapped the array[0] item inside a string literal, you will get string values for your zero'th item. If your array[0] is to be a object this would not work as well. It needs to be either string or number. Or else you would get "[object Object]" as your key
var input = ["name", "fname", "lname", "stackOverflow"];
function transformFirstAndLast(array){
return {[array[0]]: array.pop()}
}
responseObject = transformFirstAndLast(input)
console.log(responseObject)

Javascript: Convert code string and back

Suppose that I have this code:
var cfg = {
config: {
fields: {
name: {
type: 'text'
},
age: {
type: 'number'
}
},
actions: [
{
label: 'Print',
cb: (model) => {
console.log(model);
}
}
]
},
data: {name: 'Jhon', age: 23}
}
And I want to convert it to a string (to let a user edit it) and then convert it back to executable code, any idea in how to achieve this?
I tried with JSON.stringify and JSON.parse but that will of course strip the functions. .toString returns "[object Object]", iterating on the object and call .toString when the values is a string, function or number is a possibility, any other idea?
The Function constructor takes code as string, so does eval and a couple other. However, if in any way avoidable, do not convert code to string and backwards because of security concerns, ability to debug and a lot of other issues you can run into when doing so.
Converting code to a string is slightly annoying, because you need to make sure you don't redeclare variables and everything in the new context is syntactically correct, e.g. note that obj's f property is again named in the declaration, because it is later given to eval which places it in the global scope where it needs a name.
let obj = { f: function f() { let stuff = "hi"; console.log("hi"); } };
let code = obj.f.toString();
console.log(code);
eval(code);
f();
Note that JSON.stringify has an optional replacer parameter which can be used to customize the process.
I will again highly advise to avoid any code to/from string conversions when possible, in all normal cases this is not needed and should not be done.
You can iterate around that object and set it to inputs elements, like this
for (var key in cfg.config.fields) {
console.log(key, cfg.config.fields[key].type);
console.log(key, cfg.data[key],'data');
console.log('<input type="'+cfg.config.fields[key].type+'" value="'+cfg.data[key]+'">')
}
This is the solution I came up with:
const toString = (code) => {
if(Array.isArray(code)){
return code.map(item => toString(item));
}
else if(typeof code == 'object'){
let tmp = {};
Object.keys(code).forEach(key => {
tmp[key] = toString(code[key])
});
return tmp;
}
else{
return code.toString().split('\n').join('').replace(/ +(?= )/gmi, '');
}
};
This will iterate recursively across all the properties in a random JS structure (an object containing objects and arrays) an return the corresponding structure containing strings, you can then use JSON.stringify to get the actual string.
After the user edited it, it is executed with:
eval(`(${string})`);
As noted by other, be careful using eval, it can be dangerous (an interesting article is https://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/)

Javascript: How to create an object from a dot separated string?

I ran into this potential scenario that I posed to a few of my employees as a test question. I can think of a couple ways to solve this problem, but neither of them are very pretty. I was wondering what solutions might be best for this as well as any optimization tips. Here's the question:
Given some arbitrary string "mystr" in dot notation (e.g. mystr = "node1.node2.node3.node4") at any length, write a function called "expand" that will create each of these items as a new node layer in a js object. For the example above, it should output the following, given that my object name is "blah":
blah: { node1: { node2: { node3: { node4: {}}}}}
From the function call:
mystr = "node1.node2.node3.node4";
blah = {};
expand(blah,mystr);
Alternately, if easier, the function could be created to set a variable as a returned value:
mystr = "node1.node2.node3.node4";
blah = expand(mystr);
Extra credit: have an optional function parameter that will set the value of the last node. So, if I called my function "expand" and called it like so: expand(blah, mystr, "value"), the output should give the same as before but with node4 = "value" instead of {}.
In ES6 you can do it like this:
const expand = (str, defaultVal = {}) => {
return str.split('.').reduceRight((acc, currentVal) => {
return {
[currentVal]: acc
}
}, defaultVal)
}
const blah = expand('a.b.c.d', 'last value')
console.log(blah)
Here's a method that popped up in my mind. It splits the string on the dot notation, and then loops through the nodes to create objects inside of objects, using a 'shifting reference' (not sure if that's the right term though).
The object output within the function contains the full object being built throughout the function, but ref keeps a reference that shifts to deeper and deeper within output, as new sub-objects are created in the for-loop.
Finally, the last value is applied to the last given name.
function expand(str, value)
{
var items = mystr.split(".") // split on dot notation
var output = {} // prepare an empty object, to fill later
var ref = output // keep a reference of the new object
// loop through all nodes, except the last one
for(var i = 0; i < items.length - 1; i ++)
{
ref[items[i]] = {} // create a new element inside the reference
ref = ref[items[i]] // shift the reference to the newly created object
}
ref[items[items.length - 1]] = value // apply the final value
return output // return the full object
}
The object is then returned, so this notation can be used:
mystr = "node1.node2.node3.node4";
blah = expand(mystr, "lastvalue");
var obj = {a:{b:{c:"a"}}};
const path = "a.b.c".split(".");
while(path.length > 1){
obj = obj[path.shift()];
}
obj[path.shift()] = "a";

Dynamically assigning properties to a JavaScript object (trie)

I'm trying to implement a variation of a trie in JavaScript. Basically, it's an efficient data storage object in which the characters in keys are not repeated. In other words, if I have the keys "abe" and "ann," only one instance of the shared letter "a" should appear:
{
a: {
b: {
e: {
0: 'lincoln'
}
},
n: {
n: {
0: 'mcgee'
}
}
}
}
Here is the desired implementation and a few usage examples:
function Trie () {
// The top level of the trie.
var root = {};
return {
write: function (key, value) {
},
read: function (key) {
}
};
}
// Sample usage
var trie = new Trie();
trie.write('abe', 'lincoln');
trie.write('ann', 'mcgee');
trie.read('abe'); // returns 'lincoln'
trie.read('ann'); // returns 'mcgee'
I've run into a blocker with respect to the write method. Given a string key such as "abe," I need to assign a property to root['a']['b']['e']. I can't find a way to assign a value to an object property several layers deep when the number of keys and the values of the keys are unknown.
The only solution that comes to mind is, I think, a bad one: placing the path to the value into a string and using eval. For example: eval("root['a']['b']['e'] = 'lincoln'");
Is there a better solution for dynamically assigning the values? (I realize that this is a bit of complicated problem, so I'm happy to clarify by providing extra information.)
a very naive approach (given the requirements,though i would write a different implementation)
given a string of keys and a pointer to the root,and a value to assign;
function write(root,path,value){
var a = path.split(''); // 'abc'->['a','b','c']
var pointer = root;
var i=0;
while(i<a.length-1){
if(pointer[a[i]] == undefined){
pointer[a[i]]={};
}
pointer = pointer[a[i]];
i++;
}
pointer[a[i]]=value;
return root;
}
EDIT : i'm assuming all the keys exist on their respective object. I added a if condition in case some keys are not defined.
EDIT:2 split corrected, correcting a little bug right now ;)
EDIT:3 should work now.
usage : write({},'abc',1) // yields {a:{b:{c:1}}}
what you're looking for is a double array trie.
you can do a github search for that, but the two main libraries listed are:
doublearray, from the documentation:
var doublearray = require('./doublearray.js');
var words = [
{ k: 'a', v: 1 },
{ k: 'abc', v: 2 },
];
var trie = doublearray.builder().build(words);
trie.contain('a'); // -> true
trie.lookup('abc'); // -> 2
or datrie

How to access the properties of a JavaScript object?

while review a javascript coding, i saw that
var detailInf = {
"hTitle":"Results",
"hMark":"98"
};
What's the concept behind this js coding. While give alert for the variable its shows as "[object Object]". So this is an object, then how can we access the variable and reveal the data from this object.
Try doing this:
alert(detailInf['hTitle']);
alert(detailInf.hTitle);
Both will alert "Results" - this is a Javascript object that can be used as a dictionary of sorts.
Required reading: Objects as associative arrays
As a footnote, you should really get Firebug when messing around with Javascript. You could then just console.log(detailInf); and you would get a nicely mapped out display of the object in the console.
That form of a JavaScript object is called an object literal, just like there are array literals. For example, the following two array declarations are identical:
var a = [1, 2, 3]; // array literal
var b = new Array(1, 2, 3); // using the Array constructor
Just as above, an object may be declared in multiple ways. One of them is object literal in which you declare the properties along with the object:
var o = {property: "value"}; // object literal
Is equivalent to:
var o = new Object; // using the Object constructor
o.property = "value";
Objects may also be created from constructor functions. Like so:
var Foo = function() {
this.property = "value";
};
var o = new Foo;
Adding methods
As I said in a comment a few moments ago, this form of declaring a JavaScript object is not a JSON format. JSON is a data format and does not allow functions as values. That means the following is a valid JavaScript object literal, but not a valid JSON format:
var user = {
age : 16,
// this is a method
isAdult : function() {
// the object is referenced by the special variable: this
return this.age >= 18;
}
};
Also, the name of the properties need not be enclosed inside quotes. This is however required in JSON. In JavaScript we enclose them in brackets where the property name is a reserved word, like class, while and others. So the following are also equivalent:
var o = {
property : "value",
};
var o = {
"property" : "value",
};
Further more, the keys may also be numbers:
var a = {
0 : "foo",
1 : "bar",
2 : "abz"
};
alert(a[1]); // bar
Array-like objects
Now, if the above object would have also a length property, it will be an array like object:
var arrayLike = {
0 : "foo",
1 : "bar",
2 : "baz",
length : 3
};
Array-like means it can be easily iterated with normal iteration constructs (for, while). However, you cannot apply array methods on it. Like array.slice(). But this is another topic.
Square Bracket Notation
As Paolo Bergantino already said, you may access an object's properties using both the dot notation, as well as the square bracket notation. For example:
var o = {
property : "value"
};
o.property;
o["property"];
When would you want to use one over the other? People use square bracket notation when the property names is dynamically determined, like so:
var getProperty = function(object, property) {
return object[property];
};
Or when the property name is a JavaScript reserved word, for example while.
object["while"];
object.while; // error
That's an object in JSON format. That's a javascript object literal. Basically, the bits to the left of the :'s are the property names, and the bits to the right are the property values. So, what you have there is a variable called detailInf, that has two properties, hTitle and hMark. hTitle's value is Results, hMark's value is 98.
var detailInf = { "hTitle":"Results", "hMark":"98"};
alert(detailInf.hTitle); //should alert "Results"
alert(detailInf.hMark); //should alert "98
Edit Paolo's answer is better :-)
As Dan F says, that is an object in JSON format. To loop through all the properties of an object you can do:
for (var i in foo) {
alert('foo[' + i + ']: ' + foo[i]);
}

Categories

Resources