JS object inheritance with attributes - javascript

Im trying to get a very simple inheritance pattern for my Project going, extending from a base class into a specialized class. However, my specialized class's attributes are being overwritten by the parent's attributes.
Why is that and how can i fix it ?
thanks,
function Ship(className, x, y){
this.className = className;
this.x = x;
this.y = y;
this.speed = 0;
}
function Corvette(className, x, y){
this.className = className;
this.x = x;
this.y = y;
this.speed = 100;
Ship.call(this, className, x, y)
}
Corvette.prototype = Object.create(Ship.prototype);
var ship = new Ship("Biggie", 50, 50);
var corvette = new Corvette("Smallish", 50, 50);
console.log(Corvette.className) // "Smallish" - correct via parameter.
console.log(Corvette.speed) // should be 100, is 0 - not correct, "static" from parent attribute
console.log(Corvette.constructor.name) // Ship

Why you have the same properties in the child object which are already in the parent's?
I suggest you to do
function Ship(className, x, y, speed = 0) {
this.className = className;
this.x = x;
this.y = y;
this.speed = speed;
}
function Corvette(className, x, y, speed = 100) {
Ship.call(this, className, x, y, speed);
}
Corvette.prototype = Object.create(Ship.prototype);
Corvette.prototype.constructor = Corvette;
var ship = new Ship("Biggie", 50, 50);
var corvette = new Corvette("Smallish", 50, 50);
console.log(corvette.className) // "Smallish" - correct via parameter.
console.log(corvette.speed) // should be 100, is 0 - not correct, "static" from parent attribute
console.log(corvette.constructor.name) // Ship
and if your browser supports some features of ES6 use this feature ES6 classes.
class Ship { // And also Ship is an abstractionm so you can use `abstract` keyword with it
constructor(className, x, y, speed = 0) {
this.className = className;
this.x = x;
this.y = y;
this.speed = speed;
}
}
class Corvette extends Ship {
constructor(className, x, y, speed = 100) {
super(className, x, y, speed);
}
}
var ship = new Ship("Biggie", 50, 50);
var corvette = new Corvette("Smallish", 50, 50);
console.log(corvette.className) // "Smallish" - correct via parameter.
console.log(corvette.speed) // should be 100, is 0 - not correct, "static" from parent attribute
console.log(corvette.constructor.name) // Ship

You only need to move Ship.call(this, className, x, y) at the start of Corvette function.
Also, next time, before posting code, check it is correct, you wrote console.log(Corvette) instead of console.log(corvette)
Another thing: you do not need to repeat params you do not want to overwrite
function Ship(className, x, y){
this.className = className;
this.x = x;
this.y = y;
this.speed = 0;
}
function Corvette(className, x, y){
Ship.call(this, className, x, y)
this.speed = 100;
}
Corvette.prototype = Object.create(Ship.prototype);
var ship = new Ship("Biggie", 50, 50);
var corvette = new Corvette("Smallish", 50, 50);
console.log(corvette.className)
console.log(corvette.speed)
console.log(corvette.constructor.name)

You should invoke the parentclass contructor first and then override the properties, this way the properties set by Corvette will not be changed by the parent class i.e.:
function Corvette(className, x, y){
Ship.call(this, className, x, y)
this.speed = 100;
}

Related

How do i define this method in vue.js?

I am attempting to create a JavaScript Text Animation but i am getting particleArray is undefined
i am not sure how to resolve the issue i have tried moving the code from the mounted method since it would load before being defined but same results.
export default {
data : function (){
return {
particleArray: null,
x:null,
y:null,
radius: 150,
vuedata: null,
}
},
class Particle{
constructor(x, y){
this.x = x + 100;
this.y = y;
this.size = 3;
this.baseX = this.x;
this.baseY = this.y;
this.density = (Math.random() *30) + 1;
}
draw(){
ctx.fillStyle = '#fff';
ctx.beginPath();
ctx.ard(this.x, this.y, this.size,0,Math.PI * 2);
ctx.closePath();
ctx.fill();
}
}
function init(){
this.particleArray = [];
particleArray.push(new Particle(50,50));
}
The answer is this.particleArray.push(new Particle(50,50));
this.particleArray = []; assigns the data property particleArray the value [].
particleArray.push(new Particle(50,50)); attempts a method on a local variable that does not exist.

Why will my animation not work if I declare my variable locally?

I'm quite new to JS so please excuse my ignorance but I can't figure out why my animation if statement doesn't work if I declare my speed variable locally in the move() function.
If I don't declare the speed variable globally, the girl gets to the windowWidth and gets stuck moving a couple of pixels back and forth. Basically staying there rather than moving the other way.
let speed = 2;
class Girl {
constructor(x, y) {
this.x = x,
this.y = y
}
body() {
noStroke();
fill(239, 101, 233);
rect(this.x, this.y, 20, 40);
fill(249, 192, 155);
triangle(this.x, this.y, this.x + 20, this.y, this.x + 10, this.y + 15);
}
move() {
if (this.x > windowWidth + 50 || this.x < -50) {
speed = speed * -1;
}
this.x = this.x + speed;
}
}
I should mention I'm using the p5 library in case I'm using any funky functions. It works but I'm sure I could tidy this up a little bit. Any advice would be more than welcome.
Thanks in advance!
You should not declare it as a local variable inside the move method (as that would make it get re-initialised to 2 on every call), but you should make it a property of the instance that gets initialised in the constructor and modified in the move method (just like x and y).
class Girl {
constructor(x, y) {
this.x = x;
this.y = y;
this.speed = 2;
}
body() {
noStroke();
fill(239, 101, 233);
rect(this.x, this.y, 20, 40);
fill(249, 192, 155);
triangle(this.x, this.y, this.x + 20, this.y, this.x + 10, this.y + 15);
}
move() {
if (this.x > windowWidth + 50 || this.x < -50) {
this.speed = this.speed * -1;
}
this.x = this.x + this.speed;
}
}
Because the value of speed is shared across multiple calls to move. If you declare it inside move then it gets created for each call to move, thus any previous value of speed will be ignored.
If you don't want speed to be a global variable, then you can make it a property of the class Girl:
class Girl {
constructor(x, y) {
this.x = x;
this.y = y;
this.speed = 2; // make 'speed' a property of the class
}
/* ... */
// use 'this.speed' inside 'move' instead of just 'speed'
move() {
if (this.x > windowWidth + 50 || this.x < -50) {
this.speed = this.speed * -1;
}
this.x = this.x + this.speed;
}
}
Problem here is this.x > windowWidth + 50 || this.x < -50. Try to log this inside move() function and you will see that it is referring to move().x instead of Girl.x. So this.x is undefined and undefined > 10 + 50 is always false.
P.s. I dont know p5 so this is vanilla.
So to fix this you need to declare another variable to get Girl scope.
var Girl = function(){
var self = this;
//code goes here
function move(){
self.x = setValue;
console.log(this.x) //undefined
}
}

How to add object variable to an array using "new"?

I've got this object variable:
var Background = {
x: 0,
y: 0,
speed: 4,
initialize: function (x, y){
this.x = x;
this.y = y;
move: function(){
this.x -= this.speed;
}
};
And I'd like to create new object variable and add it to an array:
background_container = []
background_container.push(new Background())
But it throws an error:
"Uncaught TypeError: Background is not a constructor"
Although it works with normal:
function name() {}
var test_var = new name()
So my guess is that "new" works only for functions. But how can I do it with variable objects like the one before? (I want to have multiple of them in one array and not just multiple references to one object)
With ES5 and below you can create a function which acts as a constructor. Use this inside to bind properties to the current object which is returned from the new operator. Also you can leave the initalize function (if you intend to use this only one time) and pass parameters into the function or constructor directly.
function Background(x, y) {
this.x = x || 0;
this.y = y || 0;
this.speed = 4;
this.move = function() {
this.x -= this.speed;
}
};
var backgrounds = [];
backgrounds.push(new Background(1, 3));
console.log(backgrounds[0].x);
console.log(backgrounds[0].y);
With ES6 and higher you can use Ecmascript's new syntax for creating classes.
class Background {
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
this.speed = 4;
}
move() {
this.x -= this.speed;
}
};
const backgrounds = [];
backgrounds.push(new Background(1,3));
console.log(backgrounds[0].x);
console.log(backgrounds[0].y);

javascript base object to create 2 other objects with different methods

I've been playing around with javascript for years, but I'm trying to get serious now. Studying, and into Objects.
I want to create a base object, and use it to create 2 other objects that are slightly different.
I thought this would work :
function movingObject(x, y, z){
this.x = x;
this.y = y;
this.z = z;
}
var positiveMover = new movingObject(x, y, z);
positiveMover.prototype.move = function(a, b){
yadda yadda
}
var negativeMover = new movingObject(x, y, z);
negativeMover.prototype.move = function(b, a){
adday adday
}
var pic = postiveMover(1, 2, 3);
pic.move(20, 10);
I get a undefined error on the move.....pretty sure I've got the wrong idea. Any advice would be appreciated - links to information, or the right keywords to google
I think it is more like two classes, that you want to build :
function movingObject(x, y, z){
this.x = x; this.y = y; this.z = z;
}
// positive mover : child class of movingObject
function positiveMover (x, y, z) {
// use parent class's constructor.
movingObject.apply(this,arguments);
};
// inherit parent's class.
positiveMover.prototype = Object.create(movingObject.prototype);
positiveMover.prototype.move = function(a, b){ yadda yadda }
However, if you seek a per-instance choice of a method, you could do :
function movingObject(x, y, z, movingMethod){
this.x = x; this.y = y; this.z = z;
this.move = movingMethod;
}
Or just set the move property of a moving object, thus overriding the default prototype :
function movingObject(x, y, z){
this.x = x; this.y = y; this.z = z;
}
movingObject.prototype.move= function(a,b) { /*some default code*/}
var oneMover = new movingObject(0,0,0);
oneMover.move = function(a,b) { /* some specific code */ };

Why is object property changed for all instances?

I wanted to encapsulate the position of a sprite within another object. So that instead of using tile.x and tile.y I would access via tile.position.x and tile.position.y.
Yet once I set the value of tile.position within the init-method all the instances of the tile-object change to the same value. Why is that?
As when I set tile.x everything works as expected, meaning each object gets the right value.
This is how I create the multiple instances:
In a for loop I am creating multiple instances of said object:
for (var y = 0; y < 10; ++y) {
for (var x = 0; x < 10; ++x) {
var tile = Object.create(tileProperty);
tile.init(x, y);
...
}
}
And this is the cloned object:
var tileProperty = {
// this works
x: null,
y: null,
// this will get changed for ALL instances
position: {
x: null,
y: null
},
init: function(x, y) {
this.name = x.toString() + y.toString();
this.x = x;
this.y = y;
this.position.x = x;
this.position.y = y;
this.canvas = document.createElement('canvas');
var that = this;
$(this.canvas).bind('click', function() {
console.log(that.position, that.x, that.y);
});
document.body.appendChild(this.canvas);
}
}
Use this:
var tileProperty = {
position: { // we will inherit from this
x: null,
y: null,
init: function(x, y) {
this.x = x;
this.y = y;
}
},
init: function(x, y) {
this.name = x.toString() + y.toString();
// create an own Position object for each instance
this.position = Object.create(this.position);
// and initialize it
this.position.init(x, y); // you might inline this invocation of course
…
},
…
}
You're having a reference to the same position object in all your objects.
What you should do is using the standard prototype solution :
function tileProperty() {
this.position = {
x: null,
y: null
};
}
tileProperty.prototype.init = function(x, y) {
this.name = x.toString() + y.toString();
this.x = x;
this.y = y;
this.position.x = x;
this.position.y = y;
this.canvas = document.createElement('canvas');
var that = this;
$(this.canvas).bind('click', function() {
console.log(that.position, that.x, that.y);
});
document.body.appendChild(this.canvas);
}
and then build your instance using
var tp = new tileProperty();

Categories

Resources