Javascript object/function accesibility inside another one - javascript

I was looking for best solution, but I dont really what keyword should I look for. I need a bit of explanation of my problem :) Thats my code:
function fluidEdge(params) {
var fluid = {};
fluid.point = function(config){
fluid.x = config.x;
fluid.y = config.y;
};
fluid.renderShape = function(params){
params = params || {};
var x = params.x || 0;
var y = params.y || 0;
point = new fluid.point({
x: x,
y: y
});
console.log(point.x);
};
return fluid;
}
var test = new fluidEdge({});
test.renderShape({x: 50, y: 100});
Fiddle
My example is much more complicated, so I can't really rebuild code, I've simplified it as much as I could. I want to access fluid.point function inside fluid.renderShape. I have no idea how I could do it, I tried few ways.
Before I wasn't using var fluid = {}; and fluid. everywhere but this. and everything was working well.
If I am making any mistakes, you can point that out too. Thanks in advance.

You seem to have a slight mixup with how constructors and functions work. Your code should probably look somewhat like this:
function FluidEdge(params) {}
FluidEdge.Point = function(config) {
this.x = config.x;
this.y = config.y;
}
FluidEdge.prototype.renderShape = function(params) {
params = params || {};
var x = params.x || 0;
var y = params.y || 0;
var point = new FluidEdge.Point({x: x, y: y});
console.log(point.x);
}
var test = new FluidEdge({});
test.renderShape({x: 50, y: 100});
Note the use of prototype to denote methods on the constructor, and the use of this to refer to the constructed object.
Also note that placing constructors on instance variables is generally a bad idea, unless you know what you're doing and have a very good reason to.
Worth noting that this code becomes much better looking if you take advantage of ES2015 features
class FluideEdge {
renderShape({x = 0, y = 0}) {
var point = new FluidEdge.Point({x, y});
console.log(point.x);
}
}
FluidEdge.Point = class {
constructor({x, y}) {
this.x = x;
this.y = y;
}
}

I just realized that I just changed too many this into fluid in my code. The problem was there:
fluid.point = function(config){
this.x = config.x;
this.y = config.y;
};
It works well after that small change.

Related

Handle nested properties of Object in JS

Hi I'm writing a module in NodeJS in a OOP style.
I have multiples simples objects that contains primitive data and multiple complex objects that contain other objects.
const Simple = function Simple() {
this.x = 0;
this.y = 0;
}
Simple.prototype.getArea = function() {
return this.x * this.y;
}
const Complex = function Complex() {
this.ownProp = 0;
this.nestedProp = new Simple();
this.otherNestedProp = new otherSimple();
}
Complex.prototype.set = function(key, value) {
this[key] = value;
}
Complex.prototype.otherSet = function(value) {
Object.assign(this, value);
}
My problem is that users who will use my API can break things by doing this:
let simple = new Simple();
simple.getArea(); // 0
let complex = new Complex();
complex.nestedProp.getArea(); // 0
complex.set('nestedProp', {x: 5, y: 6});
complex.nestedProp.getArea(); // THROW <----
let complex = new Complex();
complex.nestedProp.getArea(); // 0
complex.set({nestedProp: {x: 5, y: 6});
complex.nestedProp.getArea(); // THROW <----
Is there a lodash function to only assign values of such nested Object.
Or is there a good way to manage this kind of problems?
Note: I could check for instanceof but I have a lot of modules, and I don't want to manage each specific case.
It seems you think passing something like {x: 1, y:2} to Complex.set will magically make x and y end inside of Simple. I think you are confused about how Javascript works, no offense meant.
Here's an implementation that would make things work roughly the way you seem to want.
const Simple = function Simple() {
this.x = 0;
this.y = 0;
}
Simple.prototype.getArea = function() {
return this.x * this.y;
}
Simple.prototype.set = function (x, y) {
this.x = x;
this.y = y;
}
const Complex = function Complex() {
this.nestedProp = new Simple();
}
Complex.prototype.set = function(props) {
this.nestedProp.set(props.x, props.y);
}
let complex = new Complex();
complex.nestedProp.getArea(); // 0
complex.set({x: 5, y: 6});
complex.nestedProp.getArea(); // 30
The properties x and y are passed explicitly from Complex to Simple until they end where they should. You can either pass x and y as separate parameters (see Simple's set) or as properties of an object (see Complex's set).
But if you thought x and y would make it all the way to the end by themselves you need to study basic OOP before writing code; again, no offense meant.

Moving all class variables to "this"

Here's part of my code:
class Light {
constructor(xpos,zpos,ypos,range,diffuser,diffuseg,digguseb,intensity,angle,exponent) {
this.xpos = xpos;
this.ypos = ypos;
this.zpos = zpos;
this.range = range;
this.diffuser = diffuser;
this.diffuseg = diffuseg;
this.diffuseb = diffuseb;
this.intensity = intensity;
this.angle = angle;
this.exponent;
[...]
Is there any way to move all given argument variables to this so I can access them later?
var lt = new Light(0,12,15,...);
alert(lt.zpos); //outputs '12'
I'm looking for a solution to put those 11 this lines to one
This does what you desire. The portion in mapArgsToThis which gets the argument names was taken from here. mapArgsToThis would be a helper function you would use when you want to be lazy.
var mapArgsToThis = function(func, args, thisPointer) {
var argsStr = func.toString().match(/function\s.*?\(([^)]*)\)/)[1];
var argNames = argsStr.split(',').map(function(arg) {
return arg.replace(/\/\*.*\*\//, '').trim();
}).filter(function(arg) {
return arg;
});
var argValues = Array.prototype.slice.call(args);
argNames.forEach(function(argName, index) {
thisPointer[argName] = argValues[index];
});
};
var MyConstructor = function(xpos,zpos,ypos,range,diffuser,diffuseg,digguseb,intensity,angle,exponent) {
mapArgsToThis(MyConstructor, arguments, this);
};
var myInstance = new MyConstructor(1,2,3,4,5,6,7,8,9,0);
console.log(myInstance);
Even though this is a solution, I don't recommend it. Typing out the argument mapping to your this properties is good for your fingers and is easier for others to read and know what's going on. It also doesn't allow for any processing of the argument values prior to assignment onto this.

Getting object fields and calling object functions in JavaScript

I just started fiddling around with JavaScript. Coming from Java and OO PHP things are getting weirder with every step :)
This is my introduction project to javascript in which I've set out to program multiplayer working version of Settlers of Catan. Code below is an attempt to store cube coordinates of N sized hexagonal map tiles in an array.
I've read you declare object in javascript by assigning functions to variables.
var Tile = function (x, y, z) {
this.x = x;
this.y = y;
this.z = z;
};
var Map = function () {
var grid = [];
function generate_map(radius) {
for (width = -radius; width <= radius; width++) {
var r1 = Math.max(-radius, -width - radius);
var r2 = Math.min(radius, -width + radius);
for (r = r1; r <= r2; r++) {
grid.push(new Tile(width, r, -width - r));
}
}
}
};
I've tried instantiating new Map object, calling its only function and outprinting the resulting values stores in grid[] array. But for each loop is not playing nice :( I get the unexpected identifier.
var main = function () {
var basic_map = new Map();
basic_map.generate_map(3);
for each (var tile in basic_map.grid) {
console.log(tile.x, tile.y, tile.z);
}
};
main();
I am fully aware this is one of those face palm errors, but help would nevertheless be appreciated, cheers!
Change this:
function generate_map(radius) {
...to this:
this.generate_map = function(radius) {
Edit: there are actually more issues than I at first realized.... :)
A few other tips:
First, I would recommend changing:
var Tile = function (x, y, z) {
...to simply be:
function Tile(x, y, z) {
(the same goes for Map). Your current solution works fine, but it's not very idiomatic, and until ES6 there was nothing in the spec that would cause var Tile = function to cause the resulting function's 'name' property to be set to "Tile", which is useful when it comes to debugging. I recently wrote another answer that delves a bit more into the differences between, e.g., function Foo() {} and var Foo = function() {}.
Second, you probably want to rename Map to something else. Map is a core part of ES6 now (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map).
Third, even though you can create your generate_map function using this.generate_map, you may want to move it to the Map's prototype. Also, since you need to expose the grid value, you want to store it as a property, rather than a local variable scoped to the NewMapName constructor. E.g.,:
function NewMapName() {
this.grid = [];
}
NewMapName.prototype.generateMap = function(radius) {
// you can access the grid here via `this.grid`
...
};
By moving it to the prototype, that means all instances of NewMapName will share the same function reference, rather than it being created over-and-over-and-over (although maybe you really only create it once? Either way, it's more idiomatic, at a minimum). Note that I took some liberties with the "camelCasing" here (see the last point).
Fourth, your generateMap implementation is leaking some global variables (width and r, since you don't declare them with var). I would change that to this:
NewMapName.prototype.generateMap = function(radius) {
for (var width = -radius; width <= radius; width++) {
var r1 = Math.max(-radius, -width - radius);
var r2 = Math.min(radius, -width + radius);
for (var r = r1; r <= r2; r++) {
grid.push(new Tile(width, r, -width - r));
}
}
};
Fifth, your loop is kind of broken. I would refactor that as follows:
var main = function () {
var basicMap = new NewMapName();
basicMap.generateMap(3);
basicMap.grid.forEach(function(tile) {
console.log(tile.x, tile.y, tile.z);
});
};
main();
Lastly, and probably most minor, is that in JavaScript-land, camelCase is far more dominant that snake_case, so generate_map might be "better" as generateMap.

I'm trying to improve my HTML5 Component/Entity/Systems engine, to get as close as possible to the paradigm. What can be improved?

After different paradigms used to create HTML5 game engines, I'm very curious about the Component/Entity/Systems paradigm ; after a friend which is very skillful, told me about it.
If you don't know about it, it's rather simple:
An empty object called an entity
function GameEntity(){
this.components = {};
this.createComponent = function(name, args) {
this.components[name] = new componentList[name](this, args);
}
}
Contains elements which are modular in their nature and as independant as possible
'position': function(parentEntity){
this.entity = parentEntity;
var x = 50;
var y = 50;
this.setPosition = function(newX, newY) {
x = newX;
y = newY;
}
this.getPosition = function() {
return {"x" : x, "y" : y};
}
this.setX = function(value) {
x = value;
}
this.setY = function(value) {
y = value;
}
this.getX = function() {
return x;
}
this.getY = function() {
return y;
}
},
Which are acted upon by systems, each proper to a component
for (var i =0 ; i<game.ent.entityCounter ; i++){
game.ent.entities[i].components['mouvement'].update();
game.ent.entities[i].components['graphics'].update();
}
I've been trying to follow Unity's logic, so far.
Even though it's not a very precise question, how can I improve this little engine?
http://jsfiddle.net/5etgx/2/
It's very basic, but that's mostly the structure that focuses my attention, rather than the functionnality.
Let me know if you think anything is not done in a good manner.

Javascript Prototype General Enquries and Assign Id by Array Index

I am trying to learn how to work with javascripts prototype, I am only getting into it now. Please Excuse me if I ask ridiculously stupid questions
I just have a few pre-questions:
Is it worth learning? I mean it looks like a structured/clean
approach to me?
Do/should you use this with jQuery this?
is there any major problems or reason not to use it and why isn't it commonly used or am i just slow?
Actual Question:
I have the following code:
var BudgetSection = function BudgetSection(name ) {
this.id = "";
this.name = name;
this.monthlyTotal = 0.00;
this.yearlyTotal = 0.00;
this.subTotal = 0.00;
this.lineItems = [];
};
BudgetSection.prototype.calculateSubTotal = function() {
this.subTotal = ((12 * this.monthlyTotal) + this.yearlyTotal);
};
function BudgetLineItem(name) {
this.id = "";
this.name = name;
this.monthlyAmount = 0.00;
this.yearlyAmount = 0.00;
}
BudgetLineItem.prototype = {
totalAmount : function() {
var result = ((12 * this.monthlyAmount) + this.yearlyAmount);
return result;
}
};
var budgetSections = [];
section = new BudgetSection("test1");
section.lineItems.push(new BudgetLineItem('sub'));
section.lineItems.push(new BudgetLineItem('sub2'));
section.lineItems.push(new BudgetLineItem('sub3'));
budgetSections.push(section);
section = new BudgetSection("test2");
section.lineItems.push(new BudgetLineItem('sub'));
section.lineItems.push(new BudgetLineItem('sub2'));
section.lineItems.push(new BudgetLineItem('sub3'));
budgetSections.push(section);
section = new BudgetSection("test3");
section.lineItems.push(new BudgetLineItem('sub'));
section.lineItems.push(new BudgetLineItem('sub2'));
section.lineItems.push(new BudgetLineItem('sub3'));
budgetSections.push(section);
// first iterate through budgetSections
for ( var t = 0; t < budgetSections.length; t++) {
var sec = budgetSections[t];
console.log(sec);
// iterate through each section's lineItems
for (var q = 0; q< budgetSections[t].lineItems.length ; q++) {
var li = budgetSections[t].lineItems[q];
console.log(li);
}
}
the first BudgetSection "test1" is at index 0 in the budgetSections array. how can i assign the id to "section_".
And then also how can i set the id of BudgetLineItem like so: lineItemRow_<section_index><lineitem_index>
Also finally n the for loop what would be the best way to generate html?
I personally never use the new keyword if I can avoid it and do pure prototype-based programming with Object.create. Here's a simple example. I create a prototype-object called rectangle and then create an object called myRectangle which inherits from rectangle.
var rectangle = {
init: function( x, y, width, height ) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
},
move: function( x, y ) {
this.x += x;
this.y += y;
}
};
var myRectangle = Object.create( rectangle );
myRectangle.init( 0, 0, 2, 4 );
myRectangle.move( 3, 5 );
To explain in more depth what happens here, Object.create makes a new object with a specified prototype. When we access a property on an object (like init or move), it first checks the object itself. If it can't find it there, it moves up to the object's prototype and checks there. If it's not there, it checks the prototype's prototype, and keeps going up the prototype chain until it finds it.
When we call a function on an object (myRectangle.init()), this inside the function refers to that object, even if the function definition is actually on the prototype. This is called delegation - an object can delegate its responsibilities to its prototype.
A more class-like way to do this is:
function Rectangle( x, y, width, height ) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
Rectangle.prototype.move = function( x, y ) {
this.x +=x;
this.y +=y;
};
var myRectangle = new Rectangle( 0, 0, 2, 4 );
myRectangle.move( 3, 5 );
The problem is when we need to do a deeper inheritance hierarchy:
function Parent() {
/* expensive and possibly side-effect inducing initialization */
}
Parent.prototype.parentMethod = function() {};
function Child() {}
Child.prototype = new Parent();
We have to initialize a Parent object when all we really want is to set the Child prototype to an object based on Parent.prototype. Another option is:
Child.prototype = Object.create( Parent.prototype );
But now we've got this confusing, convoluted mess of prototype-based and class-based code. Personally, I like this instead:
var parent = {
parentMethod: function() {}
};
// Using underscore for stylistic reasons
var child = _.extend( Object.create( parent ), {
childMethod: function() {}
});
var instance = Object.create( child );
instance.parentMethod();
instance.childMethod();
No new keyword needed. No fake class system. "Objects inherit from objects. What could be more object-oriented than that?"
So what's the catch? Object.create is slow. If you're creating lots of objects, it's better to use new. You can still use Object.create to set up the prototype chain, but we'll have to wait a bit for browsers to optimize it enough for lots of instantiation.
Have you tried budgetSections[0].id = 'yourID';?

Categories

Resources