Break on NaN in JavaScript - javascript

Is there any modern browser that raises exceptions on NaN propagation (ie multiplying or adding a number to NaN), or that can be configured to do so?
Silent NaN propagation is an awful and insidious source of bugs, and I'd love to be able to detect them early, even at a performance penalty.
Here's an example bug that use strict, jshint et al. wouldn't pick up:
object = new MyObject();
object.position.x = 0;
object.position.y = 10;
// ... lots of code
var newPosition = object.position + 1; // <- this is an error, and should
// have been object.position.x
// however it fails *silently*,
// rather than loudly
newPosition *= 2; // <- this doesn't raise any errors either.
// this code is actually ok if the
// previous line had been correct
Note: The TypeScript compiler is able to detect errors like the above, even in JS code, if type inference succeeds.

To answer the question as asked:
Is there any modern browser that raises exceptions on NaN propagation (ie multiplying or adding a number to NaN), or that can be configured to do so?
No. Javascript is a very forgiving language and doesn't care if you want to multiply Math.PI by 'potato' (hint: it's NaN). It's just one of the bad parts (or good parts, depending on your perspective) about the language that us developers have to deal with.
Addressing the bug that has you asking this question (presumably), using getters and setters on your Objects is one solid way to enforce this and also keep you from making mistakes like this.

Code below might help you.
To solve this problem fully, I think we need something like operator reload. We can reload operators like '+ - / *', and check if the operand is number, if not, then throw Error.
As a partial solution, when JavaScript does an operation like 'a + b', it will call the valueOf method which inherits from Object.prototype, we can rewrite Object.prototype.valueOf.
Object.prototype.originalValueOf = Object.prototype.valueOf;
Object.prototype.valueOf = function() {
if (typeof this !== 'number') {
throw new Error('Object is not a Number');
}
return this.originalValueOf();
}
var a = 1 + 2; // -> works
console.log(a); // -> 3
var b = {};
var c = b + 2; // -> will throw an Error
(hint: You can remove the code in production, and add it into your developing environment.)

the cleanest way to do that is having a short handy function that validates the expression's result every time
i know that's not the answer you are looking for but this is the javascript's nature and you can't change it sadly
function v(a){ if(isNaN(a)) throw "error"; return a; }
var test = v(100 * "abc");

I know this is an old thread but I think there may be a super simple answer to your question. You can either create a function for the below statement or add it inline.
JavaScript has some unique behaviors for certain values. One of these unique behaviors revolves around the not-a-number value or NaN. The value of NaN will not compare equal to any other value including NaN itself. For this reason the following statement:
if(x != x) {
throw "Value is NaN!";
}
will hold true if and only if the value of x is NaN.

I think this is a situation where getter and setter comes in handy.
Following is a psuedo code example just to give you an idea.
//Inside your Object class code.
function getPosition() {
//You don't want the property "position" to be NaN, right?
if(isNaN(this.position))
throws "NaN is not a correct numerical value!";
return this.position;
}
//Somewhere in your code
var newPosition = object.getPosition() + 1; //raises an exception.
I think this is better than implementing fake operator overloading and make things more complicated.

Related

Monitor and log NaN values in JavaScript/TypeScript during runtime?

Is there any way to detect - or safely guard against - NaN values during runtime, across any part of the application where these might appear?
A) Is there a safe linting to warn about potential NaN values that might occur in certain constructs?
B) Alternatively, some kind of solution that monitors the executed JavaScript during runtime, detects and logs or alerts about it? - Similar to how error detection services work?
Example
Pseudo-code of a scenario where testing for NaN might be hard:
function undetectedNaN (): AssumeStrictDataTypes {
// 1. Some algorithm ...
// 2. NaN appears undetected ...
// 3. Some algorithm ...
// 4. Return: Broken but seeming legit value and data type
}
(Assume that it's in a larger application codebase, where adding checks for isNaN() and validating individual values is not an option: It might be too costly, not a requirement, no automated testing possible etc. ...)
UPDATE 2021/12: To complement my rather abstract question: In a more practical use case, API values did not exist in an array structure. Most occurrences of NaN could be solved by better value/type checking.
function example (a, b) {
return a[0] + b[0]
}
// undefined + undefined = NaN
const result = example([], []);
console.log(result);
Some other possibilities of NaN occuring:
const testArray = [];
const testObject = {};
testArray[0] + testArray[0] // NaN
testObject.X + testObject.X // NaN
undefined + undefined // NaN
NaN + NaN // NaN
Other places where NaN might be harder to track:
e.g. if it appears during runtime, somewhere, sometimes, and is not a testable return value.
// Bitwise operators
~(NaN) // -1
// Conditionals
if (NaN > 1) {} // false
// Typecasting
!!NaN // false
There is no simple way to achieve this.
There is no easy way of detecting this statically (for a linter). NaN can be a result from simple operations like multiplication and division, so it could occur anywhere.
Of course it would be technically possible to detect expressions that always evaluate to NaN, such as if you were to type 0/0. But this is probably not what you're looking for.
To my knowledge there is no framework that can detect NaN occuring somewhere at runtime. I believe that to achieve this in the way that you want, you would need support for it at JS engine level.
You could invent hacky solutions like creating functions for arithmetic operations like multiply or wrap numbers in objects that override the valueOf() function. But none of them will work in every case and they make your code a lot less pleasant.
In the end NaN is a perfectly valid number. You would detect it like you would detect any other value. For example, if your algorithm couldn't handle negative numbers, you also couldn't bend the language so it tells you when you have negative numbers. Instead you would have to design your code in such a way that negative values don't occur or you write a lot of checks/assertions.

Comparison with possibly non-existent properties

My background is more in strongly-typed languages than not, so I will state up front that I have a bias against treating undefined objects in a casual manner. That said, I was considering a simple question of assigning a Boolean value to a variable, where said Boolean comes from the property of some object, and while the object will always exist the property may not.
That sounds more complicated than it really is. Take a look. We start with spinning up some objects early in the code, covering the three possible scenarios:
var object1 = {};
object1.IsDisplayed = true;
var object2 = {};
object2.IsDisplayed = false;
var object3 = {};
// notice we do *not* create the IsDisplayed property here
Sometime later we call the process() function that takes a single argument. Let's call this baseline Solution A.
Solution A
This being JavaScript, that actually works as expected for object1, object2, and object3. But it seems to have a bit of a code smell to me; it is not clear that the author has considered a possibly non-existent property.
function process(renderedItem) {
var rendered = renderedItem.IsDisplayed;
if (rendered) {
// do some stuff here
}
}
I see two possible ways to make this more robust:
Solution B
I like this solution because it is both robust and clear to even the most casual reader that the undefined case has been properly considered. On the downside it is wordy, not nearly as compact as solution C, and it uses a string name of a property, which I have a strong distaste for.
function process(renderedItem) {
var rendered = renderedItem.hasOwnProperty('IsDisplayed')
? renderedItem.IsDisplayed
: false;
if (rendered) {
// do some stuff here
}
}
Solution C
I like this solution because it is robust and compact; it explicitly takes into account a possibly non-existent property; however, it is not nearly as obvious as solution B. I remember early on reading some colleagues' code and thinking,"What the heck?" and suggested deleting the === true as redundant. Also, it still is technically referencing an undefined value (in the case of passing in object3).
function process(renderedItem) {
var rendered = renderedItem.IsDisplayed === true;
if (rendered) {
// do some stuff here
}
}
Is there a clear "best practice" amongst these three variations?

Security considerations using "new Function(...)" (during rendertime, expression coming from my Javascript sources)

I'd like to use new Function(...) to generate a function from very reduced code. I'l like to do this to
avoid parsing the expression on my own and
being as flexible as possible.
I avoid eval() whenever possible. But I'm not sure if it's secure enough to use new Function(...) which is also known as being liable to security holes.
Background
I want to manage the states of menu buttons. So, while defining the buttons, I'd like to write something like
{
..., // More button definition
state: "isInEditmode && (isWidgetSelected || isCursorInWidget),
...
}
While handling the statechange during several events I'll check (summarize) the states of the current overall state object against those in the states attribute.
So I'll generate a Function during rendertime and attaching it as a DOM object attribute, not DOM attribute this way:
...
$el.stateFn = new Function("stateObj", "with (stateObj) {return " + item.state + ";}");
...
Testing state:
visible = $el.stateFn.call(currentStates, currentStates);
The with statement helps me providing the current state object's attributes as variables so that the above expression does not need something like obj.isInEditmode.
Security question
In my opinion this does not introduce security holes as the function attached to the DOM object is generated during render time and read from source. Or am I wrong? Should I avoid this?
Performance hints are appreciated (comment) (I think as long as I evaluating a new Function once during render time, this is acceptable).
Edit 1
I'm using Backbone.js. Using another Framework is out of question.
Some menu items need to be bound to different or even multiple models.
Delegation (or facade / proxy?) models are considerable.
Security-wise both are just as bad if user input is allowed to break out in the code. However, maintenance wise you don't have to worry about hidden bugs when local eval messes with your scope and causes dynamic scoping.
Performance-wise the function generated by new Function is exactly the same as any other function. The generation is slower but inlike eval it doesn't cause the containing scope to be unoptimizable.
In fact, new Function can be used to improve performance in situations like:
//Will behave like function a( obj ) { return obj.something }
function makePropReader( propName ) {
return new Function( "obj", "return obj." + propName );
}
The constructed function will perform better than the function returned here:
function makePropReader( propName ) {
return function( obj ) {
return obj[propName];
}
}
Due to having to dynamically read propName from closure context and do a dynamic read on the object everytime it is called.
Please never ever use eval no matter what. There is a much better alternative. Instead of eval, use the Function constructor. eval is evil, and there's no question about that, but most people skip over the most evil aspect of eval: it gives you access to variables in your local scope. Back in the 90s, back before the concept of JIST compilation, eval sounded like a good idea (and it was): just insert some additional lines dynamically into the code you're already executing line-by-line. This also meant that evals didn't really slow things down all. However, now-a-days with JIST compilation eval statements are very taxing on JIST compilers which internally remove the concept of variable names entirely. For JIST compilers, in order to evaluate an eval statement, it has to figure out where all of its variables are stored, and match them with unknown globals found in the evaled statement. The problem extends even deeper if you get really technical.
But, with Function, the JIST compiler doesn't have to do any expensive variable name lookups: the entire code block is self-contained and in the global scope. For example, take the following terribly inefficient eval snippet. Please note that this is only for the purpose of being an example. In production code, you shouldn't even be using eval or Function to generate a function from a string whose content is already known.
var a = {
prop: -1
};
var k = eval('(function(b){return a.prop + b;})');
alert( k(3) ); // will alert 2
Now, let's take a look at the much better Function alternative.
var a = {
prop: -1
};
var k = (Function('a', 'b', 'return a.prop + b')).bind(undefined, a);
alert( k(3) ); // will alert 2
Notice the difference? There is a major one: the eval is executed inside the local scope while the Function is executed inside the global one.
Now, onto the next problem: security. There is a lot of talk about how security is difficult, and yes, with eval it is pretty much impossible (e.x. if you wrap the whole code in a sandboxing function, then all you have to do is prematurely end the function and start a new one to execute code freely in the current scope). But, with Function, you can easily (but not the most efficiently) sandbox anything. Look at the following code.
var whitelist = ['Math', 'Number', 'Object', 'Boolean', 'Array'];
var blacklist = Object.getOwnPropertyNames(window).filter(function(x){
return whitelist.indexOf(x) === -1 && !/^[^a-zA-Z]|\W/.test(x)
});
var listlen = blacklist.length;
var blanklist = (new Array(listlen+1)).fill(undefined);
function sandboxed_function(){
"use-strict";
blacklist.push.apply(blacklist, arguments);
blacklist[blacklist.length-1] =
'"use-strict";' + arguments[arguments.length-1];
var newFunc = Function.apply(
Function,
blacklist
);
blacklist.length = listlen;
return newFunc.bind.apply(newFunc, blanklist);
}
Then, fiddle around with the whitelist, get it just the way you want it, and then you can use sandboxed_function just like Function. For example:
var whitelist = ['Math', 'Number', 'Object', 'Boolean', 'Array'];
var blacklist = Object.getOwnPropertyNames(window).filter(function(x){
return whitelist.indexOf(x) === -1 && !/^[^a-zA-Z]|\W/.test(x)
});
var listlen = blacklist.length;
var blanklist = (new Array(listlen+1)).fill(undefined);
function sandboxed_function(){
"use-strict";
blacklist.push.apply(blacklist, arguments);
blacklist[blacklist.length-1] =
'"use-strict";' + arguments[arguments.length-1];
var newFunc = Function.apply(
Function,
blacklist
);
blacklist.length = listlen;
return newFunc.bind.apply(newFunc, blanklist);
}
var myfunc = sandboxed_function('return "window = " + window + "\\ndocument = " + document + "\\nBoolean = " + Boolean');
output.textContent = myfunc();
<pre id="output"></pre>
As for writing code to be runned under this strict sandbox, you may be asking, if window is undefined, how do I test for the existence of methods. There are two solutions to this. #1 is just simply to use typeof like so.
output.textContent = 'typeof foobar = ' + typeof foobar;
<div id="output"></div>
As you can see in the above code, using typeof will not throw an error, rather it will only just return undefined. The 2nd primary method to check for a global is to use the try/catch method.
try {
if (foobar)
output.textContent = 'foobar.constructor = ' + foobar.constructor;
else
output.textContent = 'foobar.constructor = undefined';
} catch(e) {
output.textContent = 'foobar = undefined';
}
<div id="output"></div>
So, in conclusion, I hope my code snippets gave you some insight into a much better, nicer, cleaner alternative to eval. And I hope I have aspired you to a greater purpose: snubbing on eval. As for the browser compatibility, while the sandboxed_function will run in IE9, in order for it to actually sandbox anything, IE10+ is required. This is because the "use-strict" statement is very essential to eliminating much of the sneaky sand-box breaking ways like the one below.
var whitelist = ['Math', 'Number', 'Object', 'Boolean', 'Array'];
var blacklist = Object.getOwnPropertyNames(window).filter(function(x){
return whitelist.indexOf(x) === -1 && !/^[^a-zA-Z]|\W/.test(x)
});
var listlen = blacklist.length;
var blanklist = (new Array(listlen+1)).fill(undefined);
function sandboxed_function(){
blacklist.push.apply(blacklist, arguments);
blacklist[blacklist.length-1] =
/*'"use-strict";' +*/ arguments[arguments.length-1];
var newFunc = Function.apply(
Function,
blacklist
);
blacklist.length = listlen;
return newFunc.bind.apply(newFunc, blanklist);
}
var myfunc = sandboxed_function(`return (function(){
var snatched_window = this; // won't work in strict mode where the this
// variable doesn't need to be an object
return snatched_window;
}).call(undefined)`);
output.textContent = "Successful broke out: " + (myfunc() === window);
<pre id="output"></pre>
One last final comment is that if you are going to allow event API's into your sandboxed environment, then you must be careful: the view property can be a window object, making it so you have to erase that too. There are several other things, but I would recommend researching thoroughly and exploring the objects in Chrome's console.
Lastly, note that Function is a very unique constructor which returns a function instead of an object instance, so there's no need to use new.
Old thread with answers considered dangerous these days.
new Function() still allows access to global variables. So an adversary, when given the chance to effect the function string - which is usually the very reason for considering new Function and hard to guarantee it can't be done maliciously -, can read and modify any global. Good luck from that point on :-)
Which is why new Function falls under the same category as eval from the viewpoint of CSP (Content Security Policy) as mentioned here.
Example:
a = 10
> 10
b = new Function('a = 20; return 42')
> function(...)
a
> 10
b()
> 42
a
> 20
As you have said that you will only be doing this on code you wrote yourself - I'd say that it's fine. new Function() is definitely better than using eval() in any case. You won't be messing with any local variables and you're enforcing your own context by using fn.call.
It seems to me that the problem you are trying to solve would be fairly straight forward if you were using an MVC or MVVM framework that supports 2 way data binding. I.e. changing the UI updates a backing model and updating the model will automatically refresh the UI for you.
For example, knockout.js. In this case the visible databinding would be appropriate.

Why is it good practice to use if (myBoolean === true) in JavaScript? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
As a follow-up to this question: Is there ever a reason to write "if (myBoolean == true)" in a JavaScript conditional? -
Why is it good practice to use if (myBoolean === true) in JavaScript? As a relatively inexperienced JavaScript user, I'm trying to work out in what specific, real-world scenarios you'd end up with a value that might be a Boolean true or might be a "truthy" value, so that you would need to check if (myBoolean === true) rather than if (myBoolean)
I'll challenge the premise of the question: I don't think it's good practice, nor do I think there's a general consensus that it is. :-)
The only reason for using === true would be if you weren't sure that myBoolean was actually a boolean and you wanted the result to be false if it weren't. There are use cases for that, but they're quite limited. 99.9% of the time, simply if (myBoolean) suffices, even though it will be true for 1, "foo", and other truthy values.
There are times when using strict equality for other reasons is quite a good idea, because JavaScript's rules for loose equality if the operands are of different types are quite complex. But if you're using something as a flag, there's little if any point to using === on it.
One particular place where I've seen === used with boolean values is in code inspired by jQuery, where a callback function can cancel an action by returning false, but doesn't have to return anything. When a function has no explicit return value, the result of calling that function is undefined, which is, of course, falsey. So code that wants to check whether the function returned false, not just undefined, would do this:
if (callback(args) === false) {
// The callback explicitly returned false (not just a falsey value), cancel
// ...
}
But that's a relatively infrequent use case, and of course it involves === false as opposed to === true...
Some random example:
function CreateSomeObject(param)
{
if (param == "1")
{
return new Stuff();
}
return null;
}
var myBoolean = CreateSomeObject("1") || true;
if (myBoolean === true)
{
//doesn't execute
}
if (myBoolean)
{
//executes just fine
}
In case of null only , you want to do that , although I never used this because it feels like more verbose and long string. No problem using it or avoiding it.It is more of style you want to write the code.
I constructed a slightly convoluted answer and then realised that the main reason is in the falsy values rather than the truthy ones. Usually, a function returns one kind of thing, and there is only one falsy value (the empty string for a string function, or 0 for a numeric one, or whatever).
However, when you aren't sure if something is defined or not, it can be instructive:
waitForResponse(request, 5000);
if(!request.ResponseValue) {
alert('Server failed to respond');
}
vs
waitForResponse(request, 5000);
if(request.ResponseValue === 'false') {
alert('Server says no');
}
Although I'd argue that you should check for undefined rather than boolyness:
if(typeof request.ResponseValue === 'undefined') {
//...
}
Incidentally, typeof is fast, at least it was in Chrome last time I checked.
Personally, I don't like statements like it's good practice to x. IMO, it all depends on the context: if you want to check some object exists, if(objectX) will do just as if (objectX === undefined) or if (typeof objectX === 'undefined') and even if (typeof objectX == 'undefined').
The reason why some people, like Douglas Crockford, strongly advocate the use of value and type checking (===) is that falsy and truthy values can, in rare cases, produce unexpected results:
var falsy = '';
if (falsy)
{//only when falsy is truthy, but an empty string is falsy
console.log('could be seen as counter-intuitive: var was declared and assigned an empty string, but is falsy');
}
var obj = {falsy:''}
if (!obj.falsy)
{
console.log('I might assume falsy is not set, although it was:');
console.log(obj.hasOwnProperty('falsy'));//true
}
Again, this might just be my opinion, but in the vast majority of cases this won't break your code. I'd even go one step further: Douglas Crockford might claim that using checking for falsy values isn't a good idea, but he does like the logical OR (||) operator:
var falsy ='';
var someVar = falsy || 'default value';//this relies heavily on falsy values
The only "solid" arguments for strict comparison are:
if you need the variable to be a boolean, but then again falsy = !!falsy; coerces to a boolean all the same
strict comparisons are marginally faster, but you'll have to do a whole lot of comparisons before you'll be able to notice the difference
Having said that, I do tend to use strict comparisons an awful lot, again, it might be a personal thing, but I like to know what the actual type of a variable is:Given that '1' == 1 evaluates to true, but '1' === 1 is false, it at least allows you to coerce a var to the type you need:
var foo = '00001';
var elements = [foo = ('00000' + (+(foo)+1)).substr(-5)];
while(elements[+(foo)-1])
{
foo = ('00000' + (+(foo)+1)).substr(-5);
elements.push(foo = ('00000' + (+(foo)+1)).substr(-5));
}
Now this isn't what you'd call good code, but there's a lot of type-juggling going on. At the end of the ride, you might want to know what value was assigned to foo. That's not an issue in this snippet, but suppose you want to use the numeric value of foo inside the while loop, if it's an odd number:
var foo = '00001';
var elements = [foo = ('00000' + (+(foo)+1)).substr(-5)];
while(elements[+(foo)-1])
{
foo = ('00000' + (+(foo)+1)).substr(-5);
elements.push(foo = ('00000' + (+(foo)+1)).substr(-5));
if (+(foo)%2 === 1)
{
foo = +(foo);
//do stuff with foo
}
}
The easiest way to check weather or not foo is a string after the loop is completed is to check foo directly: if (foo === +(foo))
I am well aware that this example is a little far-fetched, but I have encountered a case quite similar to this one. It's at times like this where the advantages of strong-typed languages really show. speaking of which: new Date() >= someDateObject vs Date() >= someDateObject... try it in your console and you'll soon see what I'm on about.

How best to determine if an argument is not sent to the JavaScript function

I have now seen 2 methods for determining if an argument has been passed to a JavaScript function. I'm wondering if one method is better than the other or if one is just bad to use?
function Test(argument1, argument2) {
if (Test.arguments.length == 1) argument2 = 'blah';
alert(argument2);
}
Test('test');
Or
function Test(argument1, argument2) {
argument2 = argument2 || 'blah';
alert(argument2);
}
Test('test');
As far as I can tell, they both result in the same thing, but I've only used the first one before in production.
Another Option as mentioned by Tom:
function Test(argument1, argument2) {
if(argument2 === null) {
argument2 = 'blah';
}
alert(argument2);
}
As per Juan's comment, it would be better to change Tom's suggestion to:
function Test(argument1, argument2) {
if(argument2 === undefined) {
argument2 = 'blah';
}
alert(argument2);
}
There are several different ways to check if an argument was passed to a function. In addition to the two you mentioned in your (original) question - checking arguments.length or using the || operator to provide default values - one can also explicitly check the arguments for undefined via argument2 === undefined or typeof argument2 === 'undefined' if one is paranoid (see comments).
Using the || operator has become standard practice - all the cool kids do it - but be careful: The default value will be triggered if the argument evaluates to false, which means it might actually be undefined, null, false, 0, '' (or anything else for which Boolean(...) returns false).
So the question is when to use which check, as they all yield slightly different results.
Checking arguments.length exhibits the 'most correct' behaviour, but it might not be feasible if there's more than one optional argument.
The test for undefined is next 'best' - it only 'fails' if the function is explicitly called with an undefined value, which in all likelyhood should be treated the same way as omitting the argument.
The use of the || operator might trigger usage of the default value even if a valid argument is provided. On the other hand, its behaviour might actually be desired.
To summarize: Only use it if you know what you're doing!
In my opinion, using || is also the way to go if there's more than one optional argument and one doesn't want to pass an object literal as a workaround for named parameters.
Another nice way to provide default values using arguments.length is possible by falling through the labels of a switch statement:
function test(requiredArg, optionalArg1, optionalArg2, optionalArg3) {
switch(arguments.length) {
case 1: optionalArg1 = 'default1';
case 2: optionalArg2 = 'default2';
case 3: optionalArg3 = 'default3';
case 4: break;
default: throw new Error('illegal argument count')
}
// do stuff
}
This has the downside that the programmer's intention is not (visually) obvious and uses 'magic numbers'; it is therefore possibly error prone.
If you are using jQuery, one option that is nice (especially for complicated situations) is to use jQuery's extend method.
function foo(options) {
default_options = {
timeout : 1000,
callback : function(){},
some_number : 50,
some_text : "hello world"
};
options = $.extend({}, default_options, options);
}
If you call the function then like this:
foo({timeout : 500});
The options variable would then be:
{
timeout : 500,
callback : function(){},
some_number : 50,
some_text : "hello world"
};
This is one of the few cases where I find the test:
if(! argument2) {
}
works quite nicely and carries the correct implication syntactically.
(With the simultaneous restriction that I wouldn't allow a legitimate null value for argument2 which has some other meaning; but that would be really confusing.)
EDIT:
This is a really good example of a stylistic difference between loosely-typed and strongly-typed languages; and a stylistic option that javascript affords in spades.
My personal preference (with no criticism meant for other preferences) is minimalism. The less the code has to say, as long as I'm consistent and concise, the less someone else has to comprehend to correctly infer my meaning.
One implication of that preference is that I don't want to - don't find it useful to - pile up a bunch of type-dependency tests. Instead, I try to make the code mean what it looks like it means; and test only for what I really will need to test for.
One of the aggravations I find in some other peoples' code is needing to figure out whether or not they expect, in the larger context, to actually run into the cases they are testing for. Or if they are trying to test for everything possible, on the chance that they don't anticipate the context completely enough. Which means I end up needing to track them down exhaustively in both directions before I can confidently refactor or modify anything. I figure that there's a good chance they might have put those various tests in place because they foresaw circumstances where they would be needed (and which usually aren't apparent to me).
(I consider that a serious downside in the way these folks use dynamic languages. Too often people don't want to give up all the static tests, and end up faking it.)
I've seen this most glaringly in comparing comprehensive ActionScript 3 code with elegant javascript code. The AS3 can be 3 or 4 times the bulk of the js, and the reliability I suspect is at least no better, just because of the number (3-4X) of coding decisions that were made.
As you say, Shog9, YMMV. :D
In ES6 (ES2015) you can use Default parameters
function Test(arg1 = 'Hello', arg2 = 'World!'){
alert(arg1 + ' ' +arg2);
}
Test('Hello', 'World!'); // Hello World!
Test('Hello'); // Hello World!
Test(); // Hello World!
url = url === undefined ? location.href : url;
There are significant differences. Let's set up some test cases:
var unused; // value will be undefined
Test("test1", "some value");
Test("test2");
Test("test3", unused);
Test("test4", null);
Test("test5", 0);
Test("test6", "");
With the first method you describe, only the second test will use the default value. The second method will default all but the first (as JS will convert undefined, null, 0, and "" into the boolean false. And if you were to use Tom's method, only the fourth test will use the default!
Which method you choose really depends on your intended behavior. If values other than undefined are allowable for argument2, then you'll probably want some variation on the first; if a non-zero, non-null, non-empty value is desired, then the second method is ideal - indeed, it is often used to quickly eliminate such a wide range of values from consideration.
I'm sorry, I still yet cant comment, so to answer Tom's answer...
In javascript (undefined != null) == false
In fact that function wont work with "null", you should use "undefined"
There is a tricky way as well to find, whether a parameter is passed to a function or not. Have a look at the below example:
this.setCurrent = function(value) {
this.current = value || 0;
};
This necessary means that if the value of value is not present/passed - set it to 0.
Pretty cool huh!
Why not using the !! operator? This operator, placed before the variable, turn it to a boolean (if I've understood well), so !!undefined and !!null (and even !!NaN, which can be quite interesting) will return false.
Here is an exemple:
function foo(bar){
console.log(!!bar);
}
foo("hey") //=> will log true
foo() //=> will log false
Sometimes you want undefined as a possible argument but you still have situations where the argument may not be passed. In that case you can use arguments.length to check how many arguments were passed.
// Throw error if the field is not matching our expectations
function testField(label, fieldValue, expectedValue) {
console.log(arguments) // Gives: [Arguments] { '0': 'id', '1': 1, '2': undefined }
if(arguments.length === 2) {
if(!fieldValue) {
throw new Error(`Field "${label}" must have a value`)
}
}
else if(expectedValue === undefined) {
if(fieldValue !== undefined) {
throw Error(`Field "${label}" must NOT have a value`)
}
}
// We stringify so our check works for objects as well
else {
if(JSON.stringify(fieldValue) !== JSON.stringify(expectedValue)) {
throw Error(`Field "${label}" must equal ${expectedValue} but was ${fieldValue}`)
}
}
}
testField('id', 12) -> Passes, we don't want id to be blank
testField('id', undefined, undefined) -> Passes, we want id to be undefined
testField('id', 12, undefined) -> Errors, we wanted id to be undefined
It can be convenient to approach argument detection by evoking your function with an Object of optional properties:
function foo(options) {
var config = { // defaults
list: 'string value',
of: [a, b, c],
optional: {x: y},
objects: function(param){
// do stuff here
}
};
if(options !== undefined){
for (i in config) {
if (config.hasOwnProperty(i)){
if (options[i] !== undefined) { config[i] = options[i]; }
}
}
}
}
Some times you may also want to check for type, specially if you are using the function as getter and setter. The following code is ES6 (will not run in EcmaScript 5 or older):
class PrivateTest {
constructor(aNumber) {
let _aNumber = aNumber;
//Privileged setter/getter with access to private _number:
this.aNumber = function(value) {
if (value !== undefined && (typeof value === typeof _aNumber)) {
_aNumber = value;
}
else {
return _aNumber;
}
}
}
}
function example(arg) {
var argumentID = '0'; //1,2,3,4...whatever
if (argumentID in arguments === false) {
console.log(`the argument with id ${argumentID} was not passed to the function`);
}
}
Because arrays inherit from Object.prototype. Consider ⇑ to make the world better.
fnCalledFunction(Param1,Param2, window.YourOptionalParameter)
If above function is called from many places and you are sure first 2 parameters are passed from every where but not sure about 3rd parameter then you can use window.
window.param3 will handle if it is not defined from the caller method.

Categories

Resources