Moving all class variables to "this" - javascript

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.

Related

Object variable is undefined even though it's initialised

I have a Node project where I create a Unit and an AddGate:
var Unit = function(value, weight) {
this.value = value;
this.weight = weight;
}
var AddGate = function() {
this.sum_function = function(units) {
sum = 0;
for (unit in units)
sum += unit.value;
return sum;
};
};
AddGate.prototype = {
forward: function(units) {
this.units = units;
this.output_unit = new Unit(this.sum_function(units), 0.0);
return this.output_unit;
}
}
I create some Units, an AddGate, and a ForwardNeuron (guess what I'm making):
var in_1 = new Unit(1.0, 0.0);
...
var in_9 = new Unit(3.0, 0.0);
var add = new AddGate();
var forwardNeuron = function() {
a = add.forward({in_1, in_2, in_3, in_4, in_5, in_6, in_7, in_8, in_9});
};
forwardNeuron();
But for some reason, when in sum_function of AddGate, I can access each unit of units fine, but when I try to access unit.value, it says it's undefined, even though I've clearly initialised it. Am I missing something?
As the comments specify, for (let unit in units) will actually set unit as the key of the units object. You can correct this in a few ways such as using units[unit].value, but it would make more sense to me for the arguments to forward and sum_function to be an array. More or less as simple as:
add.forward([in_1, in_2, in_3, in_4, in_5, in_6, in_7, in_8, in_9]);
The sum would be a reduce operation on the array as in:
return units.reduce((sum, unit) => sum + unit.value, 0);
FYI 4castle's response worked for me - I wrote:
sum += units[unit].value;
That did the trick for me. Thanks again to 4castle and trincot for their speedy responses.
EDIT: The above is even better.

Javascript object/function accesibility inside another one

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.

How can I add namespace to revealing prototype pattern

I have this code,
var MyNamespace = MyNamespace || {};
MyNamespace.Calculator = function (eq) {
//state goes here
this.eqCtl = document.getElementById(eq);
};
MyNamespace.Calculator.prototype = function () {
//private members
var add = function (x, y) {
this.eqCtl.innerHTML = x + y;
},
subtract = function (x, y) {
this.eqCtl.innerHTML = x - y;
};
//public members
return {
add: add,
subtract: subtract
};
} ();
Var calc = new MyNamespace.Calculator('eqCtl');
calc.add(2,2);
Questions
Why am I getting exception after adding "MyNamespace" to it ? It works if I remove it...
It's recommended not to use "new" keyword for creating objects by Douglas Crockford Then how can I overcome this solution.
Fiddle: https://jsfiddle.net/bpo50qjg/
You have a typo in:
Var calc = new MyNamespace.Calculator('eqCtl');
It should be:
var calc = ...

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';?

Javascript object member variable not cloning

I'm inheriting an object from the EASELJS library.
To simplify the problem, I'm reducing the code into the minimal form.
I have a class:
this.TESTProg = this.TESTProg || {};
(function() {
var _jsbutton = function(x, y, text, icon) {
p.init(x, y, text, icon);
};
var p = _jsbutton.prototype = new createjs.Container();
p.x = 0;
p.y = 0;
p.text = null;
p.icon = null;
p.init = function(x, y, text, icon) {
this.x = 0 + x;
this.y = 0 + y;
this.text = "" + text;
this.icon = null;
};
TESTProg._jsbutton = _jsbutton;
})();
Then I use it in another js object:
var buttoncancel = new SJSGame._jsbutton(
profileselConfig.cancelx, //this is defined in another jsfile:
profileselConfig.cancely,
"cancel", "_cancel.png");
console.log( buttoncancel.y ); //this gives 240
var buttoncancel2 = new SJSGame._jsbutton(
profileselConfig.cancelx,
profileselConfig.cancely - 40,
"cancel", "_cancel.png");
console.log( buttoncancel.y ); //this gives 200
console.log( buttoncancel2.y ); //this gives 200
buttoncancel2.y = 100;
console.log( buttoncancel.y ); //this now gives 200 (not changed by the second object)
console.log( buttoncancel2.y ); //this now gives 100
The config file:
var _profileselConfig = function(){
this.cancelx = 0;
this.cancely = 240;
};
profileselConfig = new _profileselConfig();
And what am i doing wrong?
I'm already using 0 + to avoid passing the reference and it's not working. What should I do now? Any suggestions? Thanks.
You should probably be calling this.init rather than p.init in your constructor.
When you call p.init, the this inside of init refers to the prototype. Thus, whenever you create an instance, your p.init call modifies the prototype for all _jsbutton objects.
That's why both buttons have the same x/y values: they both get their position from the same prototype, and the last-run constructor set the prototype values. When you set buttoncancel2.y outside of the constructor, you gave that instance its own y property, so it no longer used the shared prototype value.
If you call this.init in your constructor, then the this in init will refer to your newly-created instance. The instances will no longer use the shared prototype values for x, y, text, and icon.
Side note: "I'm already using 0 + to avoid passing the reference" -- this is not necessary, because primitive types are always copied.

Categories

Resources