pass by reference. Not working - javascript

Passing object to function is not working.
function getSecret(file, secretPassword){
file.opened = file.opened + 1;
if(secretPassword == file.password){
return file.contents;
}
else {
return "Invalid password! No secret for you";
}
}
function setSecret(file, secretPassword, secret){
if(secretPassword == file.password){
file.opened = 0;
file.contents = secret;
}
}
var superSecretFile = {
level: "classified",
opened: 0,
password: 2,
contents: "Dr. Evel's next meeting is in Detroit."
};
var secret = getSecret(superSecretFile, superSecretFile.password);** why superSecretFile.password is not passing the value 2
console.log(secret);
setSecret(superSecretFile,2, "Dr. Evel's next meeting is in Philadelphia.");
secret = getSecret(superSecretFile, superSecretFile.password);
console.log(secret);
I am passing an object as an argument. This code doesn't work if I put superSecretFile.password. Why it doesn't?

Related

Passing function in other functions as parameters

I've recently started studying programming and JS, HTML, CSS.
Reading a book at the moment which includes the following snippet of code which i try to understand and modify for my own practice and attempts in understanding. But i really can't grasp what's going on.
Is there anyone that could please try and explain what's happening and why my modified snippet of code won't run - as it does look similar to part of the original one that does run fine.
First snippet attached is original one from book.
Second is mine which is built on parts of the prior one.
var validateDataForAge = function(data) {
person = data();
console.log(person);
if (person.age <1 || person.age > 99){
return true;
} else{
return false;
}
};
var errorHandlerForAge = function(error) {
console.log("Error while processing age");
};
function parseRequest(data,validateData,errorHandler) {
var error = validateData(data);
if (!error) {
console.log("no errors");
} else {
errorHandler();
}
}
var generateDataForScientist = function() {
return {
name: "Albert Einstein",
age : Math.floor(Math.random() * (100 - 1)) + 1,
};
};
//parse request
parseRequest(generateDataForScientist, validateDataForAge,
errorHandlerForAge);
var validateAge = function(age) {
person = age();
console.log(age);
}
validateAge(17);
I get following errormessage:
TypeError: age is not a function
at validateAge:2:12
at eval:7:1
at eval
at new Promise
Thankful for any help.
Regards,
Here is the code you are looking at. It expects data to be a function.
var validateDataForAge = function(data) {
person = data();
… and so it is (the one assigned to generateDataForScientist after it gets passed through a couple of other variables and function calls).
Here is your code:
var validateAge = function(age) {
person = age();
It expects age to be a function.
Here you pass it a value:
validateAge(17);
17 is a number, not a function.
The problem is here in this part of your code
var generateDataForScientist = function() {
return {
name: "Albert Einstein",
age : Math.floor(Math.random() * (100 - 1)) + 1, // <- problem
};
};
age is just a property of the object your returning and you are using age as a function in this code
var validateAge = function(age) {
person = age(); // <-- here ,age is not a function
console.log(age);
}
you need to chage the age property to be a function like this
var generateDataForScientist = function() {
return {
name: "Albert Einstein",
age : function (){ return Math.floor(Math.random() * (100 - 1)) + 1 },
};
};
consoling data inside parseRequest will log it as a function. But you need the property age. So replace validateData(data) with validateData(data());
var validateDataForAge = function(data) {
let person = data;
if (person.age < 1 || person.age > 99) {
return true;
} else {
return false;
}
};
var errorHandlerForAge = function(error) {
console.log("Error while processing age");
};
function parseRequest(data, validateData, errorHandler) {
console.log(data)
var error = validateData(data());
if (!error) {
console.log(error);
} else {
errorHandler();
}
}
var generateDataForScientist = function() {
return {
name: "Albert Einstein",
age: Math.floor(Math.random() * (100 - 1)) + 1,
};
};
//parse request
parseRequest(generateDataForScientist, validateDataForAge, errorHandlerForAge);

How to change scope back to original function after calling a “local” function within module.exports in Node.JS

I am trying to call another local function 'MessageScoring' within another function 'NextMessageCalculation' which are both in module.exports, however I am having trouble with getting the scope to change back. The function successfully calls the other local function, however the scope is then changed and variables in the previous scope all return undefined now. How would I fix this or is there a better way to call the local function to avoid this?
module.exports = {
MessageScoring: function(){
var attrs_list = Object.keys(message_attr_obj);
var score = 0;
for (i in attrs_list){
if(user_data[attrs_list[i]]){
score = score + user_data[attrs_list[i]]["beta"];
}
else{
//user has no response with that attr yet so score is not added
}
}
score = score / attrs_list.length;
return score}... //returns an int
NextMessageCalculation: function(){ //has a call to a mongodb and the logic takes place in the callback
MESSAGE_collection.find({'message_set':user_data.message_set,'id':{$nin:[1111]}}).toArray(function(err,doc){
if (doc.length === 0)
{
USERDATA_collection.update({phone:phone_num},{$set:{send_message:false}},function(err,res) {
db.close()
});
}
else{
var highest_score = "";
var next_message = "";
for (i in doc)
{
console.log(doc[i]['id']);
var score = module.exports.MessageScoring(doc[i].attr_list,user_data);
console.log(doc[i]['id']); <---- becomes undefined here after calling scoring function which correctly returns int
if (highest_score === "")
{
console.log(doc[i]);
next_message = doc[i].id;
highest_score = score;
}
if (highest_score < score)
{
next_message = doc[i].id
highest_score = score;
}
console.log(doc[i].id);
}
Use function hoisting, step out from the modules.expors closure, and be sure that MessageScoring doesn't mutate data.
module.exports = {
MessageScoring,
NextMessageCalculation:
}
function MessageScoring() {
}
function NextMessageCalculation(){
const d = [{ id: 'ok' }];
const i = 0;
console.log(d[i]['id']); //returns ok
var score = MessageScoring(doc[i].attr_list,user_data);
console.log(d[i]['id']); //returns ok
}

Setting an empty array index

i have an array that holds student answers for given questions.
if a student gives an answer, it gets inserted into the array at the current index like answers[questionindex] = answer
later, i can read the array and map the entries to the given question-array
this case:
[
"answer",
undefined, // student has not given answer
"answer2",
]
works. (looping over the array, simply outputting "no answer given" if (answers[questionindex] === undefined)
but it doesn't work when the LAST answers were undefined (1 or more)
they just don't exist (of course).
how can i set those fields to undefined (like, after a timer reaches zero), to show that there was no answer given?
right now, the average-calculation shows 100% correct for 3 given (correctly), then 2 not given at all
code
var testResults = {
addRoom: function(Id, teacher) { // room pseudoconstructor
this[Id] = {
created: moment(),
runningProblem: false,
time: 0, // holds the countdown for the current problem
getTime: function() { // returns the countdown-counter
return this.time;
},
Id: Id,
teacher: teacher,
getCurrentSolution: function() {
return math.eval(this.testProblems[this.getCurrentProblemIndex()].problem);
},
getTimeTaken: function() {
return this.getCurrentProblemTimeLimit() - this.time;
},
getCurrentProblemTimeLimit: function() {
return this.testProblems[this.getCurrentProblemIndex()].timeLimit;
},
getCurrentProblemIndex: function() {
return this.testProblems.length - 1;
},
addTestProblem: function(problem, timeLimit) {
var solution = math.eval(problem);
this.testProblems.push({problem: problem, timeLimit: timeLimit, solution: solution});
console.dir(this.testProblems);
},
testProblems: [],
updatePercentages: function(name) {
function round(num) {
return +(Math.round(num + "e+2") + "e-2");
}
console.log('updating percentages');
console.log('answers length ' + this.students[name].givenAnswers.length);
var timeSum = 0;
for(var i = 0; i < this.students[name].givenAnswers.length; i++ ) {
timeSum += this.students[name].givenAnswers[i].takenTime;
}
var timeAvg = timeSum / this.students[name].givenAnswers.length;
console.log('timeAvg for ' + name + ' ' + timeAvg);
this.students[name].avgTime = round(timeAvg);
var correctSum = 0;
for(var j = 0; j < this.students[name].givenAnswers.length; j++ ) {
if (this.students[name].givenAnswers[j].correct) {
correctSum++;
}
}
var correctAvg = correctSum / this.students[name].givenAnswers.length;
console.log('correctAvg for ' + name + ' ' + correctAvg);
this.students[name].avgCorrect = round(correctAvg) * 100;
},
addGivenStudentAnswer: function(name, answer, takenTime, index) {
console.log('adding answer ' + name + ' ' +answer+ ' ' + takenTime);
var correct = this.getCurrentSolution() == answer;
if (typeof this.students[name].givenAnswers[index] === 'undefined') {
this.students[name].givenAnswers[index] = ({
answer: answer,
takenTime: takenTime,
correct: correct
});
this.updatePercentages(name);
//console.dir(this.students[name].givenAnswers);
return true;
} else {
console.log('attempt at double answer. not saved');
return false;
}
},
addStudent: function(name) {
if (!(this.students[name])) {
this.students[name] = {
studentName : name,
avgTime: 0,
avgCorrect: 0,
givenAnswers: []
}
}
console.dir(this);
},
students: {}
};
console.dir(this);
},
deleteRoom: function(Id) {
delete this[Id];
console.log('room deleted from testResults');
}
};
// after test
var name = socket.userName;
var room = socket.room;
var created = testResults[room].created;
var students = testResults[room].students;
var problems = testResults[room].testProblems;
var test = new tests({
roomId : room,
created : created,
teacher : name,
students : students,
problems : problems
});
test.save(function(err, result) {
if (err) {console.log(err);}
else {
console.log('test saved to DB');
socket.emit('testSaved');
// delete from roomList
testRooms.deleteRoom(room, name);
// delete from resultObject
testResults.deleteRoom(room);
// answer
io.in(room).emit('room Closed');
}
});
route for reading a test from DB afterwars
router.get('/showtests/:roomId', function(req, res) {
if (req.user && req.user.role === 'teacher') {
tests.findOne({roomId: req.params.roomId}, {}, function(err, result) {
if (err) {console.log(err);}
res.render('showSingleTest', {user: req.user, testData: JSON.parse(JSON.stringify(result))});
})
} else {
res.render('customerror', { title: "Error", errMsg1: "error.error", errMsg2: "error.notLoggedIn" });
}
});
aaaaaand the jade
h2(data-i18n="markup.studentsAnswers")
each student in testData.students
.testViewSingleStudentAnswers.col-md-6
h3 #{student.studentName}
ol.answers
each answer in student.givenAnswers
if (answer)
if (answer.correct == true)
li.correct
span #{answer.answer}
|
span.floatRight (#{answer.takenTime}s)
else
li.wrong
span #{answer.answer}
|
span.floatRight (#{answer.takenTime}s)
else
li.noAnswer(data-i18n="markup.noAnswerGiven")
.testTotals
| #{student.avgCorrect}
span(data-i18n="markup.percentCorrect")
| ,
| #{student.avgTime}
span(data-i18n="markup.avgTime")
You can do like so:
function push_answer(answer){
answer = answer || "undefined"
array_of_answers.push(answer)
}
Now, the value is not undefined, but it's defined by the literal. You can replace it with some unicode character in case some answer can be "undefined".
Have a nice day!
Seems to be working without issue for me.
HTML:
<div id="content">
</div>
JS:
var answers = ["answer1","answer2",undefined,"answer3",undefined];
for(i=0;i<answers.length;i++) {
if(!answers[i]){
answers[i]="no answer";
}
}
document.getElementById('content').innerHTML = answers;
jsFiddle
My personal recomendation: "Never leave things to chance"
if the student doesn't choose an answer, you should fill that blank space with a '', because undefined is really annoying to handle, so in order to fill the gaps:
This will check if answer is "undefined" and fill the gap with a '' (blank), then, when you check that answer, is going to be more simple to evaluate...
if(answer)
answers[questionindex] = answer;
else
answers[questionindex] = '';

Is there a property in javascript Object.type?

I am studying Node.Js right now and came across this piece of code:
var combine = require('stream-combiner');
var through = require('through2');
var split = require('split');
var zlib = require('zlib');
module.exports = function () {
var grouper = through(write, end);
var current;
function write (line, _, next) {
if (line.length === 0) return next();
var row = JSON.parse(line);
if (row.type === 'genre') {
if (current) {
this.push(JSON.stringify(current) + '\n');
}
current = { name: row.name, books: [] };
}
else if (row.type === 'book') {
current.books.push(row.name);
}
next();
}
function end (next) {
if (current) {
this.push(JSON.stringify(current) + '\n');
}
next();
}
return combine(split(), grouper, zlib.createGzip());
};
Each line the write function gets is a json line that looks like this:
"name": "Neuromancer","genre": "cyberpunk"
And the expected outcome is the following JSON object:
{
"name": "cyberpunk",
"books": [
"Accelerando",
"Snow Crash",
"Neuromancer",
"The Diamond Age",
"Heavy Weather"
]}
and etc.
Basically my question is - what does the row.type means?
Thank you in advance! :D
You put the type parameter in the var row doing
var row = JSON.parse(line);
so that's not a special property o function of the object, it's only, simply, a parameter that was in the JSON (of var line)

What is preventing the skill[id].Value increment? (Javascript)

If I create a button with the name "Level 0" and onmousedown I have it run learnSkill(3) it only increments the skill[3].Value to 1, then it picks up a click but does nothing, why?
I am trying to code a skill tree, I haven't gotten very far because of issues like this so it's mostly empty.
var skill = new Array();
function Skill(value, name, type, tier, column, info, requirement) {
this.Value = value;
this.Name = name;
this.Type = type;
this.Tier = tier;
this.Column = column;
this.Info = info;
this.Req = requirement;
//skill[id].Req
}
function SkillReq(id, amount, reqby) {
this.Id = id;
this.Amount = amount;
this.By = reqby;
//skill[id].Req.Id
//skill[id].Req.Amount
//skill[id].Req.By
}
skill[1] = new Skill(0, "Unholy Sphere", "Tree 2", 0, 1, new Array(), new SkillReq(0, 0, 3));
skill[3] = new Skill(0, "Dark Circle", "Tree 2", 1, 0, new Array(), new SkillReq(1, 3, 0));
function canLearn(id) {
alert("in canlearn");
canLearn = true;
return canLearn;
}
function canUnlearn(id) {
}
function learnSkill(id) {
alert("id: "+id);
if (!canLearn(id)) {
alert("cannot learn");
return;
}
// Increase current skill value
skill[id].Value++;
alert(skill[id].Value);
// totalSP--; Decrease totalSP, must declare first
// Update button to show new level of skill value
document.getElementById(id).value = "Level "+skill[id].Value;
}
function unlearnSkill(id) {
if (!canUnlearn(id)) {
return;
}
}
function onClickTalent(id) {
}
function rmbDown(e)
{
var isRMB = false;
e = e || window.event;
if (e.which)
isRMB = (e.which == 3);
else if (e.button)
isRMB = (e.button == 2);
return isRMB;
}
You are overwriting your canLearn function inside of it, the canLearn identifier you assign to true is the function itself, to create a new variable in the function scope use the var keyword
function canLearn(id) {
alert("in canlearn");
var canLearn = true;
return canLearn;
}
I'm not really sure what it is you're trying to do, but here's one problem:
function canLearn(id) {
alert("in canlearn");
canLearn = true;
return canLearn;
}
That function will "self-descruct" the first time it's called, because you're setting the global symbol "canLearn" to true. Trouble is, "canLearn" is already used - as the name of that function! Thus, subsequent attempts to call "canLearn" will fail because its value is no longer a function object.

Categories