creating objects how can I get nested objects too - javascript

I am creating a constructor function. So I need to get my object everything is good except nested objects, how can i do that part?
function creation(name, value, id, name) {
this.name = name;
this.value = value;
this.category = {
id: "",
name: ""
}
}
let creationOne = new creation('book', 350, 1, "Something extraoridnary");
console.log(creationOne);

You need different names for the two name parameters. And then you need to use the parameter variables when creating the nested object.
function creation(object_name, value, id, category_name) {
this.name = object_name;
this.value = value;
this.category = {
id: id,
name: category_name
}
}
let creationOne = new creation('book', 350, 1, "Something extraoridnary");
console.log(creationOne);

Using ES6 Object Property Value Shorthand
Rename the first parameter to bookName.
Now you can assign values to the id and name property inside the category object.
So, you can either do: this.category = {id: id, name: name} OR simply this.category = {id, name}.
function creation(bookName, value, id, name) {
this.name = bookName;
this.value = value;
this.category = {id, name}
}
let creationOne = new creation('book', 350, 1, "Something extraoridnary");
console.log(creationOne);

One option is to pass in the category as an object:
function creation(name, value, category) {
this.name = name;
this.value = value;
this.category = category;
}
let creationOne = new creation('book', 350, { id: 1, name: "Something extraoridnary" });
console.log(creationOne);

Related

How can I manipulate key name in Object with Javascript

I want to do change the name of a key in an Object. But when I want to do this with an if condition, I get this (Assignment to function parameter 'key') error. How can i manipulate a key name ?
My Code:
const personData = [];
Object.keys(testItem).forEach((key) => {
item = testItem[key];
if (key === 'Name'){
key = 'Person Name';
}
personData.push({ name: key, data: Object.values(item) })
});
testItem data:
testItem = {Name: {...}, Surname: {...}}
I want the Name key to change to Person Name without error.
The key variable was taken in as input for the foreach function, and you shouldn't modify it - it is meant as a read only variable. An alternative that doesn't modify the key variable would be
const personData = [];
Object.keys(testItem).forEach((key) => {
let newKey = key;
item = testItem[key];
if (key === 'Name'){
newKey = 'Person Name';
}
personData.push({ name: newKey, data: Object.values(item) })
});
I didn't get what you wanted to do, simply assign keys value to new key and delete previous one for example :
const personData = {
Name: 'John',
lastname: 'Doe'
};
personData.PersonName = personData.Name
delete personData.Name;
console.log(personData.PersonName)

Print getters when and object is printed in typescript

Is there an option in TypeScript/JavaScript to print an object who has private properties using their getters instead of printing the private properties names.
By example I have this class in TypeScript
class Vehicle {
constructor(private _brand: string, private _year: number) {}
get brand(): string {
return this._brand;
}
get year(): number {
return this._year;
}
set year(year: number) {
this._year = year;
}
set brand(brand: string) {
this._brand = brand;
}
}
const vehicle: Vehicle = new Vehicle('Toyota', 10);
console.log(vehicle);
I got this
[LOG]: Vehicle: {
"_brand": "Toyota",
"_year": 10
}
But I'm wondering if I can get something like this
[LOG]: Vehicle: {
"brand": "Toyota",
"year": 10
}
What console.log does varies by environment. If you want to do what you're describing, you'd have to write your own logger function instead, for instance (in JavaScript, but types are fairly easily added) see comments:
function log(obj) {
// Get the names of getter properties defined on the prototype
const ctor = obj.constructor;
const proto = ctor?.prototype;
const names = new Set(
proto
? Object.entries(Object.getOwnPropertyDescriptors(proto))
.filter(([_, {get}]) => !!get)
.map(([name]) => name)
: []
);
// Add in the names of "own" properties that don't start with "_"
for (const name of Object.keys(obj)) {
if (!name.startsWith("_")) {
names.add(name);
}
}
// Create a simple object with the values of those properties
const simple = {};
for (const name of names) {
simple[name] = obj[name];
}
// See if we can get a "constructor" name for it, apply it if so
let objName =
obj[Symbol.toStringTag]
|| ctor?.name;
if (objName) {
simple[Symbol.toStringTag] = objName;
}
// Log it
console.log(simple);
}
Live Example:
"use strict";
function log(obj) {
// Get the names of getter properties defined on the prototype
const ctor = obj.constructor;
const proto = ctor?.prototype;
const names = new Set(
proto
? Object.entries(Object.getOwnPropertyDescriptors(proto))
.filter(([_, {get}]) => !!get)
.map(([name]) => name)
: []
);
// Add in the names of "own" properties that don't start with "_"
for (const name of Object.keys(obj)) {
if (!name.startsWith("_")) {
names.add(name);
}
}
// Create a simple object with the values of those properties
const simple = {};
for (const name of names) {
simple[name] = obj[name];
}
// See if we can get a "constructor" name for it, apply it if so
let objName =
obj[Symbol.toStringTag]
|| ctor?.name;
if (objName) {
simple[Symbol.toStringTag] = objName;
}
// Log it
console.log(simple);
}
class Vehicle {
constructor(_brand, _year) {
this._brand = _brand;
this._year = _year;
}
get brand() {
return this._brand;
}
get year() {
return this._year;
}
set year(year) {
this._year = year;
}
set brand(brand) {
this._brand = brand;
}
}
const vehicle = new Vehicle('Toyota', 10);
log(vehicle);
Lots of room to tweak that how you like it, that's just a sketch of how you might go about it.
I don't think there is a way to do that, but you could create a log method in the class, like this:
log() {
console.log({
brand: this.brand,
year: this.year,
});
}
And then simply call vehicle.log();
You'd then get a log like this {brand: 'Toyota', year: 10}

Get arguments of constructor in JS class

How can i get an array of the arguments of a constructor class in JS? It's possible? Thanks in advance.
class Product {
constructor(id, name, price, category, stock){
this.id = id;
this.name = name;
this.price = price;
this.category = category;
this.stock = stock;
}
};
console.log(Product.constructor.params);
//expected output = ['id', 'name', 'price', 'category', 'stock'];
Inspired form #Porter answer and #evolutionxbox, I think that a reliable way would be using .match() like this:
class Product {
constructor(id, name, price, category, stock, unusedArgument) {
this.id = id;
this.name = name;
this.price = price;
this.category = category;
this.stock = stock;
}
}
class Noarguments {
constructor() {
}
}
// A function
function getClassContructorParams(obj){
let match = obj.toString().match(/constructor\((.+)\)/)
if(match && match[1]){
return match[1].split(",");
}
// If no match
return []
}
console.log(getClassContructorParams(Product))
/// Testing a class with no constructor arguments will return an empty array
console.log(getClassContructorParams(Noarguments))
My previous answer was returning the object properties, which may be different from the arguments used in the constructor...
Now using .match() will ensure what is returned really are the constructor arguments.
let s = Product.toString();
let params = s.substring(s.indexOf('(')+1, s.indexOf(')')).split(',')
My point in the comments was it seems you're coming at this problem from the wrong direction. Maybe take this approach. Have an array of labels, and array of data, and pass those into the class. You'll still have the array of labels to access (and validate) in your other code, and everything will still work.
const labels = [ 'id', 'name', 'price', 'category', 'stock' ];
const data = [ 1, 'Bob', 100, 2, 1];
class Product {
constructor(labels, data) {
data.forEach((el, i) => this[labels[i]] = el);
}
};
console.log(new Product(labels, data));
console.log(labels);
Or, if your products are identical in terms of properties you could just use an array of them, and use Object.keys to get the labels of the first object.
const data = [{ id: 1, name: 'Bob', price: 100, category: 2, stock: 1 }];
const labels = Object.keys(data[0]);
class Product {
constructor(data) {
for (let key in data) {
this[key] = data[key];
}
}
};
console.log(new Product(data[0]));
console.log(labels);

Assign object values to class values

so I've encountered a problem with assigning object values to class values. Basically, let's say that I have a class Account and an object with the same properties as the class
class Account {
id: Number;
name: String;
}
const accountObject = {
id: 4216,
name: "Test name"
}
const account = new Account();
//set values from accountObject to account as a class
account.id = accountObject.id;
//...
So is there a way to assign values from an object to a class without doing it manually? I have a lot of properties that I need to be assigned and doing it by hand would solve the issue but if there's a prettier way to do so, I'd really appreciate any help
A simple loop should do the trick:
class Foo {
name = "foo"
age = 1
}
const foo = new Foo()
const bar = {
name: "bar",
age: 100
}
for (let key in bar) {
foo[key] = bar[key]
}
console.log(foo) // prints Foo { name: 'bar', age: 100 }
console.log('----------------------------------');
Object.entries(bar).forEach(
([key, value]) => (foo[key] = value)
)
console.log(foo) // prints Foo { name: 'bar', age: 100 }
class Account {
constructor({
id,
name
}) {
this.id = id;
this.name = name;
}
}
const account = new Account({
id: 4216,
name: "Test name"
});
console.log(account);

Modify JS Object in Pure Way

I have a function that transforms a JS object. It derives a new property from an existing one, then deletes the original property. Essentially something like this:
/** Derives "capName" property from "name" property, then deletes "name" */
function transform(person) {
person["capName"] = person["name"].toUpperCase();
delete person["name"];
return person;
}
var myPerson = {
name: "Joe",
age: 20
};
var newPerson = transform(myPerson);
console.log(myPerson, newPerson);
The function returns the desired newPerson object, but also modifies the original myPerson object. I would rather do this in a pure way, that doesn't modify the original myPerson object.
Note: I really need to be ES5 compatible, but I'd like to see the ES6 solution as well.
Quite easy with destructuring:
const transform = ({ name, ...rest }) => ({ capName: name.toUpperCase(), ...rest });
I really need to be ES5 compatible
Use BabelJS, it makes your life so much eaiser.
just use Object.assign which will create a new object with new reference
function transform(person) {
var obj = Object.assign({}, person);
obj["capName"] = obj["name"].toUpperCase();
delete obj["name"];
return obj;
}
var myPerson = {
name: "Joe",
age: 20
};
var newPerson = transform(myPerson);
console.log('newPerson:', newPerson);
console.log('myPerson:', myPerson);
For ES5 compatibility, you can use JSON.parse(JSON.stringify(person)). Be aware that methods attached to person are lost on the way because they cannot properly be JSON.stringifyed.
/** Derives "capName" property from "name" property, then deletes "name" */
function transform(person) {
var obj = JSON.parse(JSON.stringify(person));
obj["capName"] = obj["name"].toUpperCase();
delete obj["name"];
return obj;
}
var myPerson = {
name: "Joe",
age: 20
};
var newPerson = transform(myPerson);
console.log(myPerson, newPerson);
If you want to retain methods, just iterate over the object keys:
/** Derives "capName" property from "name" property, then deletes "name" */
function transform(person) {
var obj = {};
for (var key in person) {
obj[key] = person[key];
}
obj["capName"] = obj["name"].toUpperCase();
delete obj["name"];
return obj;
}
var myPerson = {
name: "Joe",
age: 20
};
var newPerson = transform(myPerson);
console.log(myPerson, newPerson);
Be aware that none of the methods presented does a deep clone. For that, I'd recommend you use something like lodash's _.clone(obj, { deep: true });
You could generate a new object without the unwanted and a new property.
function transform(person) {
return Object
.keys(person)
.reduce(function (r, k) {
if (k === 'name') {
r.capName = person.name.toUpperCase();
} else {
r[k] = person[k];
}
return r;
}, {});
}
var myPerson = { name: "Joe", age: 20 },
newPerson = transform(myPerson);
console.log(myPerson);
console.log(newPerson);

Categories