I've just started using Hubot recently.
I'd like to know if a command is used, but no arguments have been entered.
robot.respond(/dothis (.*)/i, function(res) { ... };
This doesn't return anything if no arguments have been entered, even though it accepts 0 or more arguments.
robot.respond(/dothis/i, function(res) { ... };
This doesn't accept any arguments, but responds when called.
Not quite sure how to go about this, is it possible?
I think you'd need a regular expression engine that handled positive look-behinds to do this in a straightforward way, and I don't think V8 (which is what Node is using under the hood) has that as of this writing.
There are lots of other workarounds, though. Here's one using \b which checks for a word-boundary:
robot.respond(/dothis\b(.*)/i, function(res) {
if (res.match[1]) {
res.send('We got the paramater: ' + res.match[1].trim());
} else {
res.send('Command called with no parameter.');
}
});
robot.respond(/dothis(.*)/i, function(res) { ... };
This works, that space makes all the difference. It will now take an empty string as an argument.
Related
Let's have a function call
function doSomethingAndInvokeCallback(callback){
// do something
callback();
}
I can check if given argument is function if(typeof callback == 'function')
How can I discover, if given callback function is function and isn't empty?
like
doSomethingAndInvokeCallback(function(){
//nothing here
})
There is no totally reliable way to know if a function is empty because there are multiple kinds of functions in JS, some implemented with JS and some implemented with native code and you can't know for sure whether the function passed in does anything or not. If you want to limit the passed in function to only very simple JS functions, you could use the mechanisms outlined by other answers here (examining the source of the function). But, I would not recommend doing that in anything but a tightly controlled situation because there are lots of legal javascript ways to break that.
I would suggest that you should change the contract of your function arguments and have the caller pass null or not pass anything (which will make the argument undefined) rather than an empty function. Then, it will be very clear whether they intend to have a function called or not. If they then pass an empty function instead of null or undefined, they are getting the behavior that the interface of the function specifies. The caller can choose the desired behavior and you can implement your function in a more failsafe manner.
Also, one of your main suppositions in your question is not quite right. You cannot safely use typeof x == "function" to determine if something is a function as that will not work reliably in some older versions of IE for some types of functions. If you want to learn how to detect if something is a function at all, you can learn from jQuery here (even if you're not using it). jQuery has a function it uses internally all the time called jQuery.isFunction() that returns a bool. It uses that mostly for testing arguments to see if a function was passed.
Internally, it calls:
Object.prototype.toString.call(o)
and then examines the result. If the result has "Function" in it, then test test parameter is a function.
So, using the same technique used in jQuery, you could build your own simple little isFunction routine like this:
function isFunction(test) {
return(Object.prototype.toString.call(test).indexOf("Function") > -1);
}
Of course, if you have jQuery available, you could just use it's own version:
jQuery.isFunction(o)
When there are questions with potential cross browser compatibility issues, I find it instructional to look at how one of the big libraries solves the issue, even if you aren't going to be using that library. You can be sure that the libraries have been vetted against many browsers so a technique they are using is safe. You sometimes have to unwrap all their own internal routines they may use to figure out what they're really doing (which was the case for this function), but you can save yourself a lot of legwork.
You can see a working test bed for this here: http://jsfiddle.net/jfriend00/PKcsM/
In modern browsers typeof fn === "function", but in older versions of IE, some functions give a typeof === "object" which is probably why jQuery uses this other method which does work in those older versions of IE.
It seems that you can define a function to retrieve the body of a function(1). I wrote a small (non-definitive) test of this:
http://jsfiddle.net/6qn5P/
Function.prototype.getBody =
function() {
// Get content between first { and last }
var m = this.toString().match(/\{([\s\S]*)\}/m)[1];
// Strip comments
return m.replace(/^\s*\/\/.*$/mg,'');
};
function foo() {
var a = 1, b = "bar";
alert(b + a);
return null;
}
console.log(foo.getBody());
console.log(foo.getBody().length);
One possibility is matching the .toString result against a regexp to get the function body, and then trim to check whether it has become an empty string:
var f = function foo() {
};
/^function [^(]*\(\)[ ]*{(.*)}$/.exec(
f.toString().replace(/\n/g, "")
)[1].trim() === ""; // true
That ugly regexp does take care of spaces aroung named functions as well as extraneous spaces before the name and the opening brace. Spaces like in foo () do seem to be removed, so there is no reason to check for those.
You might be able to get this from .toString():
var blank = function(){};
var f = function(){};
var f2 = function() { return 1; };
f.toString() == blank.toString(); // true
f2.toString() == blank.toString(); // false
but this is really prone to error:
var blank = function(){};
var f = function(){ }; // extra space!
f.toString() == blank.toString(); // false
You could munge the strings a bit to try to overcome this, but I suspect this is very browser-dependent. I wouldn't actually try to do this in a production environment if I were you. Even if you normalize the whitespace, it still won't catch other no-op lines, including comments, useless var statements, etc. To actually address these issues, you'd probably need a whole tokenizer system (or a crazy regex).
You can't do it for a host function, but for others, you can fairly reliably do
function isEmpty(f) {
return typeof f === "function" &&
/^function[^{]*[{]\s*[}]\s*$/.test(
Function.prototype.toString.call(f));
}
This isn't efficient, but major interpreters implement toString for functions in such a way that it works, though it will not work on some interpreters for some empty-ish functions
function () { /* nothing here */ }
function () { ; }
function () { return; }
In some implementation you can just do a toString() on the function and get it's content. Though it contains comments etcetera.
var foo = function(){ /* Comment */ };
alert(foo.toString());
I came across this construct in an Angular example and I wonder why this is chosen:
_ => console.log('Not using any parameters');
I understand that the variable _ means don't care/not used but since it is the only variable is there any reason to prefer the use of _ over:
() => console.log('Not using any parameters');
Surely this can't be about one character less to type. The () syntax conveys the intent better in my opinion and is also more type specific because otherwise I think the first example should have looked like this:
(_: any) => console.log('Not using any parameters');
In case it matters, this was the context where it was used:
submit(query: string): void {
this.router.navigate(['search'], { queryParams: { query: query } })
.then(_ => this.search());
}
The reason why this style can be used (and possibly why it was used here) is that _ is one character shorter than ().
Optional parentheses fall into the same style issue as optional curly brackets. This is a matter of taste and code style for the most part, but verbosity is favoured here because of consistency.
While arrow functions allow a single parameter without parentheses, it is inconsistent with zero, single destructured, single rest and multiple parameters:
let zeroParamFn = () => { ... };
let oneParamFn = param1 => { ... };
let oneParamDestructuredArrFn = ([param1]) => { ... };
let oneParamDestructuredObjFn = ({ param1 }) => { ... };
let twoParamsFn = (param1, param2) => { ... };
let restParamsFn = (...params) => { ... };
Although is declared but never used error was fixed in TypeScript 2.0 for underscored parameters, _ can also trigger unused variable/parameter warning from a linter or IDE. This is a considerable argument against doing this.
_ can be conventionally used for ignored parameters (as the other answer already explained). While this may be considered acceptable, this habit may result in a conflict with _ Underscore/Lodash namespace, also looks confusing when there are multiple ignored parameters. For this reason it is beneficial to have properly named underscored parameters (supported in TS 2.0), also saves time on figuring out function signature and why the parameters are marked as ignored (this defies the purpose of _ parameter as a shortcut):
let fn = (param1, _unusedParam2, param3) => { ... };
For the reasons listed above, I would personally consider _ => { ... } code style a bad tone that should be avoided.
The () syntax conveys the intent better imho and is also more type specific
Not exactly. () says that the function does not expect any arguments, it doesn't declare any parameters. The function's .length is 0.
If you use _, it explicitly states that the function will be passed one argument, but that you don't care about it. The function's .length will be 1, which might matter in some frameworks.
So from a type perspective, it might be more accurate thing to do (especially when you don't type it with any but, say, _: Event). And as you said, it's one character less to type which is also easier to reach on some keyboards.
I guess _ => is just used over () => because _ is common in other languages where it is not allowed to just omit parameters like in JS.
_ is popular in Go and it's also used in Dart to indicate a parameter is ignored and probably others I don't know about.
It is possisble to distinguish between the two usages, and some frameworks use this to represent different types of callbacks. For example I think nodes express framework uses this to distinguish between types of middleware, for example error handlers use three arguments, while routing uses two.
Such differentiation can look like the example below:
const f1 = () => { } // A function taking no arguments
const f2 = _ => { } // A function with one argument that doesn't use it
function h(ff) {
if (ff.length === 0) {
console.log("No argument function - calling directly");
ff();
} else if (ff.length === 1) {
console.log("Single argument function - calling with 1");
ff(1);
}
}
h(f1);
h(f2);
This is based off Bergi's answer, but I thought adding an example was a little more editing than I was happy to do to someone elses post.
Is there a method or way in JavaScript that I can check if assert if a function returns a value through the use of an if statement?
So this:
function(val) {
if (val) return "it is true";
return "it is false";
}
versus this:
function(val) {
var str = 'it is ';
return str += val;
}
I've been looking around and can only find articles related to Java or other languages. Thanks in advance.
EDIT: I'm writing tests to assert whether or not a function (written by a user) utilizes an if statement. Hope that clarifies that a bit!
First I'd like to mention that such checks shouldn't be used in code, in which I mean that proper code should never check whether an if-statement is used inside a function. Whether a value is returned from it or not, this shouldn't be checked or tested.
But, to get back on topic. I'm not quite sure whether this is possible out of the box. I do however have a solution that you might be able to use to achieve something similar to your goals.
You can convert a given function to it's string representation. Take a look at the following example:
// Define a function
var myFunction = function() {
return 1 + 3;
};
// Print the function, as a string
console.log(myFunction.toString());
This code will print the string representation of the function in the console, so that will be function() { return 1 + 3; }. Some environments, such as the Firefox return a compiled version of the function which would look like function() { return 4; } but that doens't really have any effect on our use.
Using this method you'll be able to check whether the given function contains an if-statement. Such code would look like this:
// Define a function
var myFunction = function() {
return 1 + 3;
};
// Check whether the given function contains an if-statement
if(myFunction.toString().indexOf('if') > -1) {
console.log('This function does contain an if-statement');
} else {
console.log('This function does not contain an if-statement');
}
This method isn't ideal for your situation but it might point you in the right direction. Please note that this method isn't a rock-solid solution, at least not in this state. The usage of 'if' as a string (or something else) in a function would also cause the code above to say that the function contains an if-statement. Also, this doesn't explicitly check whether a value is returned from inside of an if-statement.
If you'd like to ensure the things mentioned above (that a real if-statement is used, in which a value is returned from it) you might have to modify the above code to make it smarter if this string-based method suits your needs. Then, I'd highly recommend to write a fancy wrapper around it to make it easier in use.
Let's say I have an object that looks like this:
{
'apple': 'nice',
'banana': 'decent',
'cherry': 'yuck',
}
and I have these two methods:
function eatItems(cherry, apple) { }
function throwItem(banana) { }
My two questions:
Is it possible for me to invoke eatItem and send the arguments in the correct order? Maybe something like:
eatItems.call(this, {'cherry': cherry, 'apple': apple});
What if I don't know what arguments eatItems receives, can I dynamically look up the names of the arguments for a function so I can know the order that I need to throw them in?
There's a way, indeed, and it involves calling toString on a function:
var source = eatItems.toString();
// => "function eatItems(cherry, apple) { }"
The next step is to parse the string you've got to get the names of the arguments:
var args = source.substring(source.indexOf("(") + 1, source.indexOf(")")),
argNames = /\S/.test(args) ? args.split(/\s*,\s*/) : [];
A few caveats:
This solution has been kept quite simple. It doesn't handle comments in the function definition.
Not every browser can correctly convert a function to a string (the PS3 browser comes to my mind), but they're a really small minority anyway.
I haven't tested it, but there may be some performance issues on slower machines and/or older browsers with large functions.
And, overall, this solution is more like an exercise. I wouldn't recommend taking this pattern in Javascript. Don't forget that some functions handle a variable number of arguments, and you won't find them listed in their definition. Rethink your code, and find a better way.
If I understand correctly you want extract the argument names from the function, and inject data from an object based on those names. This can be accomplished by converting the function to a string, extracting the arguments, and applying the function with those arguments:
function inject(data, f) {
var args = f.toString()
.match(/function\s*?\((.+?)\)/)
.pop()
.split(',')
.map(function(a){return data[a.trim()]})
return function() {
return f.apply(this, args)
}
}
var data = {
apple: 'nice',
banana: 'decent',
cherry: 'yuck',
}
var eat = inject(data, function(cherry, apple) {
console.log(cherry, apple)
})
eat() //=> yuck, nice
The obvious problem with this approach is that it is highly dependent on the variable names, so when you minify your code, the variables will get mangled and the function will stop working. This is a known problem in AngularJS, which uses something similar for their dependency injection.
This is often an XY problem, or an anti-pattern at the very least.
In Javascript I can call any method with more than the necessary amount of parameters and the extra parameters are silently ignored.
e.g.
letters = ['a','b','c']
//correct
letters.indexOf('a')
//This also works without error or warning
letters.indexOf('a', "blah", "ignore me", 38)
Are there ways to detect cases where this occurs?
My motivation is that in my experience cases where this occurs are usually bugs. Identification of these by code analysis or at runtime would help track these errors down.
These cases are especially prevalent where people are expecting alterations to base types which may not have occurred. Logging a warning where this happens
e.g.
Date.parse('02--12--2012', 'dd--MM--YYYY')
Notes:
To be clear I would like a solution that doesn't involve me sprinkling checks all over my code and other peoples' code.
You can use the arguments object.
function myFunction(param1,param2)
{
if (arguments.length!=2)
{
// wrong param number!
}
...
}
As per your edit: If you want to implement an automated form of check, without ever touching the original functions:
You still have to process each function with:
functionName = debug(functionName, numberOfExpectedArgs);
This operation wraps the function with a check of the number of arguments.
So we leave a sample function untouched:
// this is the original function... we want to implement argument number
// checking without insertint ANY debug code and ANY modification
function myFunction(a,b,c)
{
return a + " " + b + " " + c;
}
// the only addition is to do this...
myFunction = debug(myFunction,3); // <- implement arg number check on myFunction for 3 args
// let's test it...
console.log(myFunction(1,2,3));
console.log(myFunction(1,2));
You need to implement this debug() function:
function debug(f, n)
{
var f2 = f;
var fn = function()
{
if (arguments.length!=n) console.log("WARNING, wrong argument number");
return f2.apply(f2, arguments);
};
return fn;
}
This solution is TOTALLY transparent as per already defined functions, so it may be what you seek for.
I strongly suggest to check against deprecations (there are some) and crossbrowser compatibility.
The functions in JavaScript are objects. As such they have properties. What you want can be achieved with length MDN property, which specifies the number of arguments expected by the function.
function say ( hello, world ) {
alert (
"arguments length = " + arguments.length + "\n" +
"defined with = " + say.length
);
}
say ( "this ", "brave ", "new ", "world" );
This works even on IE8. Demo. In your case you can do something like this.
Javascript is a very dynamic language and many of its useful features also make it impossible to do some checks statically.
The existance of the arguments implicit object means there is no way to automatically determine how many arguments a function is expecting for all functions. Many var-arg functions declare no formal arguments and uses the arguments object exclusively.
All you can reliably do is to check it manually in each function like Cranio suggested.
If you want to have automated checks, e.g. as part of your unit tests, you can make use of the length property of the Function objects, which returns the number of formal arguments. For var-arg functions, just don't include the check. For example:
function checkNumberOfArguments(args) {
if (args.length != args.callee.length) {
throw new Error('Wrong number of arguments');
}
};
// Use it like
function a(b) {
checkNumberOfArguments(arguments);
}
a(1);
a(1,2);
Inside function you can use arguments object, it contains an array of all the arguments that were supplied to the function when it was called.
function x(){
return arguments.length;
}
x()
=> 0
x(1,1,1,1,1,1,1,1,1)
=> 9