Javascript constructor: Accessing outside variable - javascript

I try to access an object which is global; it's a kind of a preset.
var perks = {health: 100, attack: 10};
var player = function(hp) {
this.stats = perks;
//Changing some standard values..
this.stats["health"] = hp;
}
var Peter = new player(200);
var Steven = new player(300);
I hope you get my intention; the problem is, that it won't work correct, and I'm not even sure what it does wrong. If I create more than one player, e.g. Steven, Collin and James, every player has the same perks. In this example Peter and Steven both have 300 health.
If I change the line
this.stats = perks;
to
this.stats = {health: 100, attack: 10};
everything works like intended. Peter and Steven both have their own stats.
How do I access the global var perks?

It happens because in JavaScript object does not copy that way, thats why all of your players using the same perks object.
There is a few ways to solve it:
Create new object with a function (object own constructor).
function createPerks() {
return {
health: 100,
attack: 10
};
}
var player = function(hp) {
this.stats = createPerks();
//Changing some standard values..
this.stats["health"] = hp;
}
var Peter = new player(200);
var Steven = new player(300);
Create new object each time and use constants for default values:
var BASE_HEALTH = 100;
var BASE_ATTACK = 10;
var player = function(hp) {
this.stats = {
health: BASE_HEALTH,
attack: BASE_ATTACK
};
//Changing some standard values..
this.stats["health"] = hp;
}
var Peter = new player(200);
var Steven = new player(300);
Use Object.create (works in IE9+, but shimable for older browsers):
var perks = {health: 100, attack: 10};
var player = function(hp) {
this.stats = Object.create(perks);
//Changing some standard values..
this.stats["health"] = hp;
}
var Peter = new player(200);
var Steven = new player(300);
Keep in mind that Object.create does not clone an object but inherit one object from another.
Object.create shim for old browsers by Douglas Crockford:
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}

The moment you write this.stats = perks; both of them refer to the same object that is {health: 100, attack: 10}. So any changes made to any one of them will always affect the other.
As var Steven = new player(300); is the last value you assigned. All your players will now have {health: 300, attack: 10}

Related

Create an instance with new, with nested objects as arguments

I want to create an instance of the object Player, which as an instance of the object Weapon nested in it.
For example, player1 should start the game with a dagger.
I tried different things but the nested object (weapon) is not in the player instance.
function Weapon(name, damage) {
this.name = name;
this.damage = damage;
}
function Player(name, life) {
this.name = name;
this.life = life;
this.weapon = {
name: name,
damage: damage
};
}
const player1 = new Player("Joueur 1", 100, dagger);
const dagger = new Weapon("Dague", 5);
const sword = new Weapon("Epée", 10);
const axe = new Weapon("Hache", 15);
const flail = new Weapon("Fléau", 20);
What is the right syntax to add this weapon as a nested object?
Also, the weapon may change during the game.
I think you're looking for something like this, you're currently trying to pass a parameter but the constructor isn't expecting it. I've given 2 examples of how you could achieve this.
function Weapon(name, damage) {
this.name = name;
this.damage = damage;
}
function Player(name, life, weapon) {
this.name = name;
this.life = life;
this.weapon = weapon;
}
const dagger = new Weapon("Dague", 5);
const player1 = new Player("Joueur 1", 100, dagger);
const player2 = new Player("Joueur 1", 100, new Weapon("Dague", 5));
console.log(player1);
console.log(player2);

node.js how to make one variable change apply to another one aswell?

Is there some kind of way of having some kind of "shared" variable? What I want to do is this:
var id = 5;
var player = new Player(id);
var array1[0] = player;
var array2[0] = player;
array1[0].id = 8
console.log(array1[0]); //8
console.log(array2[0]); //8
In JavaScript, you do not store an object directly in a variable, but rather a reference to the object.
That means, you can have two variables that point to the same object - you simply copy the reference:
var a = {test: "test"};
var b = a;
console.log(a === b) // true
In this case, if you mutate the object via a and later read it via b, you will see the changes.
With the right implementation of Player, you can make that work for you:
var Player = function(id) {
this.id = id;
}
Player.prototype.setId = function(id) {
this.id = id;
}
Player.prototype.getId = function() {
return this.id;
}
var player = new Player(5);
console.log(player.getId()); // 5
var arrA = [];
var arrB = [];
arrA.push(player);
arrB.push(player);
console.log(arrA[0].getId()); // 5
console.log(arrB[0].getId()); // 5
arrA[0].setId(10);
console.log(arrA[0].getId()); // 10
console.log(arrB[0].getId()); // 10
Check MDN for more info on working with objects.

Retrieving a value held in all instances of an object

I am working on a Person constructor function that takes a name and age as its parameters, and trying to implement a method that retrieves all the 'Person' instances current age value and outputs the average. Here's my code...
var Person = (function() {
//private state
var inst = 1;
function Person(name, age) {
this.name = name;
this.age = age;
Object.defineProperty(this, "age", {
get: function() {
return age;
},
set: function(num) {
age = num;
}
});
Object.defineProperty(this, "_id", {
value: inst++
});
}
//Attempt to return number of instances divided by all current Person weights
Person.prototype.aveAge = function() {
return inst;
};
return Person;
}());
var jim = new Person("jim", 32);
var richard = new Person("richard", 27);
richard.age = 28;
var alfie = new Person("alfie", 42);
Person.aveAge() //Returns TypeError: Person.aveAge is not a function
I have set up a variable that is shared across all instances (inst) that increments each time an another instance is created and assigns a unique id. I cannot figure out how I can get to each 'age' value of all Person instances in existence using the aveAge prototype I have added at the bottom. I am also getting a 'TypeError: Person.aveAge is not a function' when I attempt to call it to even test that variable 'inst' holds the correct number of instances. Does anybody know where I am going wrong?
It feels strange to keep ages on a person when it references people. Notice that hanging things on __proto__ makes them available from the constructor (Person), while hanging things on prototype makes them available from the instance (richard). If Age is updated, it needs to be done via setAge so the PeopleTracker knows to update it's memory. Also, in my example, the average is only calculated when needed rather than each time a person wants to know what is is.
var peopleTracker = {
_count: 0,
_ages: [],
averageAge: 0,
addPerson: function (age) {
var pt = peopleTracker;
pt._count += 1;
pt._ages.push(age);
pt.getAverage();
},
getAverage: function () {
var sum = 0,
pt = peopleTracker;
sum = pt._ages.reduce(function (a, b) {
return a + b;
});
pt.averageAge = Math.round(sum / pt._count);
},
update: function (oldAge, newAge) {
var pt = peopleTracker,
ages = pt._ages,
i = ages.indexOf(oldAge);
ages.splice(i, 1, newAge);
pt.getAverage();
}
};
var Person = function (name, age) {
this.name = name;
this.age = age;
peopleTracker.addPerson(age);
};
Person.__proto__ = { // available from the constructor
Constructor: Person,
setAge: function (age) {
var oldAge = this.age;
this.age = age;
peopleTracker.update(oldAge, age);
},
aveAge: function () {
return peopleTracker.averageAge;
}
};
Person.prototype = Person.__proto__; // now also available from the instance
var jim = new Person("Jim", 32),
richard = new Person("Richard", 27),
alfie = new Person("Alfie", 42);
Person.aveAge(); // 34
richard.aveAge(); // 34
richard.setAge(20);
Person.aveAge(); // 31
richard.aveAge(); // 31

JavaScript prototype structure and objects

I'm new to the prototype structure, and I'm having trouble figuring this one out. Here's my JavaScript code.
var Game = function ()
{
//some variables
};
Game.prototype.block =
{
spawn: function () {
var t1 = new this.inst;
},
inst : {
x: 5,
y: 0,
type: ''
}
};
When I try to create a new object "inst" I get the following error:
TypeError: object is not a function. What am I doing incorrectly?
If you want to create objects that inherit from the inst object, you can do that using Object.create, with var t1 = Object.create(this.inst);.
var Game = function () {
//some variables
};
Game.prototype.block = {
spawn: function () {
var t1 = Object.create(this.inst);
},
inst : {
x: 5,
y: 0,
type: ''
}
};
So then your code would look something like this;
var game = new Game();
game.block.spawn();
And the .spawn() method would have a variable that references an object that inherits from the Game.prototype.block.inst object.
First of all, inst is not defined within the scope of Game. So, this which refers to Game doesn't have any properties called inst. Secondly, inst must be followed by () to indicate a call to the constructor, which you are missing here.
I guest you need a static factory method to create new "inst". is the below code what you need? you call the Game.spawn method to generate a new inst, and you can put this method in setInterval.
function Game() {
//some variables
}
Game.spawn = function() {
function Inst() {
this.x = 5;
this.y = 0;
this.type = '';
}
return new Inst;
}
var inst1 = Game.spawn();
inst1.x = 1; //test inst1
console.log(inst1.x);
var inst2 = Game.spawn();
inst2.x = 2; //test inst2
console.log(inst2.x);
var inst3 = Game.spawn();
inst3.x = 3; //test inst 3
console.log(inst3.x);

Why I can not read the property of an object passed to a function? In JavaScript

I'm getting the next error in function getOlder():
TypeError: Cannot read property 'age' of undefined
What's the problem and how to fix it?
function person(name, age) {
this.name=name;
this.age=age
}
// Returns the older person in a group of persons.
var getOlder = function(people) {
if (people.length === 0) {
return new person();
}
var older = people[0]; // The first one is the older for now.
var value;
for (var _ in people) {
value = people[_];
if (value.age > older.age) {
older = value;
}
}
return older;
};
// Declare some persons.
var paul = new person("Paul", 23);
var jim = new person("Jim", 24);
var sam = new person("Sam", 84);
var rob = new person("Rob", 54);
var karl = new person("Karl", 19);
var older = getOlder(paul, jim);
if (older.name !== "Jim") {
console.log("Fail");
}
Look at the signature of your function:
var getOlder = function(people) {
You did not create your function such that it accepts two person objects. You apparently only accept an array, as you're using people.length and people[0] inside the function. So you also have to pass an array:
var older = getOlder([paul, jim]);
var getOlder = function() {
var people = arguments;
if (people.length === 0) {
return new person();
}
var older = people[0]; // The first one is the older for now.
var value;
for (var _ in people) {
value = people[_];
if (value.age > older.age) {
older = value;
}
}
return older;
};
By Accepting no arguments in the function definition and relying on the variable arguments feature of JS you can get away with calling getOlder(paul, jim).
arguments is a property of every function which is basically an array of variable arguments provided to it while calling .

Categories