Using function in Javascript - javascript

Example:
function pcs()
{
var t1 = document.getElementById("tot1").value
var pb = document.getElementById("pcbox").value
var pc = ""
if (t1==! && pb==!)
{
document.getElementId("rbox").innerHTML = ""
}
}
My question is if t1 and pb are null the function pcs() is not called... Why?

The line
if(t1==! && pb==!)
is not legal syntax. If this is exactly how you have written the code it will not parse and thus the function will not be defined (plus you'll be getting Javascript errors).
Perhaps you meant
if(t1 != null && pb != null)
Additionally, while semicolons at the end of lines can be inferred by the interpreter, they are meant to be there (as opposed to being actually optional) and adding them is good practice.
EDIT and while I didn't understand your final question 100%, remember that the code you've written (assuming the syntax were correct) merely defines a function. You will need to have some other code call this function at an appropriate point in order to have it executed, e.g. for some element onblur = pcs();

The line if(t1==! && pb==!) is nonsense - did you mean if (!t1 && !pb)?

if(t1==! && pb==!) --> this is absolutly wrong.... What are you trying to check?
Maybe if(t1!="" && pb!="")?

Related

shorten javascript code - check if property exists and is not empty [duplicate]

This question already has answers here:
Test for existence of nested JavaScript object key
(64 answers)
Closed 6 years ago.
Is it possible to shorten this code?
var access_followup = user_access && user_access.followup && user_access.followup.access ? true : false;
Unfortunately JS does not have a null conditional operator. You could write helper function for it or use a slightly less effective method of creating dummy objects:
var access_followup = !!((user_access || {}).followup || {}).access;
which is shorter and prevents using the property names more than once, but doesn't improve readability. The !! is used to enforce a boolean value even when the values don't exist
Maybe I am answering the wrong thing, but why would you want to make it shorter? I'd vote to make it a bit longer, but easier to read for people who work with your code ( including you :) ).
You could make it more readable by splitting it up into multiple lines:
var access_followup = (
user_access &&
user_access.followup &&
user_access.followup.access === true // if access is a boolean value
);
Or, in case you really really want to have short code and you do not use a minifier already, you can try https://jscompress.com/ (which actually compresses any code you paste into it! but makes it WAY less readable).
If the first 2 checks are because you are protecting against exception thrown when user_access.followup is undefined, you can try this:
var accessFollowup;
try {
accessFollowup = !!user_access.followup.access;
} catch (e) {
accessFollowup = false;
}
You could also shorten by removing just the ternary by using !! to force last element into Boolean value:
var access_followup = !!user_access && !!user_access.followup && !!user_access.followup.access
very ugly code that works
var access_followup = (followup = (user_access || {}).followup) && followup.access;

Unexpected '.' from wrapped expression to chain

I have this method that is calculating a total, and part of it is giving a warning in JS Lint. We're trying to get cleaner JS Lint inspections at work, so I want to see if there's a rational way to get around this that I'm not thinking of.
calculateTotal = function() {
var hours = parseFloat($hours.val());
var rate = parserFloat($rate.val());
var total = '';
if (!isNaN(hours) && !isNaN(rate)) {
// This throws the error.
total = (rate * hours).toFixed(2);
}
$total.val(total);
}
I can avoid the message if I do the following:
total = rate * hours;
total = total.toFixed(2);
It's a little too verbose for me to just jump at it, but it may be the best bet.
I checked out this question, and considered doing Number(rate * hours).toFixed(2), but that's (marginally) less performant, plus it would be a bad precedent to start with all of the warnings about using String() as stated in response to the accepted answer there.
This could be moot if my above attempt is the best way to get JS Lint to stop complaining, but I would like to hear from other people.
TL;DR
JSLint is going to force you to move the toFixed() from behind of the parentheses. I'd suggest the least annoying place to move it is in the $total.val(total) assignment.
This lints as-is on JSLint.com:
/*jslint white:true, browser:true */
/*global $hours, $rate, $total */
var calculateTotal = function() {
"use strict";
var hours = parseFloat($hours.val());
var rate = parseFloat($rate.val());
var total;
if (!isNaN(hours) && !isNaN(rate)) {
// This throws the error.
total = rate * hours;
}
$total.val(total.toFixed(2)); // moved `toFixed` to here
};
A little longer...
I tried it against the most recent version of JSLint, and it's borking at left_check in JSLint's code, here:
function left_check(left, right) {
// Warn if the left is not one of these:
// e.b
// e[b]
// e()
// identifier
var id = left.id;
if (
!left.identifier &&
(
left.arity !== "binary" ||
(id !== "." && id !== "(" && id !== "[")
)
) {
warn("unexpected_a", right);
return false;
}
return true;
}
left is essentially (rate & hours) and right is . with toFixed the next token in this case.
As dangerous as it is to assume code function from comments, I think the comments tell us where JSLint is coming from -- It wants methods called only on objects, not on operations, including type coercions that often occur inside of them. It pretty much has to let you make "fluent" calls, where you chain methods, and the only valid things that can have method calls are...
an object: e
A property of an object: e.b
A property in a collection: e[key]
The return value of a function: e()
Just to double check, since your construction used to work in "old JSLint" (the last version before JSLint for ES6), I asked Douglas Crockford. He's pretty terse, but he did confirm JSLint is working as intended.
Sorry I can't be more help there. I think there are places where (someExpression).someMethod() is expedient, but understand where JSLint's coming from too. If you're going to have the potential for type coercion, coerce explicitly.
Interesting question; thanks for asking.

JavaScript Short Circuit Logic

After seeing some examples online, I've collected two different explanations:
Ex: var x = A || B;
If A exists and B does not, left side is returned.
If A exists and B exists , return right side (last evaluated value).
Based on that logic, I would assume that x would return: v.item(0).click(). But when testing it x first returned B then A, aka fired B then fired A as well. Why? (http://jsfiddle.net/nysteve/QHumL/59/)
HTML:
<div class="indeed-apply-button" onclick="alert('BOOM BUTTON');">boo</div>
<div class='view_job_link' onclick="alert('BOOM LINK');">boo</div>
JavaScript
var v = document.getElementsByClassName('view_job_link');
var i = document.getElementsByClassName('indeed-apply-button');
var x = v.item(0).click() || i.item(0).click();
EDIT 1:02 PM 10/10/2013
Did not mention my true intentions, but based on the answer and discussion, my goal was essentially to convert the following piece of code into the JavaScript code I originally mentioned.
var v = document.getElementsByClassName('view_job_link');
var i = document.getElementsByClassName('indeed-apply-button');
if(v){v.item(0).click();}
else if(i){i.item(0).click();}
else{}
In the code above, how would you read if(v){v.item(0).click();} vs. the short-circuit?
Neither of your two descriptions are accurate.
var x = A || B;
What that does is:
Evaluate "A". Call the result VA.
If VA is not null, undefined, 0, NaN, false, or the empty string, then the value of the overall expression is VA and evaluation stops.
Evaluate "B". Call the result VB. That value, VB, is the value of the expression.
Your test code first tests the return value of calling the "click" function on the first element and then the second. Those functions both return undefined, so the subexpressions on both sides of the || are evaluated. That is, the first call gets VA and it's undefined, so that means that the other side will be evaluated too, and that'll be the value of the expression. (It's going to come out undefined.)
edit — OK now that you've added more to the answer, I think I see what you're up to.
In your actual code (or, I guess, the sample code that's closer to reality), you've got:
if(v){v.item(0).click();}
else if(i){i.item(0).click();}
else{}
That means something quite different than:
var x = v.item(0).click() || i.item(0).click();
Note that in the if statement version, it's explicitly checking "v". A test like that will perform a "truthy/falsy" test on the value of "v". In this case, it's really checking to make sure that "v" isn't either null or undefined. In the || version, however, there's no such explicit test for the "goodness" of variable "v"; it's just used directly. (If it happens to be null there, that'd result in a runtime error.)
A version of the actual code using || and && is possible, but in my opinion the existing code is clearer. However, just for discussion purposes, you could replace the if version with:
v && (v.item(0).click(), true) || i && i.item(0).click();
Personally I think that looks kind-of ugly.

does object/array exist in javascript

I'm trying to put content from RSS feed - problem is every RSS feed has different formats for images, content etc.
I'm trying to see if certain object exists in javascript or jquery:
item.mediaGroups[0].contents[0].url
How can I check it in an if statement? I keep getting for feeds without this structure:
Uncaught TypeError: Cannot read property '0' of undefined
Also tried:
if (typeof item.mediaGroups[0].contents[0].url === "undefined")
but I keep getting the same error.
thanks!
There is no "simple" built in way to do this sort of in depth checking. The reasoning is simple - most of the time you know the type of the objects you're working against.
You can do:
if (typeof item !== "undefined" &&
typeof item.mediaGroups !== "undefined" &&
typeof item.mediaGroups[0] !== "undefined" &&
typeof item.megiaGroups[0].contents !== "undefined" &&
typeof item.megiaGroups[0].contents[0] !== "undefined" &&
typeof item.mediaGroups[0].contents[0].url !== "undefined"){
When you type all that you might want to consider your data structures, since this really is not a situation you should be in to begin with :)
(hint, you can skip the typeof on all but the first, but I think typeof is a good clarification here).
The real question is this:
Why are you not sure what the structure of your data is?
If you are querying data (for example XML in an RSS feed) there are effective ways to do so with XPATH or query selectors. Object property access is built for objects where what you're querying is a document. Sure, it's possible with a bunch of ugly checks just like you can hammer a nail in with a heavy screwdriver.
You can see this question in Stack Overflow on how to use DOM methods to parse XML.
If you're uncertain about the exisence of properties, try this helper function:
function getProperty(root) {
var l = arguments.length, i, undefined;
for( i=1; i<l; i++) {
if( typeof root[arguments[i]] == "undefined") return undefined;
root = root[arguments[i]];
}
return root;
}
You can then call it like this:
var url = getProperty(item,'mediaGroups',0,'contents',0,'url');
As a more "haxy" way, you can try this:
try {url = item.mediaGroups[0].contents[0].url;}
catch(e) {url = undefined;}
I would check the length of both arrays in this case to be sure - before assuming there are objects defined at index 0
item.mediaGroups.length > 0
and
item.mediaGroups[0].contents.length > 0
As the outer check you can also throw in a
if(item.mediaGroups){
}
How about 'optional chaining' (described in ES2021 spec and already implemented in all browsers except three) ?
from MDN:
The optional chaining operator provides a way to simplify accessing
values through connected objects when it's possible that a reference
or function may be undefined or null.
The optional chaining ?. stops the evaluation if the value before ?. is undefined or null and returns undefined so it is giving us a way to handle the possibly undefined/nullsish values
item?.mediaGroups[0]?.contents[0]?.url // will evaluates to undefined if either of those is undefined.
item.mediaGroups[0].contents is undefined, you have to check for it.
if(item.mediaGroups && item.mediaGroups[0].contents) {
return item.mediaGroups[0].contents[0].url;
}
It's not a solution with if-statements (as requested), but you can use exceptions to achieve similar functionality. Something like this:
function throwOrReturn(thing){
if(typeof thing === 'undefined'){
throw "Didn't find it..."
}else{
return thing
}
}
// The unknown thing.
var a = {
b1: {
},
b2: {
c: 'lookingFor'
}
}
var c
// Test our different paths.
try{
// First guess.
c = throwOrReturn(a.b1.c.d)+" - a.b1.c.d"
}catch(error){
try{
// Second guess.
c = throwOrReturn(a.b[45][34].c)+" - a.b[45][34].c"
}catch(error){
try{
// Third guess.
c = throwOrReturn(a.b2.c)+" - a.b2.c"
}catch(error){
// Try more guesses, or give up.
c = "notFound"
}
}
}
console.log("c:", c) // Logs: "c: lookingFor - a.b2.c"
It ain't pretty, but it's an alternative worth to mention.

How can I speed up this bit of JSON date parsing?

I am stuck using an AJAX library from about 5 years ago in this project, and it had some issues with parsing dates in JSON. I wound up rewriting its parse function to use a single regex:
return eval('(' + (enableDateParsing ? text.replace(/"(?:\\)?\/Date\((.*?)\)(?:\\)?\/"/g, "new Date($1)") : text) + ')');
This works really well, but I thought I could get a speed up if I used native JSON parsing in IE8 / chrome / ff, so I added this bit:
if (typeof JSON !== 'undefined' && typeof JSON.parse !== 'undefined') {
var nativeJsonDateParseRegex = /\/Date\(.*?\)\//g;
return JSON.parse(text, function (key, value) {
if (AjaxPro.enableDateParsing && typeof value === 'string' && value.match(nativeJsonDateParseRegex))
{
value = new Date(parseInt(value.substr(6)));
}
return value;
});
}
else // revert to eval for ie6/ie7
The reviver callback will execute once for each JSON property returned, so it has to be very fast. During a profile I've seen it's been called 170484 times, but still runs pretty fast (131.237ms). Any ideas on how to make it faster, or is this the best you can do without serious tweaking?
Your code contains a lot of constant conditions, you'll be fine with checking once whether native JSON is supported or not.
Suggestions:
check for native JSPN support at page load, and add the right function accordingly.
Drop the global flag from the regex if you do not need it
Drop regular expressions if possible, if every date always starts with "/Date(", search for it. It's much faster (see benchmark at jsperf.com)
todo: check whether parseInt can be replaced with an other method to get rid of the trailing )/.
If AjaxPro.enableDateParsing is a constant, you can remove if from AjaxPro.jsonParse and and make it a condition like the check for native JSON
Code without RE:
if (typeof JSON !== 'undefined' && typeof JSON.parse !== 'undefined') {
AjaxPro.nativeJsonDateParseRegex = /\/Date\(.*?\)\//g;
AjaxPro.dateFunc = function(key, value) {
if (typeof value === "string" && !value.indexOf("/Date(")) {
return new Date(value.substring(6, value.length-2));
}
return value;
};
AjaxPro.jsonParse = function(text) {
if (AjaxPro.enableDateParsing) {
return JSON.parse(text, AjaxPro.dateFunc);
}
return JSON.parse(text);
};
} else // revert to eval for ie6/ie7
This should be highly optimized. You might want to run some more test on your own in multiple browsers. Maybe checking for a property of a string is faster than checking its type (doubt it), thing like that.
One not so good microoptimization, but still worth giving a try.
Since your substring contains millisecond timestamp only, and no other garbage string.
You can remove the call to parseInt.
You can try typecasting with simple mathematical operation like multiplication with 1.
Might save some time if you are too keen on microoptimizations.
value = new Date(1*(value.substr(6)));
example:
a = "a:3333";
b = a.substring(2);
alert(b*2); // alerts 6666

Categories

Resources