passing arguments in constructer function in javascript - javascript

function player(){
this.hitpoints =100;
this.attack = function attack(opponent){
opponent.hitpoints -= 10;
}
}
var p1 = new player();
var p2 = new player();
p1.name = "ali";
p2.name = "ahmed";
p1.attack(p2);
alert(p2.name+"has"+p2.hitpoints+"left behind");
The output of the above code is
ahmed has 90 left behind.
But whenever I change my code to p1.attack(p2.name; instead of p1.attack(p2); then it will output the following result:
ahmed has 100 left behind.
Why does it output this result?
I am a beginner in Javascript, I do not really know anything about objects. I simply want to know how arguments should be passed in that particular attack() function.

It is because you're passing an object to the function.
Passing p2.name as a parameter will not work, since p2.name is a property with data type of string.
The operation then goes with the following parameters given:
attack(p2) => p2.hitpoints -= 10
attack(p2.name) => p2.name.hitpoints -=10,
which is not valid because p2.name is not an instance of player.

If you use
p1.attack(p2.name)
then the code will try to substract 10 from p2.name.hitpoints and left p2.hitpoints intact.

Related

Why is a Javascript function without declared parameter working?

I'm writing a hangman game. With the help of Google I have a function to check if a letter is in the word, but I don't understand how, although I never declare the parameter "chosenLetter" of my function, this is able to give "chosenLetter" exactly the value of the specific letter I click on. Nor how "getElementById(chosenLetter)" can pick exactly the letter I click on to disable the button.
Same thing with the "guessedWord" function, where "letter" is never declared, yet it selects a letter to check for in the "guessed" array
let answer = '';
let maxWrong = 5;
let mistakes = 0;
let guessed = [];
let wordStatus = null;
function guessedWord() {
wordStatus = answer.split('').map(letter => (guessed.indexOf(letter) >= 0 ? letter : '_')).join('');
document.getElementById('word').innerHTML = wordStatus;}
function generateButtons() {
let buttonsHTML = 'abcdefghijklmnopqrstuvwxyz'.split('').map(letter =>
`
<button
class = "btn"
id = '` + letter + `'
onClick = "handleGuess('` + letter + `')"
>
` + letter + `
</button>
`).join('');
document.getElementById('alphabet').innerHTML = buttonsHTML;}
function handleGuess(chosenLetter) {
if (guessed.indexOf(chosenLetter) === -1) {
guessed.push(chosenLetter)
} else {
null;
}
document.getElementById(chosenLetter).setAttribute('disabled', true);
if (answer.indexOf(chosenLetter) >= 0) {
guessedWord();
checkIfGameWon();
} else if (answer.indexOf(chosenLetter) === -1) {
mistakes++;
updateMistakes();
checkIfGameLost();
}}
As I'm new at javascript, I'm generally trying to understand how is it possible that parameters not declared can seem to declare themselves so specifically? I don't know if I'm asking the wrong question, but that's the only thing in the code which I can't understand nor explain
You need to read this documentation first.
It says
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
If we try to break the following statement in separate statements,
wordStatus = answer.split('').map(letter => (guessed.indexOf(letter) >= 0 ? letter : '_')).join('');
You will find,
let splittedAnswer = answer.split(''); // This will split the answer string and crate an array with all the characters in answer.
const callbackFunction = (letter) => {
return guessed.indexOf(letter) >= 0 ? letter : '_';
}
let newArray = splittedAnswer.map(callbackFunction);
let joinedString = newArray.join('');
As you can see you are declaring a callback function. You are passing that function to the array.map() method. Now the array.map() method will call the function with 3 params currentItemInTheArray, currentIndex, theSourceArray. As you have declared only the first param in your callbackFunction i.e. currentElementInTheArray you will get the first param. You could declare your callback array like this,
const callbackFunction = (item, index, arr) => {
console.log(item);
console.log(index);
console.log(arr);
}
And now if you call
[1,2,3].map(callbackFunction);
You will get the following output,
1 //currItem
0 //index
[1,2,3] //source array
2 //currItem
1 //index
[1,2,3] //source array
3 //currItem
2 //index
[1,2,3] //source array
But you are doing it inline, that is why you were not following. I hope now it is clear to you.
This is how functions work, you pass an argument as an input and to use that argument in your function you use parameters in the function definition which act as placeholders for your input and then you can use the parameters anywhere inside your function.
Example: In the function guessedWord(), you are using a map function which takes a callback function as an argument. So the work letter is actually the parameter of the callback function and parameters don't need declaration they are just placeholders.
generateButtons is going to insert into the HTML element "alphabet" something that looks like this:
<button
class = "btn"
id = 'a'
onClick = "handleGuess('a')"
>
a
</button>
<button
class = "btn"
id = 'b'
onClick = "handleGuess('b')"
>
b
</button>
...
Those onClick handlers will be function that pass the various letters as the first (and only) argument to handleGuess.
handleGuess is a function declared to take a single parameter, which is known internally to the function as chosenLetter. But when you call it, you do not have to pass it a variable with the name chosenLetter. Javascript doesn't care about that. You could pass it a variable named foobar and it would be fine, or you could just pass it the raw value.
For a simpler example, let's say we had a simple function:
function area (height, width) {
return height * width
}
we could call it in various ways, including:
const height = 5;
const width = 8;
area (height, width) //=> 40
// or
const h = 6
const w = 7
area (h, w) //=> 42
// or
const rectangle = {
height: 3,
width: 10
}
area (rectangle.height, rectangle.width) //=> 30
// or simply
area (4, 9) //=> 36
The same principle applies to handleGuess
in JavaScript
variables that don't get declared will get automatically assigned to the global scope
is simple words it will declare it self :)
in your case something different is happening
you are passing the letter as a parameter to the function
onClick = "handleGuess('` + letter + `')"
and this is why it makes all the magic come alive :)
the same goes to the id property
id = '` + letter + `'
passing the information about which specific letter you are pressing on make it so that the JavaScript Engine know which button is being pressed and that is how it know what letter you chose and what he need to disable

Creating an Arithmetic Task Runner

I have been tasked to create an Arithmetic Task Runner as part of my assignment.
Up until today I've never used NodeJS or even the terminal to execute a script.
I have been working on this for the past 5 hours and still no luck. I have avoided coming here and asking as I'd like to figure it out for myself, however, I have succumbed to desperately needing help.
This is the code I have so far:
class ArithmeticTaskRunner {
static set taskCount(counter) {
throw new('This is a readOnly accessor, the value is ${value}');
}
add(y) {
this.y = y || 0
console.log(y)
}
minus(x) {
this.x = Math.abs(this.y) * -1;
console.log(this.x);
};
multiply(z) {
this.z = z * this.x;
console.log(this.z)
}
execute(startValue) {
this.startValue = startValue + this.y
this.y = this.startValue
console.log(this.startValue)
this.startValue = this.minus
console.log(this.startValue)
this.startValue = this.multiply(this.startValue)
console.log(this.startValue)
}
}
tasks = [
function() { minus()},
function() { multiply(z)},
function() { add(x)},
function() { execute(x)}
]
This is nowhere near perfect, but it's 80%-90% near completion.
This is the task I have been given:
You should implement a class called ArithmeticTaskRunner with the following:
- An instance variable named tasks which is initialised to an empty array upon
creation.
- A method named addNegationTask which adds an anonymous function to the
tasks array. This anonymous function should take one argument, x, and return the
negation, -x.
- A method named addAdditionTask which takes a single argument y, and adds
an anonymous function to the tasks array. This anonymous function should take
one argument, x, and return the result x + y.
- A method named addMultiplicationTask which takes a single argument y,
and adds an anonymous function to the tasks array. This anonymous function
should take one argument, x, and return the result x * y.
- A read-only accessor named taskCount which returns the number of queued tasks.
- A method named execute, which takes a single argument named startValue.
If omitted, startValue defaults to zero. Starting at startValue, this method should iterate over the tasks array executing each function on the current value. It then returns the resulting number after all arithmetic operations have been executed.
I'd be grateful for any help I could get.
The issues I have are the following: The execute method (trying to make the startValue, after the addition, a negative), the multiplication method and the fact I cannot call the addition method twice without overriding the value. The examples of the program fully working have shown I should allow for a method to be called multiple times without overriding the previous value.
I know there's a rule where it's one question per issue, I concede that. But if anyone can help me out with any of the issues I will truly be grateful and I will compensate people for their efforts.
Thank you.
Edit - This is an example of both the expected inputs/outputs
> let taskRunner = new ArithmeticTaskRunner()
undefined
> taskRunner.addAdditionTask(2)
undefined
> taskRunner.addMultiplicationTask(4)
undefined
> taskRunner.addAdditionTask(10)
undefined
> taskRunner.execute(2)
26
> taskRunner.execute(-2)
10
I don't want to provide the whole answer because this is an assignment for you, but here's some code that might help you out. This starts with 5 then calls doubleIt and then calls addOne to arrive at 11.
It does this by creating an array of functions, each one performs a simple task and returns the result of its input modified in some way.
Then it creates a function called execute that uses Array.reduce to call the first function in the array with a given initial value, then repeatedly calls each function in the array on the result. Check the documentation for Array.reduce if you're confused about how it works.
doubleIt = x => x * 2;
addOne = x => x + 1;
tasks = [doubleIt, addOne];
execute = (initial) => tasks.reduce((x,fn) => fn(x), initial)
document.write(execute(5))
Hint #2
class ArithmeticTaskRunner {
constructor() {
this.tasks = [];
}
addAdditionTask(arg) {
this.tasks.push(x => x + arg);
}
addMultiplicationTask(arg) {
this.tasks.push(x => x * arg);
}
execute(startValue) {
return this.tasks.reduce((x, fn) => fn(x), startValue);
}
}
let taskRunner = new ArithmeticTaskRunner()
taskRunner.addAdditionTask(2)
taskRunner.addMultiplicationTask(4)
taskRunner.addAdditionTask(10)
document.write(taskRunner.execute(2));
document.write(', ');
document.write(taskRunner.execute(-2));

What is being passed into this 'function(x)'?

I'm having a hard time grasping some finer details of javascript, I have this function function(x) it doesn't seem to be receiving any parameters. Maybe I'm not understanding the Math.sin part. I'm not sure. Any ideas on what is happening?
function makeDerivative( f, deltaX )
{
var deriv = function(x) // x isn't designated anywhere
{
return ( f(x + deltaX) - f(x) )/ deltaX;
}
return deriv;
}
var cos = makeDerivative( Math.sin, 0.000001);
// cos(0) ~> 1
// cos(pi/2) ~> 0
Update
I tried this instead and got NaN, then 15
function addthings(x, y)
{
var addition = function(m)
{
return( x + y + m);
}
return addition;
}
var add = addthings(5, 5);
alert(add());
alert(add(5));
To understand how that code works you have to read more about currying in functional javascript and functions closures.
The outer function returns the inner function, so everything you pass to
cos later theoretically is what you pass into the inner function. Imagine calling it like this:
console.log(makeDerivative( Math.sin, 0.000001)(0)); // 1
would output the same as if you're doing it as described
console.log(cos(0)) // 1
as cos is assigned reference to a function (the one that gets returned by makeDerivative).
The other answers touch on the issue, but I'm going to try to get to the core of it.
JavaScript variables are untyped, which means that they can dynamically change what kind of variable they are. On a simple level, this means that var a can be instantiated as an array, and then later assigned as a string on the fly.
But you can also store entire functions within those untyped variables. For example;
var test = 'hey'
console.log(test) //:: hey
test = function(input){ console.log('inner function: ' + input) }
console.log(test) //:: function(input){ console.log('inner function' + input) }
test() //:: inner function
test('with input') //:: inner function with input
Where //:: _____ represents the output to the console.
So the function you are using returns another dynamic function. You can then call that function in a normal fashion, inputting the value for x when you call it.
Well, you don't really call the function in the code you posted.
The makeDerivative gets reference to Math.sin function and inside it uses it to create reference to function which compute derivation of the passed function (see the f parameter).
In your example this reference is assigned to cos variable. If you called it with (0) argument, you would get 1 as return value and the argument (0) would be passed into that deriv function...

Function updating a number var through a parameter doesn't correctly update number var

So I have this bit of code that goes like this
var number = 0;
function addnumber(numbertype){
numbertype = numbertype +50;
}
function numberupdate() {
document.getElementById('adiv').innerHTML = number;
}
Somewhere, I call
onClick="addnumber(number);"
Now, if I check the value of number with an alert, it displays correctly. But the number only goes to 50 once and doesn't climb the more I click, and even though an alert called within the addnumber() function will caluclate number correctly, it will not update the value of number when checked outside of that function.
I'm sure I'm missing something simple.
In your addnumber function, the variable that you're passing in is getting increased by 50, not (I'm assuming) number.
You could change it to:
function addnumber(){
number += 50;
}
You are confused with number and numbertype variable.
var number = 0;
function addnumber(numbertype){
number = number + numbertype +50;
}
function numberupdate() {
document.getElementById('adiv').innerHTML = number;
}
Arguments to a javascript function are either passed 'by value' in case of primitives, or 'by reference' in case of objects. Your var 'number' is a primitive. In this case, a copy is made of the primitive value, and passed as the argument. Addnumber therefore adds 50 to a copy of number, not to number itself.
When you want to change the value of a variable in this way, use an object, then it will work as you initially expected:
var number={value:0};
function addnumber(numbertype){
numbertype.value = numbertype.value +50;
}

JSON corrupted attributes

I'm having difficulties understanding behavior of Javascript.
Code:
function getPosition(element){
var position = {
x:$(".line div").has(element).index(),
y:$(".line").has(element).index()
};
console.log(position.y);
console.log(position)
return position;
}
Now while calling it from function I'm getting results like this:
0
Object
x: 8
y: 3
What I don't understand is how is it possible to change object attributes when trying to access it via object reference, but not directly.
But when I call same function from console I get this:
0
Object
x: 8
y: 0
This is the same element passed to function. And it seems that it fails always when X or Y is 0(zero), when it's another number it's ok.
Could anyone explain what I'm doing wrong? Or is it somekind of JS bug? O_o
EDIT:
So I finally found out what the problem was. I always thought that I was passing values but unfortunately I was wrong all the time. During some searches on stackoverflow, I found topic about JS values and references.
If anyone is interested and too lazy to read the topic, you can look at this example. It's pretty much self explanatory.
function test(){
var a = 5;
var b = a; //b now has value of 5
console.log("a:"+a+":b:"+b);
b = 4;//a still has value of 5 and b is assinged to 4
console.log("a:"+a+":b:"+b);
var c = {val:1};
var d = c; //d now has reference to c
d.val = 2; //c.val changes because it is a reference
console.log(c);
}
EDIT2:
oh and by the way, how can I mark my question as answered?
console.log delays converting values to string until the application slows down so that logging doesn't slow down the application unnecessarily.
If the console.log(position) is showing a value that is different from that at the time console.log was called its because the position has been modified between the call and the time the console widget decided to format the value for display.
You can see this by trying the following HTML:
<script>
// Emits the JSON form when converted to a string.
var obj = {
x: 1,
toString: function () {
return JSON.stringify(this);
}
};
console.log(obj); // Often {x:2}
console.log("" + obj); // Reliably {x:1}
obj.x = 2;
</script>
Look for code that does something like
obj = getPosition(...);
...
obj.y = <expression that evaluates to zero>
Alternatively, you can force eager formatting by changing
console.log(position)
to
console.log("" + position)
So I finally found out what the problem was. I always thought that I was passing values but unfortunately I was wrong all the time. During some searches on stackoverflow, I found topic about JS values and references.
If anyone is interested and too lazy to read the topic, you can look at this example. It's pretty much self explanatory.
function test(){
var a = 5;
var b = a; //b now has value of 5
console.log("a:"+a+":b:"+b);
b = 4;//a still has value of 5 and b is assinged to 4
console.log("a:"+a+":b:"+b);
var c = {val:1};
var d = c; //d now has reference to c
d.val = 2; //c.val changes because it is a reference
console.log(c);
}

Categories