I have a class
class Foo {
constructor(x, y) {
this.x = x
this.y = y
Bar() {
console.log(this.x, this.y)
}
I recall seeing a method of referring to this. variables without having to specify this. Something like
class Foo {
constructor(x,y) {
this.x = x
this.y = y
Bar() {
x,y = [this] // something like this
console.log(x, y) // equivalent to this.x, this.y
}
I desire this because I have dozens of statements that call methods on this.ctx - like this.ctx.rect() - and I don't want to have to have this. prepended to all of them for the sake of readability.
Is there a syntax for this?
You can deconstruct this like any JavaScript object,
Bar() {
const {x, y} = this;
}
I do not recommend doing this however, it seems like it would not scale well as a technique.
Objects (including arrays and functions) are handled by reference, meaning that if you write
let a = this.ctx;
then a points to the same object as ctx and you can do a.rect().
Related
I know that you can write functions which work if you input different arguments. However, is there a way to add a function which you can write such as
vector.function(arguments);.
When I write the functions, I use the vector or object as an argument to get the value back, but is there a way to write it like I have above?
var Vector = function(x, y) {
this.x = x;
this.y = y;
}
Vector.prototype.yourFunction = function() {
/* access vector properties */
console.log(this.x, this.y);
}
var vector = new Vector(1,2);
vector.yourFunction(); // 1 2
It looks like what you want it an object containing a set of functions inside of it. When functions are defined inside of an objects, these are commonly referred to as "methods". This is a useful way of "namespacing" a set of common methods. You can achieve this in many ways. Here is the most basic way:
const vector = {
x: 0,
y: 0,
getDirection() {
return Math.atan2(this.y, this.x);
},
};
console.log(vector.getDirection());
This will work fine if you only need one vector. If you want to have many vectors, you can use instantiation to create as many vectors as you need. For example:
// Globally defined function
function getDirection(x, y) {
return Math.atan2(y, x);
}
function Vector(x = 0, y = 0) {
this.x = x;
this.y = y;
this.getDirection = () => {
// Defer to the globally defined function
return getDirection(x, y);
};
return this;
}
const vectors = [new Vector(10, 15), new Vector(0, 10), new Vector(10, 50)];
vectors.forEach((vector) => {
console.log(vector.getDirection());
});
I created an instance of Shape using Object.create() method and tried accessing the property of Shape as follows, but the inherited property becomes undefined:
function Shape(){
this.x = 10;
this.y = 20;
}
var rectangle = Object.create(Shape);
console.log(rectangle.x) // undefined
To create an instance of a constructor, use new
var rectangle = new Shape()
May declare the shape as an object instead of function though functions are first class object in js. Create a function inside this object and return the required value from this function
var shape = {
userProperty: function(x, y) {
this.x = x || 10; // if no value of x is passed it will be 10
this.y = y || 10; // if no value of y is passed it will be 10
return {
x: this.x,
y: this.y
}
}
}
var rectangle = Object.create(shape);
console.log(rectangle.userProperty(40).x) // 40
I have JavaScript files like this:
shape.js
var shape = (function() {
var shape = {};
Object.defineProperty(shape, 'init', {
value: function(x, y) {
this.x = x;
this.y = y;
return this;
}
});
return shape;
}());
circle.js
var circle = (function(parent) {
var circle = Object.create(parent);
Object.defineProperty(circle, 'init', {
value: function(x, y, r) {
parent.init.call(this, x, y);
this.r = r;
return this;
}
});
return circle;
}(shape));
rectangle.js
var rectangle = (function(parent) {
var rectangle = Object.create(parent);
Object.defineProperty(rectangle, 'init', {
value: function(x, y, width, height) {
parent.init.call(this, x, y);
this.width = width;
this.height = height;
return this;
}
});
return rectangle;
}(shape));
rectangle-with-text.js
var rectangleWithText = (function(parent) {
var rectangleWithText = Object.create(parent);
Object.defineProperty(rectangleWithText, 'init', {
value: function(x, y, width, height, text) {
parent.init.call(this, x, y, width, height);
this.text = text;
return this;
}
});
return rectangleWithText;
}(rectangle));
I also have other JavaScript files like constants.js, customErrors.js, validator.js, player.js, renderer.js, game.js, initializator.js, main.js in the same coding style.
Now I want to do some collision detection with a simple JavaScript library for performing 2D collision detection but I must type somewhere
var SAT = require('sat');
I typed this in the global scope. (I know I am polluting the global scope with my shape, circle, rectangle etc. but I am still a junior and this is my best solution so far:)
The problem is that I must use browserify or some other similar framework which provides 'require', and I am not familiar with 'require' yet and how I must organize my code around it.
I installed browserify globaly and I also installed uniq in my project as well as sat (what I want indeed)
Now I believe I have to type a command like this:
browserify constants.js game-errors.js validator.js shape.js circle.js triangle.js rectangle.js rectangle-with-text.js player.js renderer.js game.js initializator.js main.js -o bundle.js
But when I reference bundle.js in my html file and I run the browser I get this errror in the console:
Uncaught ReferenceError: shape is not defined
which points to the code where I try to build circle, which means that my IIFE for the circle cannot see shape.
So what should I do in order to make browserify to build my bundle properly?
I just got into JavaScript and I'm kind of puzzled by its object-oriented behavior.
I was just trying to create a class Point2D with x,y members and extend it with a Point3D class with x,y,z members.
The behavior I'm trying to achieve is something like, let's say it in C#:
class Point2D
{
int x, y;
public Point2D(int x, int y) { this.x = x; this.y = y; }
}
class Point3D : Point2D
{
int z;
public Point3D(int x, int y, int z) : base(x, y) { this.z = z; }
}
I read a lot of stuff but I don't seem to really find what I'm looking for.
Here's what I've come up to so far:
function Point2D(x, y) { this.x = x; this.y = y; }
Point2D.prototype.constructor = Point2D;
function Point3D(x, y, z) { Point2D.prototype.constructor.call(this); this.z = z; }
Point3D.prototype = new A(); // see latter explanation
Point3D.prototype.constructor = B;
var p = new Point3D(10, 20, 30);
Which is obviously wrong.
Now, I know I should do something like Point3D.prototype = new A(x, y) but I don't want to create a prototype with fixed x,y coordinates and variable z.
It must be very simple, but I'm just not getting it, I can't seem to call the superclass constructor or to make it behave properly.
JavaScript's prototypal inheritance provides a couple of different flexible ways to perform the kind of polymorphic constructors you're looking for. In your particular example, you want something like this:
function Point2D(x, y) {
this.x = x;
this.y = y;
}
function Point3D(x, y, z) {
Point2D.call(this, x, y);
this.z = z;
}
Fussing with explicitly setting the constructor on the prototype is not strictly necessary here. (It is really only necessary when you are creating the prototype "all at once" -- e.g., with an object.)
For a detailed discussion of object-oriented JavaScript, I'd recommend Nicholas Zakas' Principles of Object-Oriented Programming in JavaScript (ebook) or the discussion of prototypes and inheritance in his other book, Professional JavaScript for Web Developers.
Here is my little program. When I check the value of rec in the debug mode, the object is Base { x=0, y=0, w=10, more...}. Should it be Rectangle? Also the constructor.prototype is Base. Why not Shape?
function Base() {
}
function Shape(x, y) {
this.x = x;
this.y = y;
}
Shape.prototype = new Base();
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.log("x = " + this.x + " y = " + this.y);
};
function Rectangle(x, y, w, h) {
Shape.call(this, x, y);
this.w = w;
this.h = h;
}
Rectangle.prototype = new Shape();
Rectangle.prototype.area = function() {
return this.w * this.h;
};
var rec = new Rectangle(0, 0, 10, 10);
console.log(instanceOf(rec, Rectangle));
function instanceOf(object, constructor) {
while (object != null) {
if (object == constructor.prototype)
return true;
if ( typeof object == 'xml') {
return constructor.prototype == XML.prototype;
}
object = object.__proto__;
}
return false;
}
Have a look at Why [not] to use the new keyword here?. You might not use it and create a new instance of it, but rather just inherit from Base.prototype.
Also the constructor.prototype is Base. Why not Shape?
I'm not sure which constructor you are referring to here:
The constructor property of all your objects is Base, as all of them inherit this prototype from the Base.prototype object. You did not overwrite it after setting up the inheritance chains. It is not really necessary, but good style: Shape.prototype.constructor = Shape and Rectangle.prototype.constructor = Rectangle - where those prototype objects are the overwritten ones which inherit from Base.
The constructor parameter of your instanceOf function. You pass in Rectangle there, so constructor.prototype is the prototype object of Rectangle, which inherits from Base but is different.
When I check the value of rec in the debug mode, the object is Base { x=0, y=0, w=10, more...}
Usually not. Is Base something special, e.g. a host object? Your rec object is an instance of Base, so it might be displayed differently because of that.
rec is just an object which inherits from Rectangle.prototype which inherits from Shape.prototype which inherits from Base.prototype which inherits from… Assuming Base is the function you defined, from Object.prototype which inherits from null.