defining the variables of javascript inside the class scope - javascript

guys i know it is dummy question but i tried alot and never reached .. i want to define the variables of Javascript file inside the scope of the class not to be overridden by any outside source .. here is my code
var pageSize = 5;
var startIndex = 0;
var endIndex = startIndex + pageSize;
var page = 1;
var textField;
var check = 0;
// i want all of the above variables to be defined inside the scope of the class not outside
function bindContext(fn, context) {
return function() {
fn.apply(context, arguments);
}
}
function GridLibraryDep(data) {
this.data = data;
this.columns = $.map(this.data[0], function(item, key) {
return key;
});
document.getElementById("from").innerHTML = 1;
document.getElementById("to").innerHTML = pageSize;
document.getElementById("total").innerHTML = data.length;
$("#first").click(bindContext(this.first, this));
$("#last").click(bindContext(this.last, this));
}
GridLibraryDep.prototype = {
first : function() {
var size = this.data.length;
page = 1;
// document.getElementById("lbl").innerHTML = page;
endIndex = page * pageSize;
startIndex = endIndex - pageSize;
this.deleteTable();
document.getElementById("from").innerHTML = 1;
document.getElementById("to").innerHTML = endIndex;
document.getElementById("total").innerHTML = size;
this.display();
},
last : function() {
var size = this.data.length;
endIndex = size;
startIndex = Math.floor(size / pageSize) * pageSize;
page = Math.ceil(size / pageSize);
this.deleteTable();
// document.getElementById("lbl").innerHTML = page;
document.getElementById("from").innerHTML = startIndex + 1;
document.getElementById("to").innerHTML = endIndex;
document.getElementById("total").innerHTML = size;
this.display();
}};

This is a common way to create a prototype Class - https://jsfiddle.net/aaronfranco/fysbbdp7/10/
var MyClass = MyClass || {};
(function () {
"use strict";
//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
MyClass = function () {
this.created = true;
};
//============================================================
// Member Functions & Variables
//------------------------------------------------------------
MyClass.prototype = {
pageSize:5,
startIndex:0,
endIndex:0,
page:1,
textField:null,
check:0,
init: function(){
this.endIndex = this.startIndex + this.pageSize;
},
first : function() {
// function here
console.log(this.endIndex);
},
last : function() {
// function here
//alert(this.pageIndex);
console.log(this.pageSize)
},
iterater: function(int) {
console.log(this.pageSize);
this.pageSize += int;
}
}
})();
Here is the example usage available in the JSFiddle link above:
var newClass = new MyClass();
newClass.init();
newClass.first();
for(var i=0; i<10; i++){
newClass.iterater(i);
newClass.last();
}
Using this "namespaced" technique, you can instantiate this class using
var newClass = new MyClass();
newClass.init();
You could then create protected variables in the class by making them private. There is a good article about some potential ways to create protected variables here.
http://philipwalton.com/articles/implementing-private-and-protected-members-in-javascript/

Related

How can I use attributes directly in methods of Javascript prototype?

I am used to coding with objects in different languages such as Java, Python, …
I have never used JavaScript objects before and I am stuck with a problem: I don't know how to use attributes in methods.
I have done the following but perhaps it's not the correct way:
function test() {
this.un = 1;
this.deux = 2;
this.sum = 1;
add = function() {
this.sum = this.un + this.deux;
}
}
var test = new test();
console.log(test.sum); // res : 1
test.add;
console.log(test.sum); // res : 1 and not 3 as like i want
You have to call add as the method and declare it with this.add, like in the code snipet I posted:
function test() {
this.un = 1;
this.deux = 2;
this.sum = 1;
this.add = function() {
this.sum = this.un + this.deux;
}
}
var obj = new test();
console.log(obj.sum); // res : 1
obj.add();
console.log(obj.sum); // res : 3
function test() {
this.un = 1;
this.deux = 2;
this.sum = 1;
this.add = function() {
this.sum = this.un + this.deux;
}
}
var test = new test();
console.log(test.sum); // res : 1
test.add();
console.log(test.sum); // res : 1 and not 3 as like i want

How to instantiate a class multiple times based on a user input?

I'm trying to create a board game and would like to instantiate the class Human based on a number of times provided by the user. Obviously I'm trying to assign a different ID per object and the following loop doesn't work in order to instantiate the number of players:
var question = prompt('how many players');
var numOfPlayers = parseInt(question);
class Human {
constructor (id) {
this.id = id;
this.health = 100;
this.hammer = false
this.knife = false;
this.sword = false;
this.baseballbat = false;
this.damage = 0;
this.location = {
x: Math.floor(Math.random() * 8),
y: Math.floor(Math.random() * 8)
}
}
moveTo(x, y){
this.location.x += x;
this.location.y += y;
}
}
var i;
for (i = 0; i < numOfPlayers; i++) {
const player = new Human(id = i);
}
Firstly, I hope I have understood what you are trying to achieve here. The scope of the "const player" is limited within the loop. If you want to be able to access it outside the loop you need to declare a list/array likewise.
Code may go like this for the same:
var players = [];
for(let i = 0; i < numOfPlayers; i++) {
players.push(new Human(i));
}
Note: If you don't want to use variable 'i' outside the loop you can declare it inside 'for' using 'let' keyword as can be seen in the code above.
class Human {
constructor (id){
this.id = id;
this.health = 100;
this.hammer = false
this.knife = false;
this.sword = false;
this.baseballbat = false;
this.damage = 0;
this.location = {
x:Math.floor(Math.random()*8),
y:Math.floor(Math.random()*8)
}
console.log(`Human created with id of ${id}`); //Remove this just to show you that your class is being instantiated for each 'player'
}
moveTo(x,y){
this.location.x += x;
this.location.y += y;
}
}
let numOfPlayers = prompt('How many players?');
const _init = () => {
if(parseInt(numOfPlayers) > 0) {
for (let i = 0; i < numOfPlayers; i++) {
new Human(i)
}
}
}
_init();

this.property is undefined: Cannot read property 'classList' of undefined

I'm making something to visualize photographs.
The goal is to select the picture you want in the "list" to make it appear on the main HTML element. But to help you find where you are in the list there's a class putting borders on the element you selected.
The issue :
The function executing with the event this.block.onclick = function () begins well, the .selected is removed from the initial selected element, but when comes this.block.classList.add('selected'); I get this error:
media_visu.js:26 Uncaught TypeError: Cannot read property 'classList' of undefined
I tried to put the function outside, tried className, setAttribute, but nothing changed: my this.block seems to be undefined.
mediavisu.js :
var mediaVisu = function () {
'use strict';
window.console.log('mediaVisu loaded');
var i,
visu = document.querySelector("#img"),
Album = [];
function Photo(nb, folder) {
this.block = document.querySelector("#list_img_" + nb);
this.place = 'url(../src/' + folder + '/' + nb + '.jpg)';
this.block.onclick = function () {
for (i = 0; i < Album.length; i += 1) {
window.console.log(Album[i].block);
if (Album[i].block.classList.contains('selected')) {
Album[i].block.classList.remove('selected');
}
}
visu.style.background = this.place;
window.console.log(visu.style.background);
window.console.log(this.place);
this.block.classList.add('selected');
};
Album[Album.length] = this;
}
var test_a = new Photo(1, "test"),
test_b = new Photo(2, "test"),
test_c = new Photo(3, "test"),
test_d = new Photo(4, "test"),
test_e = new Photo(5, "test");
window.console.log(Album);
for (i = 0; i < Album.length; i += 1) {
window.console.log(Album[i]);
}
};
in the onclick function, this will be the element that was clicked
so you can simply use
this.classList.add('selected');
you may need to rethink using this.place as this wont be the this you think it is .. a common solution is as follows
function Photo(nb, folder) {
this.block = document.querySelector("#list_img_" + nb);
this.place = 'url(../src/' + folder + '/' + nb + '.jpg)';
var self = this;
this.block.onclick = function () {
for (i = 0; i < Album.length; i += 1) {
window.console.log(Album[i].block);
if (Album[i].block.classList.contains('selected')) {
Album[i].block.classList.remove('selected');
}
}
visu.style.background = self.place;
window.console.log(visu.style.background);
window.console.log(self.place);
this.classList.add('selected');
};
Album[Album.length] = this;
}
alternatively, using bind
function Photo(nb, folder) {
this.block = document.querySelector("#list_img_" + nb);
this.place = 'url(../src/' + folder + '/' + nb + '.jpg)';
this.block.onclick = function () {
for (i = 0; i < Album.length; i += 1) {
window.console.log(Album[i].block);
if (Album[i].block.classList.contains('selected')) {
Album[i].block.classList.remove('selected');
}
}
visu.style.background = this.place;
window.console.log(visu.style.background);
window.console.log(this.place);
this.block.classList.add('selected');
}.bind(this);
Album[Album.length] = this;
}
note: now you go back to this.block.classList.add('selected') as this is now the this you were expecting before
You can access to it with 'this' (as mentionned in the previous answer) or with the event target :
this.block.onclick = function (e) {
for (i = 0; i < Album.length; i += 1) {
window.console.log(Album[i].block);
if (Album[i].block.classList.contains('selected')) {
Album[i].block.classList.remove('selected');
}
}
visu.style.background = this.place;
window.console.log(visu.style.background);
window.console.log(this.place);
e.target.classList.add('selected');
};

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);

passing array to Constructor function and keep it public

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());

Categories

Resources