passing array to Constructor function and keep it public - javascript

here is my code :
var BoxUtility = function() {
var boxList = Array.prototype.pop.apply(arguments);
};
Object.defineProperties(BoxUtility, {
totalArea: {
value: function(){
var x = 0;
for(var i = 0, len = boxList.length; i <= len - 1; i++){
x = x + boxList[i].area;
};
return x;
}
}
});
I'm trying to achieve this syntax for my Code :
var boxArray = [box01, box02, box03];
box are objects, box01.area => boxes have area property
var newElement = new BoxUtility(boxArray);
alert(newElement.totalArea);
I WANT TO SEE THE RESULT AS I EXPECT but I think boxList is in another scope
How can I reach it in defineProperties

You have to assign the value to a property of this in your constructor.
var BoxUtility = function() {
// this.boxList
this.boxList = Array.prototype.pop.apply(arguments);
};
// instance methods go on the prototype of the constructor
Object.defineProperties(BoxUtility.prototype, {
totalArea: {
// use get, instead of value, to execute this function when
// we access the property.
get: function(){
var x = 0;
// this.boxList
for(var i = 0, len = this.boxList.length; i <= len - 1; i++){
x = x + this.boxList[i].area;
};
return x;
}
}
});
var boxUtil = new BoxUtility([{area:123}, {area:456}]);
console.log(boxUtil.totalArea); // 579
Variable scope is always at the function level. So you declared a local variable that is only usable inside your constructor function. But every time you call the constructor function you get a new object (this). You add properties to this in order to have those properties accessible in your instance methods on the prototype.

this works
var BoxUtility = function() {
this.boxList = Array.prototype.pop.apply(arguments);
Object.defineProperties(this, {
totalArea: {
get: function(){
var x = 0;
for(var i = 0, len = this.boxList.length; i <= len - 1; i++){
x = x + this.boxList[i].area;
};
return x;
}
}
});};
var y = new BoxUtility(boxArray);
alert(y.totalArea)

This is simple way to pass array as argument in constructer and declare function prototype for public access.
function BoxUtility(boxArray) {
this.boxArray = boxArray;
this.len = boxArray.length;
}
Color.prototype.getAverage = function () {
var sum = 0;
for(let i = 0;i<this.len;i++){
sum+=this.boxArray[i];
}
return parseInt(sum);
};
var red = new BoxUtility(boxArray);
alert(red.getAverage());

Related

Getting javascript undefined TypeError

Please help....Tried executing the below mentioned function but web console always shows
TypeError: xml.location.forecast[j] is undefined
I was able to print the values in alert but the code is not giving output to the browser because of this error. Tried initializing j in different locations and used different increment methods.How can i get pass this TypeError
Meteogram.prototype.parseYrData = function () {
var meteogram = this,xml = this.xml,pointStart;
if (!xml) {
return this.error();
}
var j;
$.each(xml.location.forecast, function (i,forecast) {
j= Number(i)+1;
var oldto = xml.location.forecast[j]["#attributes"].iso8601;
var mettemp=parseInt(xml.location.forecast[i]["#attributes"].temperature, 10);
var from = xml.location.forecast[i]["#attributes"].iso8601;
var to = xml.location.forecast[j]["#attributes"].iso8601;
from = from.replace(/-/g, '/').replace('T', ' ');
from = Date.parse(from);
to = to.replace(/-/g, '/').replace('T', ' ');
to = Date.parse(to);
if (to > pointStart + 4 * 24 * 36e5) {
return;
}
if (i === 0) {
meteogram.resolution = to - from;
}
meteogram.temperatures.push({
x: from,
y: mettemp,
to: to,
index: i
});
if (i === 0) {
pointStart = (from + to) / 2;
}
});
this.smoothLine(this.temperatures);
this.createChart();
};
You are trying to access the element after the last one. You can check if there is the element pointed by j before proceeding:
Meteogram.prototype.parseYrData = function () {
var meteogram = this,
xml = this.xml,
pointStart;
if (!xml) {
return this.error();
}
var i = 0;
var j;
$.each(xml.location.forecast, function (i, forecast) {
j = Number(i) + 1;
if (!xml.location.forecast[j]) return;
var from = xml.location.forecast[i]["#attributes"].iso8601;
var to = xml.location.forecast[j]["#attributes"].iso8601;
});
};

JavaScript updating last index class data

I have following issue.
I have array of objects, and when I want to get one of the items and update data, it updates last data.
for example:
var arr = [];
for (var i = 0; i < 8; i++){
var c = new MyClass1(i);
arr.push (c)
}
and the MyClass1
(function () {
var score = 0;
function MyClass1(id){
this.id = id;
this.x = 100;
//some code. not important
}
var p = MyClass1.prototype;
p.updateScore = function (s){
score = s;
}
window.MyClass1 = MyClass1;
}());
and function which returns one of these classes
var getMyClassesById = function(/* int */ id){
var size = arr.length;
for (var i = 0; i<size; i++){
if (id == arr[i].id){
return arr [i];
}
}
}
Finally I'm calling function and want to update Score
getMyClassesById(1).updateScore (122);
it's updates last index item Score, and calls last item "updateScore" function... why?
but when i'm changing some other property its changes correctly for example "x". I can't understand is here something not right with prototypes?
Your variable score is not defined as a member of MyClass - it is only defined in the scope of your closure. Your code will work, but there will only be 1 "score" for all instances of MyClass.
If score is supposed to be part of MyClass then move it
function MyClass1(id){
this.id = id;
this.x = 100;
this.score = 0
//some code. not important
}
And update the method:
var p = MyClass1.prototype;
p.updateScore = function (s){
this.score = s;
}
(function () {
function MyClass1(id){
this.id = id;
this.x = 100;
this.score = 0;
//some code. not important
}
var p = MyClass1.prototype;
p.updateScore = function (s){
this.score = s;
}
window.MyClass1 = MyClass1;
}());
var arr = [];
for (var i = 0; i < 8; i++){
var c = new MyClass1(i);
arr.push (c)
}
var getMyClassesById = function(/* int */ id){
var size = arr.length;
for (var i = 0; i<size; i++){
if (id == arr[i].id){
return arr [i];
}
}
}
getMyClassesById(1).updateScore (122);
console.log(arr);

Javascript undefined error: `this` is null

Somehow when executing this code, I get the alert from line 29 .mouseOnSeat.
But I don't know why this.seats is null, while in the draw function it is not.
I call the init function from html5.
//init called by html5
function init() {
var cinema = new Cinema(8, 10);
cinema.draw("simpleCanvas");
var canvas = document.getElementById("simpleCanvas");
//add event listener and call mouseOnSeat
canvas.addEventListener('mousedown', cinema.mouseOnSeat, false);
}
var Cinema = (function () {
function Cinema(rows, seatsPerRow) {
this.seats = [];
this.rows = rows;
this.seatsPerRow = seatsPerRow;
var seatSize = 20;
var seatSpacing = 3;
var rowSpacing = 5;
var i;
var j;
for (i = 0; i < rows; i++) {
for (j = 0; j < seatsPerRow; j++) {
this.seats[(i * seatsPerRow) + j] = new Seat(i, j, new Rect(j * (seatSize + seatSpacing), i * (seatSize + rowSpacing), seatSize, seatSize));
}
}
}
Cinema.prototype.mouseOnSeat = function (event) {
//somehow this is null
if (this.seats == null) {
alert("seats was null");
return;
}
for (var i = 0; i < this.seats.length; i++) {
var s = this.seats[i];
if (s.mouseOnSeat(event)) {
alert("Mouse on a seat");
}
}
alert("Mouse not on any seat");
};
Cinema.prototype.draw = function (canvasId) {
var canvas = document.getElementById(canvasId);
var context = canvas.getContext('2d');
var i;
//somehow this isn't
for (i = 0; i < this.seats.length; i++) {
var s = this.seats[i];
context.beginPath();
var rect = context.rect(s.rect.x, s.rect.y, s.rect.width, s.rect.height);
context.fillStyle = 'green';
context.fill();
}
};
return Cinema;
})();
I tried a lot, like creating a self variable (var self = this ) and then calling from self.mouseOnSeat, it was suggested on another post, but I didn't figure it out.
The problem is that when you call addEventListener, the variable this does not carry along to the function call. This means that this is not your object.
You workaround is sound, you can use it. Or alteratively change your addEventListener call to:
canvas.addEventListener('mousedown', cinema.mouseOnSeat.bind(this), false);
Do note that you might need to use a polyfill to get Function.prototype.bind for older browsers, although it is very well supported currently. See caniuse.
I found a workaround :
canvas.addEventListener('mousedown', function (event) {
cinema.mouseOnSeat(event);
}, false);
But I have no clue why

javascript push not working in array inside object

As you can see in the code, i tried to dynamically create arrays inside an object, it doesn't have a problem when debugging, but when i tried to use push method in the array it throws an error. By the way this is in google app script.
Push function not found in the object [object Object]: TypeError. (line 32, file
var LoopQuestGuildAchievementReward = function (spread_sheet, master_name, is_update) {
initializeBase(this, MasterBase, [spread_sheet, master_name, is_update]);
this.guild_achievement_columns = new Object();
this.create_guild_achievement_columns = function () {
var guild_achievement_coloumn_names = ['ids', 'event_ids', 'range_starts', 'range_ends', 'incentive_ids'];
for (var i = 0; i < guild_achievement_coloumn_names.length; i++) {
if (!this.guild_achievement_columns[guild_achievement_coloumn_names[i]]) {
this.guild_achievement_columns[guild_achievement_coloumn_names[i]] = {};
};
};
};
};
LoopQuestGuildAchievementReward.prototype.setMaster = function(option) {
if (!option || !option.summary_values || !option.batch_reward_values) {
throw "Argument exception.";
};
var event_id = option.summary_values[8][0];
var incentive_values = option.batch_reward_values;
var incentive_master_id = Commons.getIncentiveId(1, event_id, 5);
var data_row_number = searchRowNumberWrittenLavelInColumn_(incentive_values, 1, "reach num") + 1;
var guild_achievement_last_id = Commons.getLatestId("loop_quest_guild_achievement_reward", "ja") + 1;
this.create_guild_achievement_columns();
while (data_row_number < incentive_values.length && incentive_values[data_row_number][1] != "") {
var reach_number = incentive_values[data_row_number][1];
Logger.log(this.guild_achievement_columns.ids);
this.guild_achievement_columns.ids.push(guild_achievement_last_id); // <- this where the error message points (line no. 32)
// this.guild_achievement_columns.event_ids.push(event_id);
// this.guild_achievement_columns.range_starts.push(reach_number);
// this.guild_achievement_columns.range_ends.push(reach_number - 1);
// this.guild_achievement_columns.incentive_ids.push(incentive_master_id);
guild_achievement_last_id++;
incentive_master_id++;
data_row_number++;
}
Logger.log(this.guild_achievement_columns);
};
After asking my superior he mention that curly braces refer to objects and brackets refer to array.
Object: this.guild_achievement_columns[guild_achievement_coloumn_names[i]] = {};
Array: this.guild_achievement_columns[guild_achievement_coloumn_names[i]] = [];

Prototype "this" not working (JS)

Trying to do an .onload method with an Image() object and apparently it isn't inheriting the "this" in its function. Any help?
function UI() {
this.canvas_obj = document.getElementById('game');
this.canvas = this.canvas_obj.getContext('2d');
this.imgcache = {};
this.imglist = [
'rooms/main-square.png'
];
for (var i = 0; i < this.imglist.length ; i++) {
var img = new Image();
img.src = this.imglist[i];
this.imgcache[this.imglist[i]] = img;
}
}
// snip //
/*
* drawImg
* Draws an image on the canvas at the specified x, y (if the image isn't in the pre-cache, it creates it as well)
* #param str image path
* #param array x,y
* #param array width, height
*/
UI.prototype.drawImg = function(path, coords, size) {
var found = false;
if (size == undefined) {
var w = 0;
var h = 0;
} else {
var w = size[0];
var h = size[1];
}
for (var i = 0; i < this.imgcache.length ; i++) {
if (path == this.imgcache[i].src) {
found = true;
}
}
if (!found) {
var img = new Image();
img.src = path;
this.imgcache[path] = img;
}
if (w == 0 && h == 0) {
this.imgcache[path].onload = function() {
this.canvas.drawImage(this.imgcache[path], coords[0], coords[1], this.imgcache[path].width, this.imgcache[path].height);
};
} else {
this.imgcache[path].onload = function() {
this.canvas.drawImage(this.imgcache[path], coords[0], coords[1], w, h);
};
}
}
As for every variable, in JavaScript, the scope of this is relative to function you are in. So, when in
this.imgcache[path].onload = function() {
// ...
};
this will be bound to the object imgcache[path]. A common approach is to keep the value of this in another variable (by convention, it's often that) in order to access it inside nested functions: it's called a closure.
var that = this;
this.imgcache[path].onload = function() {
// that will reference the "outer this"
};
Now, this is due to how JavaScript binds the this value on function invocation. It is possible to bind this to another value by using call or apply.
The value of a function's this keyword is set by how the function is called. When the drawImg method is called on an instance of UI, e.g.:
var fooUI = new UI(...);
fooUI.drawImg(...);
then in the method fooUI.drawImg, the this keyword will reference fooUI.
Within the method there is an assignment to an onload property:
this.imgcache[path].onload = function() {
this.canvas.drawImage(this.imgcache[path], coords[0], coords[1],
this.imgcache[path].width, this.imgcache[path].height);
};
The first this will reference fooUI. However, the anonymous function assigned to the onload property is called as a method of the object referenced by this.imagecache[path], so that is the object referenced by the function's this when called.
You can change that by using a closure to a local variable with a sensible name (that is not a good choice in my opinion) like:
var uiObj = this;
this.imgcache[path].onload = function() {
uiObj.canvas.drawImage(uiObj.imgcache[path], coords[0], coords[1],
uiObj.imgcache[path].width, uiObj.imgcache[path].height);
};

Categories

Resources