Say I have this:
interface Point {
x: number;
y: number;
}
interface Line {
vertix1: Point;
vertix2: Point;
}
let v1: Point = { x: 1, y: 2 };
let v2: Point = { x: 1, y: 2 };
let line: Line = {vertix1: v1, vertix2: v2};
How can I define line directly without defining v1 and v2? I tried and that, obviously, did not work:
let line1: Line = {
vertix1: Point = { x: 1, y: 2 },
vertix2: Point = { x: 1, y: 2 },
}
It would be just :
let line1: Line = {
vertix1: { x: 1, y: 2 },
vertix2: { x: 1, y: 2 },
}
classes can easily be skipped thanksfully.
You might be better off using a class which implements an interface.
interface IPoint {
x: number;
y: number;
}
interface ILine {
vertix1: Point;
vertix2: Point;
}
class Point implements IPoint {
x: int;
y: int;
constructor(x: int, y: int) {
this.x = x;
this.y = y;
}
}
class Line implments ILine {
vertix1: Point;
vertix2: Point;
constructor(vertix1: Point, vertix2: Point) {
this.vertix1 = vertix1;
this.vertix2 = vertix2;
}
}
let v1: Point = new Point(1,2);
let v2: Point = new Point(1,2);
let line: Line = new Line(v1,v2);
You could also create the points in the constructor. Not sure if this answers your question but hope it helps.
let line: Line = new Line(new Point(1,2), new Point(1,2))
Related
I am new to OOP and just learning now. I want to reinitialise the default location of a circle by using the codes below:
function Circle(radius) {
this.radius = radius;
let defaultLocation = {
x: 0,
y: 0
};
this.getDefaultLocation = function(a, b) {
return defaultLocation
};
Object.defineProperty(this, 'defaultLocation', {
get: function(a, b) {
return defaultLocation;
},
set: function(a, b) {
defaultLocation = {
x: a,
y: b
};
}
});
}
const circle = new Circle(10);
circle.defaultLocation = {
x: 5,
y: 6
};
However, i check in the chrome browser console, the result is:
x: {x: 5, y: 6}
y: undefined
Could you tell me where i done wrong and how to correct it?
Thanks.
You can't pass two variables to set, but you can pass an object (or an array).
class Circle {
get defaultLocation() {
return this._defaultLocation
}
set defaultLocation(loc) {
this._defaultLocation = loc
}
constructor(radius) {
this.radius = radius;
this._defaultLocation = {
x: 0,
y: 0
};
}
}
const circle = new Circle(10);
circle.defaultLocation = {
x: 5,
y: 6
};
I have this code snippet that creates an array of boxes, I want to make it generic so it can also, for example, store a triangle. I'm not quite sure what parameters I need to use or how I need to modify this so it will allow a triangle. It almost seems like it would be better to create an array of triangles then position them to form a box if I want triangles and boxes, but then I'd loose the flexibility of creating easy rectangles. Context: this is a snippet of a program that implements a z-buffer.
class Box {
/** #member {Object} position of the box storing x,y,z coordinates */
position;
/** #member {Object} size of the box storing width and height */
size;
/** #member {Object} color of the box given in RGB */
color;
constructor (props) {
this.position = props.position;
this.size = props.size;
this.color = props.color;
}
/**
* Check if given point is in box
* #param {Number} px coordinate of the point
* #param {Number} py coordinate of the point
* #return {Boolean} point in box
*/
pointInBox (px,py) {
return this.position.x < px && this.position.x + this.size.width > px
&& this.position.y < py && this.position.y + this.size.height > py;
}
}
const boxes = [
new Box({
position: { x: 50, y: 50, z: 10 },
size: { width: 150, height: 50 },
color: { r: 255, g: 0, b:0 }
}),
new Box({
position: { x: 80, y: 30, z: 5 },
size: { width: 10, height: 150 },
color: { r: 0, g: 255, b:0 }
}),
new Box({
position: { x: 70, y: 70, z: 8 },
size: { width: 50, height: 40 },
color: { r: 0, g: 0, b: 255 }
})
];
console.log({ boxes });
.as-console-wrapper { min-height: 100%!important; top: 0; }
With vanilla JS you would have to use inheritance such as below. I would recommend using Typescript, a super set of Javascript, that makes using types a lot easier.
class Shape {
constructor({ color, position}){
this.color = color;
this.positon = position;
}
}
class Cube extends Shape {
constructor({color, position, height, width, length}){
super({ color, position });
this.height = height;
this.width = width;
this.length = length;
}
}
const myCube = new Cube({
color: "#555555",
position: {x: 12, y: 5, z: 9},
height: 12,
width: 12,
length: 12
});
console.log(myCube)
In Typescript, it would look something like this instead:
interface Coordinate {
x: number;
y: number;
z: number;
}
interface Shape {
color: string;
position: Coordinate;
}
interface Box extends Shape {
height: number;
width: number;
length: number;
}
And now, If I want a function that will work for both boxes and shapes, you can do it like this:
function getPosition(shape:Shape){
return shape.position;
}
const myShape: Box = {
color: "red",
position: {
x: 1,
y: 4,
z: 7,
},
height: 12,
length: 12,
width: 12,
};
getPosition(myShape);
Because Box extends shape, the function works for both of them, and any other interface that extends shape.
That's just scratching the surface of what you can do with Typescript.
With Vanilla-JS one of cause is not limited to just one option like choosing an inheritance based approach. Composition, based on tailored mixins, does provide/support the flexibility the OP is looking for.
One also is free of where (and when and even how) to compose, for instance at plain object level within e.g. a factory function or at instantiation time within a class constructor.
// function based "position" mixin.
function withPosition({ x = 0, y = 0, z = 0 }) {
// "position" specifc (default) assignment.
Object.assign(this, { position: { x, y, z } });
}
// function based "shape" mixin.
function asShape({ color='#000', ...position }) {
// "shape" specifc (default) assignment.
Object.assign(this, { color });
// delegate "position" specific assignement
// and default handling to the mixin.
withPosition.call(this, (position || {}));
}
// factory function.
function createRectangle({ width=10, height=10, ...options }) {
const type = {};
// delegate "shape" specific assignements
// and default handling to the mixin.
asShape.call(type, options);
// "rectangle" specifc assignments including defaults.
return Object.assign(type, { width, height });
}
// factory function.
function createCube({ length=10, ...options }) {
// composition via ...
// ... "rectangle" specifc forwarding ...
// ............. and "cube" specific `length` enrichment.
return { ...createRectangle(options), length }
}
class Cube {
// `Cube` type instantiation.
constructor({ width=10, height=10, length=10, ...options }) {;
// delegate "shape" specific assignements
// and default handling to the mixin.
asShape.call(this, options);
// "cube" specifc assignments including defaults.
Object.assign(this, { width, height, length });
}/*
constructor({ length=10, ...options }) {
Object.assign(this, { ...createRectangle(options), length });
}*/
}
const my1stRectangle = createRectangle({
x: 50,
y: 50,
z: 10,
width: 150,
height: 50,
color: '#fc0',
});
const my2ndRectangle = createRectangle({});
const myCubeComposite = createCube({
x: 50,
y: 50,
z: 50,
color: '#c0f',
});
const myComposedCubeType = new Cube({});
console.log({
my1stRectangle,
my2ndRectangle,
myCubeComposite,
myComposedCubeType,
});
console.log(
'(myCubeComposite instanceof Cube) ?',
(myCubeComposite instanceof Cube)
);
console.log(
'(myComposedCubeType instanceof Cube) ?',
(myComposedCubeType instanceof Cube)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
I'm currently storing data as objects inside a array in the following way:
let data = [];
module.exports.init = function() {
database.pool.query("SELECT * FROM data", (error, rows) => {
if (error) {
logUtil.log.error(`Loading failed: ${ error.message }`);
}
else {
rows.forEach((row) => data.push({dimension: row.dimension, x: row.x, y: row.y, z: row.z}));
logUtil.log.info(data);
}
});
};
data will hold the following now: [{ dimension: 2, x: -973.097, y: -133.411, z: 38.2531 }, { dimension: 3, x: -116.746, y: -48.414, z: 17.226 }, { dimension: 2, x: -946.746, y: -128.411, z: 37.786 }, { dimension: 2, x: -814.093, y: -106.724, z: 37.589 }]
Now I'm trying to receive a random object from this array storing a specific dimension parameter.
For example I want to return a random object storing the dimension: 2
I've tried to filter the array using something like:
let result = jsObjects.filter(data => {
return data.dimension === 2
})
then return a random object from the result.
Question: How could I receive this random object in the best way?
You can do it in two steps.
Get all record which satisfy criteria like dimension === 2
let resultArr = jsObjects.filter(data => {
return data.dimension === 2
})
Get random object from result.
var randomElement = resultArr[Math.floor(Math.random() * resultArr.length)];
var arr = [{ dimension: 2, x: -973.097, y: -133.411, z: 38.2531 }, { dimension: 3, x: -116.746, y: -48.414, z: 17.226 }, { dimension: 2, x: -946.746, y: -128.411, z: 37.786 }, { dimension: 2, x: -814.093, y: -106.724, z: 37.589 }]
//Filter out with specific criteria
let resultArr = arr.filter(data => {
return data.dimension === 2
})
//Get random element
var randomElement = resultArr[Math.floor(Math.random() * resultArr.length)];
console.log(randomElement)
You could use Math.random() and in the range of 0 to length of array.
let result = jsObjects.filter(data => {
return data.dimension === 2
})
let randomObj = result[Math.floor(Math.random() * result.length)]
I was wondering if it with rest/spread is possible to only override the existing properties on an object:
let xy = {
x: 1,
y: 2,
}
let xyz = {
x: 41,
y: 23,
z: 1
}
Now i have two objects and i wish to override the existing properties on xy without getting the z property from xyz as well, so my output is the following:
xy = {
x: 41,
y: 23,
}
Is this possible?
Thanks in advance!
Rest/spread will always stuff into a destination what it finds in a source object, if you don't want to use a loop / want a functional approach, go for reduce, e.g.
const xyNew = Object.keys(xyz).reduce((res, key) =>
// if the key is contained in the accumulator, rewrite it with xyz value, else just return the accumulator (res ~ "result")
res[key] ? { ...res, [key]: xyz[key] } : res
, xy);
Here is a simple implementation :-)
let xy = {
x: 1,
y: 2,
}
let xyz = {
x: 41,
y: 23,
z: 1
}
function compute(){
let key = Object.keys(xy);
for(let i=0;i<key.length;i++){
if(key[i] in xyz) xy[key[i]] = xyz[key[i]];
}
}
compute();
console.log(xy);
I have this way to make an array
var playerList = [];
exports.player = function(socket, name)
{
this.id = socket.id;
this.name = name;
this.x = 20;
this.y = 40;
return this
}
exports.addPlayer = function(data)
{
playerList.push(data)
}
And I'm adding items to playerList array like this
var client = new player(socket, data);
exports.addPlayer(client);
But I also got a function that makes the following
exports.getSafeList = function(id)
{
var player_array = playerList.slice();
for(var i = 0; i < player_array.length; i++)
{
if(player_array[i].id != id)
{
player_array[i].id = 'unknown';
}
}
return player_array;
}
And now I do the following
exports.getPlayerList = function()
{
return playerList;
}
console.log(players.getPlayerList())
console.log(players.getSafeList(id))
So far the code is working fine but when I log the 2 functions it seems that getPlayerList variable merges with player_list one, this is the output
When theres just ONE player on the array
[ { id: 'tjvh8XdMtX-o6QYDAAAB', name: 'Raggaer', x: 20, y: 40 } ]
[ { id: 'tjvh8XdMtX-o6QYDAAAB', name: 'Raggaer', x: 20, y: 40 } ]
But when there are more:
[ { id: 'unknown', name: 'Raggaer', x: 20, y: 40 },
{ id: '2-K5At07wLV4BDiAAAAC', name: 'Alvaro', x: 20, y: 40 } ]
[ { id: 'unknown', name: 'Alvaro', x: 20, y: 40 },
{ id: '2-K5At07wLV4BDiAAAAC', name: 'Alvaro', x: 20, y: 40 } ]
As you can see on both arrays id appears as "unknown" when it shouldn't, since I'm not modyfing the playerList array...
The problem is that while Array.prototype.slice() will create a separate copy of the original array, its items will still be references to the same object instances. So modifying an item in one array ends up modifying the corresponding item in the cloned array.
If your items are simple data objects (no functions), this workaround might do the trick for you:
// instead of "var player_array = playerList.slice();"
var player_array = JSON.parse(JSON.stringify(playerList));