Difficulties with using function expression - javascript

Hopefully you will answer it !
var myform = document.getElementById("myform"),
saveBtn = document.getElementById("submit");
saveBtn.addEventListener("click", saveInfo);
var saveInfo = function (e){
e.preventDefault();
var dateValue = document.getElementById("inputdeadline").value;
var todoValue = document.getElementById("textarea").value;
todoValue = todoValue.replace(/\n/g," ");
if ( dateValue > 24 || dateValue <= 0) {
myform.reset();
return false;
};
if (!(todoValue)) {
myform.reset();
return false;
};
var todoObj = {
todoValue,
dateValue
};
if (localStorage.getItem("localTodoItem") === null) {
var todoArray = [];
todoArray.push(todoObj);
todoArray.sort(function (a, b) {
return a.dateValue - b.dateValue;
});
localStorage.setItem("localTodoItem", JSON.stringify(todoArray));
} else {
var todoArray = JSON.parse(localStorage.getItem("localTodoItem"));
todoArray.push(todoObj);
todoArray.sort(function (a, b) {
return a.dateValue - b.dateValue;
});
localStorage.setItem("localTodoItem", JSON.stringify(todoArray));
};
showTodoItems();
myform.reset();
};
Here when I am using function declaration for this saveInfo function it is correctly doing all functionalities but when I am using function expression it just reload the page that's it nothing happening.
Please help me.
If you need more clarification about code please visit github.

This is because function declarations are hoisted, whereas function expressions are not. You're using saveInfo before the expression is executed, which would work for a declaration but not an expression.
Function declaration hoisting on MDN

Related

JSlint warning "Move variable declaration to top of function or script."

I don't know why there is a warning of "Move variable declaration to top of function or script."
Although I move the variable "myName" to other places, the variable below will be the new one having the same warning. I have input "window, document" in the "Options" section in JSlint.
window.onload = function() {
"use strict";
var myLogin = document.forms.submitForm;
myLogin.onsubmit = processForm;
var myName = document.getElementById("result__username");
var myPassword = document.getElementById("result__password");
var myMessage = document.getElementById("output");
myMessage.classList.add("displaynone");
function processForm() {
var in_username = myLogin.username;
var in_password = myLogin.password;
if (in_username.value === "") {
in_username.classList.add("changered");
in_username.focus();
return false;
}
in_username.classList.add("changewhite");
if (in_password.value === "") {
in_password.classList.add("changered");
in_password.focus();
return false;
}
in_password.classList.add("changewhite");
myName.innerHTML = in_username.value;
myPassword.innerHTML = in_password.value;
myMessage.classList.add("displayblock");
return false;
}
};
If you are going to use a linter, you need to follow what ever rules you have applied. You need to move the vars before you touch the variables. You need to indent right. Set up your IDE with plug ins that will format your code for you.
window.onload = function () {
"use strict";
var myLogin = document.forms.submitForm;
var myName = document.getElementById("result__username");
var myPassword = document.getElementById("result__password");
var myMessage = document.getElementById("output");
myMessage.classList.add("displaynone");
myLogin.onsubmit = processForm;
function processForm() {
var in_username = myLogin.username;
var in_password = myLogin.password;
if (in_username.value === "") {
in_username.classList.add("changered");
in_username.focus();
return false;
}
in_username.classList.add("changewhite");
if (in_password.value === "") {
in_password.classList.add("changered");
in_password.focus();
return false;
}
in_password.classList.add("changewhite");
myName.innerHTML = in_username.value;
myPassword.innerHTML = in_password.value;
myMessage.classList.add("displayblock");
return false;
}
};

Why function name as variable?

While studying Element.scrollHeight i failed to understand 2 things. The code example is as described below:
function checkReading () {
if (checkReading.read) {
return;
}
checkReading.read = this.scrollHeight - Math.round(this.scrollTop) === this.clientHeight;
document.registration.accept.disabled = document.getElementById("nextstep").disabled = !checkReading.read;
checkReading.noticeBox.textContent = checkReading.read ? "Thank you." : "Please, scroll and read the following text.";
}
onload = () => {
const oToBeRead = document.getElementById("rules");
checkReading.noticeBox = document.createElement("span");
document.registration.accept.checked = false;
checkReading.noticeBox.id = "notice";
oToBeRead.parentNode.insertBefore(checkReading.noticeBox, oToBeRead);
oToBeRead.parentNode.insertBefore(document.createElement("br"), oToBeRead);
oToBeRead.onscroll = checkReading;
checkReading.call(oToBeRead);
}
Why they have used checkReading(which is a function name) as object/variable?
I tried to remove checkReading and used oToBeRead object as this, so when i used this.reading = this.scrollHeight - Match.round(this.scrollTop)===this.clientHeight
the function checkReading is converted to constructor function,
why so?
here's my updated code where the function is converting to constructor function:
function checkReading () {
if (checkReading.read) {
return;
}
this.read = this.scrollHeight - Math.round(this.scrollTop) === this.clientHeight;
document.registration.accept.disabled = document.getElementById("nextstep").disabled = !this.read;
this.noticeBox.textContent = checkReading.read ? "Thank you." : "Please, scroll and read the following text.";
}
onload = () => {
const oToBeRead = document.getElementById("rules");
oToBeRead.noticeBox = document.createElement("span");
document.registration.accept.checked = false;
oToBeRead.noticeBox.id = "notice";
oToBeRead.parentNode.insertBefore(checkReading.noticeBox, oToBeRead);
oToBeRead.parentNode.insertBefore(document.createElement("br"), oToBeRead);
oToBeRead.onscroll = checkReading;
checkReading.call(oToBeRead);
}
This picture is showing how the function is converted to constructor function and then quokka is giving tip to change it to class declaration

Evaluating JavaScript expression with a worker

I need to evaluate JavaScript expressions, in a browser, Chrome. To make it safe, I use a Blob and a Worker running my evaluator, until it posts back the result of a timeout cancels the wait. This is working fine. I also need to support an environment for my JavaScript. I do this as below:
function evalWorker () {
let postResponse = function(expr, ...) {
let presets = `var EnvObject = {};
EnvObject.platform = "Chrome";
EnvObject.pasteboard = "${clipboard}";
EnvObject.baseDate = new Date();
...
EnvObject._output = "";
EnvObject.appendOutput = (str) => {EnvObject._output += str; };
`
postMessage(eval(presets + expr));
};
onmessage = function(e) {
postResponse(e.data['expression'], e.data['clipboard'], ...);
}
}
My problem is that if _output is not empty, I need to return that - _output instead of the evaluated expression, as in
EnvObject.appendOutput('hello');
var a = 0;
++a;
Should return hello; while without appendOutput, it should return 1.
How would I go about something like this?
#Bergi had the right idea with pushing the scope out. The below works.
function evalWorker () {
let postResponse = function(expr, TextExpander) {
let result = eval(expr);
if (EnvObject._output && EnvObject._output.length) {
postMessage(EnvObject._output);
} else {
postMessage(result);
}
};
onmessage = function(e) {
var EnvObject = {};
EnvObject.platform = "Chrome";
EnvObject.pasteboardText = e.data['clipboard'];
...
EnvObject._output = "";
EnvObject.appendOutput = function(str) {EnvObject._output += str; };
postResponse(e.data['expression'], EnvObject);
}
}

Generic function?

I'm trying to figure out the answer to this question:
Without using Javascript's bind function, implement the magic function so that:
var add = function(a, b) { return a + b; }
var addTo = add.magic(2);
var say = function(something) { return something; }
var welcome = say.magic('Hi, how are you?');
addTo(5) == 7;
welcome() == 'Hi, how are you?';
I think I need to use call or apply but I just don't know, if someone could point me in the right direction or provide some literature it would be much appreciated.
You can use closure, and apply function
Function.prototype.magic = function(){
var self = this;
var args = Array.from(arguments);
return function(){
return self.apply(null, args.concat(Array.from(arguments)));
}
}
var add = function(a, b) { return a + b; }
var addTo = add.magic(2);
var say = function(something) { return something; }
var welcome = say.magic('Hi, how are you?');
console.log(addTo(5) == 7);
console.log(welcome() == 'Hi, how are you?');
Also you can look to Polyfill for bind function on MDN
Please see below code:
Object.prototype.magic = function (message) {
alert(message);
}
var add = function (a, b) { return a + b; }
var addTo = add.magic(2);
var say = function (something) { return something; }
var welcome = say.magic('Hi, how are you?');
addTo(5) == 7;
welcome() == 'Hi, how are you?';

Writing a function to set some but not necessarily all parameters in another function

I had a coding interview test that asked the following question which I was not able to fully solve. I'm wondering the best way to do this following my approach -- also sorry this is long.
You are given a function to read in like this (not necessarily 2 parameters):
function add(a, b) {
return a + b;
}
The objective is to create a function to initialize some of those variables and again call the function to perform the calculation like, function setParam(func, params). To use this you would do the following:
_add = setParam(add, {b:9})
_add(10) // should return 19
My solution was to parse the function to see how many parameters there are, then set them using the given parameters but since I barely know javascript I was never able to actually return a function with only some variables set and others still undefined.
(attempt at solution)
function setParam(func, params) {
// varray is an array of the the varriables from the function, func
// ie varray = [a,b] in this test
var varray = /function[^\(]*\(([^\)]*)\)/.exec(func.toString())[1].split(',');
//creates an array, paramset, that has the variables in func defined
//where possible
// ex paramset = [a,9] if only b was set
var paramsset = []
for (i = 0; i < varray.length; i++) {
if (typeof(params[varray[i]]) == "undefined"){
paramsset[i] = varray[i];
} else {
paramsset[i] = params[varray[i]];
}
}
//////
// need to modify existing function and return with added parameters
// where I'm stuck as this doesn't work.
newfunc = (function(){
var _func = func;
return function() {
return _func.apply(this, paramsset);
}
})();
newfunc()
}
I'm sure I'm not doing this the correct way, but any help would be appreciated.
I'm certainly not advocating to go towards that solution, but I still implemented something to follow your initial's API design for fun. The signatures weak map is necessary in order to preserve the initial function's signature so that we can call setParams again on partially applied functions.
var setParams = (function () {
var signatures = new WeakMap();
return function (fn, paramsToApply) {
var signature = signatureOf(fn), newFn;
validateParams(paramsToApply, signature.params);
newFn = function () {
var params = appliedParamsFrom(arguments, paramsToApply, signature.indexes);
return fn.apply(this, params);
};
signatures.set(newFn, signature);
return newFn;
};
function signatureOf(fn) {
return signatures.has(fn)?
signatures.get(fn) :
parseSignatureOf(fn);
}
function parseSignatureOf(fn) {
return String(fn)
.match(/function.*?\((.*?)\)/)[1]
.replace(/\s+/g, '')
.split(',')
.reduce(function (r, param, index) {
r.indexes[param] = index;
r.params.push(param);
return r;
}, { indexes: {}, params: [] });
}
function validateParams(paramsToApply, actualParams) {
Object.keys(paramsToApply).forEach(function (param) {
if (actualParams.indexOf(param) == -1) throw new Error("parameter '" + param + "' could not be found in the function's signature which is: 'function (" + actualParams + ")'");
});
}
function appliedParamsFrom(args, paramsToApply, paramsIndex) {
var appliedParams = [],
usedIndexes = [],
argsIndex = 0,
argsLen = args.length,
argSpotIndex = 0;
Object.keys(paramsToApply).forEach(function (param) {
var index = paramsIndex[param];
appliedParams[index] = paramsToApply[param];
usedIndexes.push(index);
});
while (argsIndex < argsLen) {
if (usedIndexes.indexOf(argSpotIndex) == -1) {
appliedParams[argSpotIndex] = args[argsIndex++];
}
++argSpotIndex;
}
return appliedParams;
}
})();
function add(a, b) { return a + b; }
var addTo9 = setParams(add, { b: 9 });
var add10To9 = setParams(addTo9, { a: 10 });
document.write(addTo9(10) + ', ' + add10To9());
Now, note that JavaScript comes with the Function.prototype.bind function which allows to perform in-order partial function application. The first parameter to bind has nothing to do with arguments, it's to bind the this value.
function add(a, b) { return a + b; }
var addTo9 = add.bind(null, 9);
document.write(addTo9(10));
And finally, an implementation with a placholder if you need one:
var partial = (function (undefined) {
var PLACEHOLDER = {};
function partial(fn, partialArgs) {
return function () {
return fn.apply(this, applyPartialArgs(arguments, partialArgs));
};
}
Object.defineProperty(partial, 'PLACEHOLDER', {
get: function () { return PLACEHOLDER; }
});
return partial;
function applyPartialArgs(args, partialArgs) {
var appliedArgs = partialArgs.map(function (arg) {
return arg === PLACEHOLDER? undefined : arg;
}),
partialArgsLen = partialArgs.length,
argsLen = args.length,
argsIndex = 0,
argSpotIndex = 0;
while (argsIndex < argsLen) {
if (
partialArgs[argSpotIndex] === PLACEHOLDER ||
argSpotIndex >= partialArgsLen
) {
appliedArgs[argSpotIndex] = args[argsIndex++];
}
++argSpotIndex;
}
return appliedArgs;
}
})();
function add(a, b, c, d) {
return a + b + c + d;
}
var _ = partial.PLACEHOLDER;
var addTo9 = partial(add, [_, 5, _, 4]);
document.write(addTo9(5, 5));
I'm guessing that they might have been testing for knowledge of partial application. (not currying)
Edit: Edited based upon your comments. This is Crockford's curry function straight from his book.
function add(a, b) {
return a + b;
}
if (!Function.prototype.partial) {
Function.prototype.partial = function() {
var slice = Array.prototype.slice,
args = new Array(arguments.length),
that = this;
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i];
}
return function() {
return that.apply(null, args.concat(slice.apply(arguments)));
}
};
}
var example = add.partial(4);
console.log(example(10)); // output 14
console.log(example(20)); // output 24
var example = adder(4) assigns example to be function with a closure with a (in this case 4). When example is called like in the console.log, it will in effect be returning "the value of a when example was assigned, plus this new number."
Walkthrough of the partial() function:
Converts arguments to an array
returns a function gets passed the arguments given, which can be called later. It has a closure with the previously assigned arguments.

Categories

Resources