Working on an E2E using Ramda. I'm not getting how to convert a simple IF condition using Ramda Cond.
Code using If :
if (constraint == 'required') {
// then only do something
await waitForElementToBeClickable(constraintElement);
await constraint.click();
}
I don't want the else because I want the action to happen only if the constraint is present.
I've done this so far using constraint but it's not working :
await waitForElementToBeClickable(cond([
[equals('required'), always(constraintElement)],
])(constraint), this.browser);
const constraintCheck = cond([
[equals('required'), () => constraintElement.click()],
]);
await constraintCheck(constraint);
In some cases, I do not want to pass the constraint. Then the Condition should not execute at all. But it is always getting executed and throwing the error : Cannot read property 'isPresent' of Undefined.
I think perhaps there's some confusion here (beyond what customcommander rightly points out about the type of constraint.)
One of the features Ramda tries to offer is to allow us to program with expressions rather than statements. Especially concerning are control-flow statements. But a statement that looks like this:
let foo
if (condition) {
foo = 'bar'
} else {
foo = 'baz'
}
already has a standard expression form:
const foo = condition ? 'bar' : 'baz'
Ramda does not really try to offer an alternative to this. But there is another way we might try to use if:
let foo
if (test(val)) {
foo = bar(val)
} else {
foo = baz(val)
}
Here, when working with functions, Ramda offers a convenient shorthand:
const getFoo = ifElse(test, bar, baz)
// ... later
const foo = getFoo(val)
(And if you just want to return val in the case the test fails, you can use the shorthand:
const foo = when(test, bar)
Or if you want val when the test succeeds, you can do
const foo = unless(test, baz)
)
While it might be slightly more expressive to turn the code into
const foo = ifElse(test, bar, baz)(val)
That's not the main point. The rationale for ifElse is to use it in creating the reusable function ifElse(test, bar, baz). (cond is just the same, just offering a sequence of condition-consequent pairs instead of one if and one else.)
Note one important feature to this: the test function, the function to run if it's true, and the one to run if it's false all have the same signature. If one of them takes three parameters, then they all should accept three parameters. And while the test should return a boolean, the other two can have any return type, but each should have the same return type as the other.
So one can use a thunk, as you try with () => constraintElement.click(), it is mostly a misuse of the Ramda feature. It probably gains you nothing in your code.
It's still not clear what you're trying to do with the conversion from an if statement to ifElse or cond. Please feel free to add an update to your question explaining more fully what you're trying to do, and what problem you're trying to solve with this conversion, someone will probably be able to offer some help. But make sure you clarify what constraint and constraintElement are and what waitForElementToBeClickable resolves to. Right now it's fairly confusing.
By looking at your example, it seems that you use constraint both as a string and an object which may cause unnecessary confusion. I know you can implement a toString() method on an object but I'm not sure if that always plays nicely when you integrate with external libraries
const obj = {
toString: () => 'burrito',
order: () => '🌯'
};
obj + '' === 'burrito' // true
obj === 'burrito' // false
equals('burrito', obj + '') // true
equals('burrito', obj) // false
I would suggest that you convert your object into a string before you make the check:
const check = pipe(
toString,
equals('burrito')
);
check(obj); // true
Then if you don't need an "else" branch, you could consider using when.
const execute = when(check, invoker(0, 'order'))
execute(obj); // "🌯"
execute({}); // {}
Related
I want to know if an argument will throw if I use it in a key-value spread construction:
{ ...maybeIWillThrow }
I've got a bunch of functions that use spread to concisely implement "default options" behavior, like so:
const DEFAULTS = { bells: true, whistles: true }
function doThing( arg1, options ) {
let effectiveOptions = { ...DEFAULTS, ...options }
// do work...
}
Now I want to go back and add a few guard clauses to protect against calling with a non-hash options argument. Using try/catch feels clunky because it requires two code blocks instead of one, and my preference would be a ternary or maybe a single-statement detour:
let effectiveOptions = spreadsLikeButter(options)
? { ...DEFAULTS, ...options }
: { ...DEFAULTS }
MDN suggests that testing for iterability is not right here (emphasis added):
Spread syntax (other than in the case of spread properties) can be applied only to iterable objects
I know I can protect against undefined with default parameters, but that won't help if callers pass 5 or true, and I assume typeof options === 'object' will produce too many false positives (e.g. Date, Promise).
Is there a concise way to test a variable to see whether it will spread into an object without throwing?
Right now I'm wrapping try/catch in a willItBlend( value: any ): boolean, but I'm hoping to replace that with something cleaner once I understand this better.
Also, I know I could move all the merge-with-defaults logic into a separate function that can hide the mess -- and maybe that's a good idea in my case -- but for academic purposes let's focus specifically on how to test a variable to determine wether it will spread.
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?
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.
Many times I'm having to loop through data and add the new to the old, but I can never seem to get it right.. Here's what I have now, basically trying to concatinate together the previous number from the new number, ultimately building a comma delimited string of numbers:
function showItems(){
if(prev_numbers == undefined){
var prev_numbers = '';
}else{
prev_numbers = prev_numbers;
}
numbers = Math.floor(Math.random()*101);
values = numbers +','+ prev_numbers;
// Here is where some code would be that makes use of comma delimited numbers
alert(values);
prev_numbers = values;
}
setInterval(showItems, 1000);
Why not use the Array.join method?
var numbers = [1, 2, 3, 4, 5];
values = numbers.join(',');
It's not clear where the numbers are coming from. Perhaps post a little more code.
It seems like you're storing the history as a comma-delimited string, and adding new numbers to the beginning of the string as they come in.
Generally, it would make more sense to store the numbers as an array of numbers, then use join to build the string for display as needed. You can prepend to the array using unshift:
numbers.unshift(Math.random() * 100);
Actually, I would recommend this even if the id's are strings.
As meder said, you'd need to define prev_numbers outside showItems, or specify them as global by referencing them as a property of window (substitute prev_numbers by window.prev_numbers). That said, harpo's solution is a lot faster if you're splitting the string up again to access the separate numbers. We need to know a bit more about the context as well as your priority (speed? memory? code length? maintainability?).
By the way, this
if(prev_numbers == undefined){
var prev_numbers = '';
}else{
prev_numbers = prev_numbers;
}
is completely useless as far as I know. It might change the internal representation of prev_numbers, but with complicated things like JIT I'm not sure if that still holds. Your application doesn't seem to be interested in that anyway. As far as I can tell, this code can be removed.
What you need to do is to implement the memoize technique, i.e. you need a memoizer function.
Here's what Google came up with for a JS memoize implementation.
Your doing it right, only that your neglecting that functions are implemented as a type in JS--it's a first-class object, so these are completely valid statements:
function a() { };
a.foo = 'bar';
a.hasOwnProperty('foo'); // true
a.foo; // 'bar'
a = function { this.foo = 'bar' }
a.foo; // 'bar'
a['foo']; // 'bar', because objects are implemented as dictionaries
The only thing that you need to change is to set prev_numbers as a property of showItems:
function showItems() {
// bool check for undefined object properties returns false
if(!this.prev_numbers)
this.prev_numbers = '';
numbers = Math.floor(Math.random()*101);
this.prev_numbers = numbers + ',' + this.prev_numbers;
}
As to your particular problem of always receiving ReferenceError in your code, I do not know the exact implementation details, but I have observed that accessing undefined globals will raise ReferenceError instead of simply returning undefined, as you'd expect. This is how to properly handle it:
if (hasOwnProperty('prev_numbers') { ... }
// equivalent to
if(window.hasOwnProperty('prev_numbers') { ... }
Take a look at this:
baz; // ReferenceError
hasOwnProperty('baz'); // false
window.hasOwnProperty('baz') //false
baz = 'bar';
hasOwnProperty('baz'); // true
window.hasOwnProperty('baz) // true
An alternative to calling hasOwnProperty is:
foo; // ReferenceError
window.foo // undefined (no ReferenceError raised)
if (!window.foo) 'yay'; // 'yay'
if (window.foo == undefined) 'yay'; // 'yay'
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.