I'm not sure if this is bad code or would it be "better" to put the isPrime function in a method and then use that method inside the printSomething method?, if so how would it be possible how can i use one method inside another method?
class PrimeNumbers{
constructor(isPrime, number){
this.isPrime = isPrime;
this.succes = "succes";
this.failure = "failure";
this.number = number;
}
printSomething(isPrime){
if (!this.isPrime(this.number)) {
console.log(this.succes);
} else {
console.log(this.failure);
}
}
}
function isPrime(value) {
if (value == 1) return false;
for (let i = 2; i <= Math.sqrt(value); i++) {
if (value % i == 0) {
return false;
}
}
return true;
}
let primeTest = new PrimeNumbers(isPrime, 10)
primeTest.printSomething()
Hopefully someone who can explain this better than me comes along. In case they don't ... you can add isPrime as a method on PrimeNumbers and then use it with this.isPrime(). Here, this refers to the current object that you're dealing with.
When you do let primeTest = new PrimeNumbers(10); primeTest becomes an instance of PrimeNumbers, when you do primeTest.printSomething() you're accessing the printSomething property on primeTest and calling it. Once the code is executing inside printSomething it will often need a way to refer to the object that's stored in primeTest that's what the this keyword does; it allows you to refer to the particular instance of the object that's being dealt with when the code runs.
This page is probably much better at explaining what I've just tried to explain.
In terms of whether it's better to add to add isPrime to the class. I'm not really sure, it might depend on some other things. If you don't add it to the class it's pretty unlikely that you need to pass the function as an argument to the constructor (though there probably are reasons to do this there's probably no point if you're always passing in the same function) you can just call the function inside the class methods.
isPrime as method:
class PrimeNumbers{
constructor(number){
this.succes = "succes";
this.failure = "failure";
this.number = number;
}
printSomething(){
if (!this.isPrime(this.number)) {
console.log(this.succes);
} else {
console.log(this.failure);
}
}
isPrime(value) {
if (value == 1) return false;
for (let i = 2; i <= Math.sqrt(value); i++) {
if (value % i == 0) {
return false;
}
}
return true;
}
}
let primeTest = new PrimeNumbers(10);
primeTest.printSomething();
isPrime as function called from the class:
function isPrime(value) {
if (value == 1) return false;
for (let i = 2; i <= Math.sqrt(value); i++) {
if (value % i == 0) {
return false;
}
}
return true;
}
class PrimeNumbers{
constructor(number){
this.succes = "succes";
this.failure = "failure";
this.number = number;
}
printSomething(){
if (!isPrime(this.number)) {
console.log(this.succes);
} else {
console.log(this.failure);
}
}
}
let primeTest = new PrimeNumbers(10);
primeTest.printSomething();
Related
In this example I would like to call the defineX function before calling the add and value methods
class cl {
#x;
defineX(n) {
this.#x = n;
return this;
}
add(n) {
this.#x += n;
return this;
}
value() {
return this.#x;
}
}
const cObj = new cl();
console.log(cObj.defineX(3).add(5).value()); // output 8
console.log(cObj.add(3)) // should not happen
what is the best solution so I can prevent calling add before defineX method ??
also how to prevent calling the add method after it has been called for the first time ??
Don't use a single class, use multiple ones with different methods, each holding a different immutable state. It's simpler without class syntax at all though:
const cObj = {
defineX(n) {
const x = n;
return {
add(n) {
const v = x + n;
return {
value() {
return v;
}
};
}
};
}
};
console.log(cObj.defineX(3).add(5).value()); // output 8
console.log(cObj.add(3)) // error
With classes:
const cObj = {
defineX(n) {
return new Cl(n);
}
};
class Cl {
#x;
constructor(x) {
this.#x = x;
}
add(n) {
return new Result(this.#x + n);
}
}
class Result {
#v;
constructor(v) {
this.#v = v;
}
value() {
return this.#v;
}
}
Since 1) operations not allowed and 2) breaking from a chain of calls are involved, it seems to me correct way is to throw an exception whenever something wrong happens. You can always try/catch it if you know exception is a possibility.
class cl {
#x;
#defined;
#added;
defineX(n) {
this.#x = n;
this.#defined = true;
return this;
}
add(n) {
if (!this.#defined) {
throw new Error("`add` before define")
}
if (this.#added) {
throw new Error("already did `add`")
}
this.#x += n;
this.#added = true;
return this;
}
value() {
return this.#x;
}
}
const cObj = new cl();
// tests:
// console.log(cObj.defineX(3).add(5).value()); // output 8
// console.log(cObj.add(3)) // should not happen - output error
console.log(cObj.defineX(3).add(5).add(6).value()); // output error
I can easily understand how it works in C#, but in Javascript I'm a little bit confused. Here is a little test code I wrote:
function Lunch(name,price)
{
var priceChanging = [], priceChanged = [];
this.name = function(val)
{
return name;
}
this.price = function(val)
{
if(val !== price && val !== undefined )
{
for(var i = 0; i < priceChanging.length; i++)
{
if(!priceChanging[i](this,val))
{
return price;
}
}
price = val;
for(var i = 0; i < priceChanged.length; i++)
{
priceChanged[i](this);
}
}
return price;
}
this.OnPriceChanging = function(val)
{
priceChanging.push(val);
}
this.OnPriceChanged = function(val)
{
priceChanged.push(val);
}
}
var order = new Lunch("Fish and Chips",20);
console.log(order.name());
console.log(order.price());
order.OnPriceChanging(function(name,price)
{
if(price > 30)
{
console.log("Price too high");
return false;
}
return true;
});
order.OnPriceChanged(function(name)
{
console.log("Price changed to: $" + name.price());
});
It runs fine, the thing is I want to be able to explain it to myself. I'm not in front of a debugger and just used Notepad at the moment. I just thought of it like .NET where subscribers are put in a container, I'm just curious how it works in Javascript.
Does the OnPriceChanging and OnPriceChanged function call themselves automatically anytime you add/change the price? I guess I'm just uncomfortable with how Javascript is loosely typed and all.
As always, I'm very thankful for all the imparted knowledge.
It's really quite simple. You have two arrays that store functions:
var priceChanging = [], priceChanged = [];
You have two methods that push functions into the arrays:
this.OnPriceChanging = function(val)
{
priceChanging.push(val);
}
this.OnPriceChanged = function(val)
{
priceChanged.push(val);
}
You then push functions into the arrays:
order.OnPriceChanging(function(name,price)
{
if(price > 30)
{
console.log("Price too high");
return false;
}
return true;
});
order.OnPriceChanged(function(name)
{
console.log("Price changed to: $" + name.price());
});
Note that the code above may be confusing if you're not used to seeing anonymous functions. They are exactly equivalent to this:
function priceChangingCallback (name,price)
{
if(price > 30)
{
console.log("Price too high");
return false;
}
return true;
}
function priceChangedCallback (name)
{
console.log("Price changed to: $" + name.price());
})
order.OnPriceChanging(priceChangingCallback);
order.OnPriceChanged(priceChangedCallback);
So you see, the arrays priceChanging and priceChanged should now both contain a single function each.
Does the OnPriceChanging and OnPriceChanged function call themselves automatically anytime you add/change the price?
No, they do not. In fact to be precise, it's not OnPriceChanging and OnPriceChanged that are called. It's functions inside the arrays priceChanging and priceChanged. And they don't call themselves. You called them:
this.price = function(val)
{
if(val !== price && val !== undefined )
{
for(var i = 0; i < priceChanging.length; i++)
{
if(!priceChanging[i](this,val)) // <--- you're calling it here!!
{
return price;
}
}
price = val;
for(var i = 0; i < priceChanged.length; i++)
{
priceChanged[i](this); // <-- you're calling it here!!
}
}
return price;
}
You're calling all functions inside priceChanging and priceChanged arrays inside for loops. Functions that you added to the arrays using the OnPriceChanging and OnPriceChanged methods.
I'm struggling in a recursive Javascript function to find a specific subdirectory. This is my code:
function navigateToParent() {
var parentFullPath = parentDirectory(); // gets the full Path String
if (parentFullPath != null) {
var parent = getDirectoryByName(parentFullPath, rootDirectory);
// set the parent directory object as the current one
currentDirectory(parent);
}
}
function getDirectoryByName(fullName, myDirectory) {
if (myDirectory.fullName == fullName) {
return myDirectory;
} else {
var subs = myDirectory.subDirectories;
for (i = 0; i < subs.length; i++) {
return getDirectoryByName(fullName,subs[i]);
}
}
}
Every directory object has the properties fullName(string),subDirectories(array of directories) and files(array of files). My aim is to get the correct directory object, where it's fullName is matching.
I know, that i have to break the for loop in some way, but i don't know how to do it exactly.
After overthinking the logic i came to this solution (seems to work):
function getDirectoryByName(fullName, myDirectory) {
if (myDirectory.fullName == fullName) {
return myDirectory;
} else {
var subs = myDirectory.subDirectories;
for (i = 0; i < subs.length; i++) {
var match = getDirectoryByName(fullName, subs[i]);
if (typeof match !== "undefined"){
return match;
}
}
}
}
I'm trying to create a function to loop through some table rows but I need to use this.isempty instead of isempty. How do I access this inside of an each loop.
Code:
function checkValues(look) {
this.isempty = 1;
this.search = $(look).find("input").each(function(){
if ($.trim($(this).val())!="") {
this.isempty = 0;
}
});
return this.isempty;
}
Obviously the this.isempty = 0; will not work. How can I do this?
You can use a closure variable in this case to refer isempty
function checkValues(look) {
this.isempty = 1;
var self = this;
this.search = $(look).find("input").each(function () {
if ($.trim($(this).val()) != "") {
self.isempty = 0;
}
});
return this.isempty;
}
But a more appropriate way here is to use .filter() like
function checkValues(look) {
this.isempty = 1;
this.search = $(look).find("input").;
this.isempty = this.search.filter(function () {
return $.trim(this.value) != '';
}).length > 0;
return this.isempty;
}
Do you need to reference this because of a constraint in your code? Would the following work?
function checkValues(look) {
var isEmpty = 1;
$(look).find("input").each(function(){
if ($.trim($(this).val())!="") {
isEmpty = 0;
return false; // Breaks out of the loop for a little performance boost
}
});
return isEmpty;
}
I am comparing two attributes of the same object to work out which one is larger, if one is larger then it sets another attribute to True.. else it sets it to false.
Here is my function:
country.prototype.cure = function(){
for (var i = 0; i<this.diseases.length; i++)
{
console.log(this.health);
console.log(this.diseases[i].cureLevel);
if (this.heatlh >= this.diseases[i].cureLevel)
{
this.diseases[i].cured = true;
createDiseaseTable();
}
else
{
this.diseases[i].cured = false;
}
}
}
NOTE: this.health = 39000000 and this.diseases[i].cureLevel = 2500000
The problem is that whenever I run the function, despite this.health being larger it will always miss the if and go straight to the else...
Try this:
country.prototype.cure = function(){
for (var i = 0; i<this.diseases.length; i++)
{
var a=parseInt(this.health);
var b=parseInt(this.diseases[i].cureLevel);
if (a >= b)
{
this.diseases[i].cured = true;
createDiseaseTable();
}
else
{
this.diseases[i].cured = false;
}
}
}