I have a javascript method that takes a single parameter. That parameter can be a path (in which case the function will use ajax to resolve the variable, a function (which will be called to resolve the variable, or valid markup (which will be used directly).
I'm looking for suggestions for distinguishing between a string that represents a path and a string that represents markup.
Note: I'm not too concerned if the markup is invalid
Well if you are stuck with the function you got, than you would have to use a regular expression to dtermine what you got. Problem with that, it can be error prone.
You are better off passing in an object and letting the object tell you what you have based on what properties it has.
function myMethod( obj ) {
if (obj.path) {
console.log("I have a path:", obj.path);
} else {
console.log("I have a path:", obj.html);
}
}
myMethod({"path":"/foo/bar/"});
myMethod({"html":"<p>/foo/bar/</p>"});
You can use something like this:
function validate(param) {
if (typeof(param) == 'function') {
console.log('It is a function!')
} else if (typeof(param) == 'string') {
if (param.indexOf('http') == 0) {
console.log('It is a path!')
} else {
console.log('It is a markup!')
}
}
}
It's far from perfect (especially in Path department) but it's a starting point.
Demo: http://jsfiddle.net/4369k/
Related
I'm having a lot of trouble figuring out how the recursive function is being done in this example. Problem is that he uses this technique farther down the book and I feel I need to have a grasp of what's he doing or I'm doomed. I've tried to console log the result of the function (part in quotes) to see how it changes down the line, but it doesn't give me a clear view of what's going on. Since returns often exit functions and loops, and the function is returning true at the end, I can't seem to track down how the function's suppose to work, let alone the recursive part
function talksAbout(node, string) {
if (node.nodeType == Node.ELEMENT_NODE) {
for (let child of node.childNodes) {
console.log(talksAbout(child,string));
if (talksAbout(child, string)) {
return true;
}
}
return false;
} else if (node.nodeType == Node.TEXT_NODE) {
return node.nodeValue.indexOf(string) > -1;
}
}
console.log(talksAbout(document.body, "book"));
// → true
From my best understanding of this, here's how it works, assuming the block of code is the talksAbout function.
if (node.nodeType == Node.ELEMENT_NODE) {
I'm guessing this is checking if the node it's looking at is an "element" that likely contains other nodes.
for (let child of node.childNodes) {
console.log(talksAbout(child,string));
if (talksAbout(child, string)) {
return true;
}
}
return false;
Here, the function seems to be iterating through the children of an element. Best I can explain it is, it's basically sending a "chain" of itself down the tree of an element, and if it finds something it's looking for, it returns true. If it doesn't find anything, it returns false.
} else if (node.nodeType == node.text_NODE) {
This is checking if the node it's looking at is a text node, which I'm assuming probably doesn't have any other children.
return node.nodeValue.indexOf(string) > -1;
}
Here, it's checking if the string in the "string" parameter exists inside the node. If it is, it returns true, and this "true" cascades down the line of recursive calls and eventually, the entire function returns true.
If it isn't, it just kinda... does nothing, letting the other calls in the "chain" check for other stuff.
EDIT:
It turns out, the function is massively overcomplicated. It isn't necessary to use a recursive function to search through all of the children: it's possible to just search through node.textContent and check for the string you're looking for. The recursive function is equivalent to this simplified function:
function talksAbout(node, string) {
return node.textContent.indexOf(string) > -1;
}
It also should be noted that if the <script> tag containing the function call is inside the node being searched, the function will always return true because it'll reach into the script tag and find the function's "string" parameter.
Example:
function talksAbout(node,string) {
return node.textContent.indexOf(string) > -1; // functionally equivalent to the recursive function
}
console.log("document.body talks about 'book': " + talksAbout(document.body, "book")); // This script tag is inside document.body, so it finds the "book" string here
console.log("wrapper talks about 'bar': " + talksAbout(document.getElementById("wrapper"), "bar")); // finds string in second layer
console.log("example talks about 'bar': " + talksAbout(document.getElementById("example"), "bar")); // the word "bar" comes before the element being searched
<div id="wrapper">foo
<div>bar
<div id="example">baz</div>
</div>
</div>
Using the following code:
const assrt = function () {
try {
return chaiAssert.apply(null, arguments);
}
catch (e) {
return handleError(e);
}
};
v.assert = new Proxy(assrt, {
get: function (target, prop) {
if(typeof prop === 'symbol'){
// I don't know what to do with symbols, so return
return Reflect.get(...arguments);
}
// but here! we still get properties that don't exist
if(!chaiAssert[prop]){
return handleError(
new Error(`The assertion library used does not have '${prop}' property or method.`)
);
}
return function () {
try {
return chaiAssert[prop].apply(null, arguments);
}
catch (e) {
return handleError(e);
}
}
}
});
the error I get with this code is:
TypeError: Cannot convert a Symbol value to a string
and this occurs on the line:
new Error(`The assertion library used does not have '${prop}' property or method.`));
I have used Proxies before, and I have never seen Symbols being passed to the get method of the Proxy. Does anyone know how to circumvent this problem?
Why are Symbols being passed to the Proxy get function and how do I properly handle that?
Why are Symbols being passed to the Proxy get function?
We don't know, you didn't show any code that actually uses the proxy. But many symbols are accessed by builtin methods, e.g. when you iterate the proxy it uses the Symbol.iterator method.
and how do I properly handle that?
You cannot concatenate a symbol with a string, you need to be explicit about doing this. You can use either prop.toString() or just switch based on typeof prop.
In order to write quality code with good readability, I'm adopting currying functions approach and making pure helper functions for most of the repetitive code snippets. I just observed that I’m having an existence/type check everywhere in my project to avoid any possible errors like type of undefined.
The checks are like:
if (param){
action...
}
I'm thinking to create a global helper function that should take two parameters; param that need to be checked and the action function to perform the action in case the check passes. Something like:
function isExist(param, action){
if (param){
action();
}
}
This functions is not ideally working for all snippets/cases. How can i make it efficient and globally functional for all cases? Also is this the right approach. If not then what is the best approach that i should follow to achieve my aim here?
Example:
if (userInput){
saveToDB(userInput);
}
if (valueFromDB){
performSomeAction();
}
if (username && password){
validate(username, password)
}
I want all of these checks at different points in my code to be replaced by single helper function to somewhat like:
isExist( userInput, saveToDB(userInput) );
isExist( valueFromDB, performSomeAction );
isExist( (username && password), validate(username, password) );
In this way we've replaced this 9 lines of code with just three lines. This is what I wanna achieve.
Well, if you try to think of a good name for
function isExist(param, action){
if (param){
action();
}
}
Then I think one good candidate would be conditionalExecute(condition, codeToExecute). Does this kind of work sound familiar? Are you sure you're not just reinventing the if-statement itself?
Maybe I'm missing your point, but I can't personally see the benefit of encapsulating the logic of the if-statement more than it already is.
Edit: It should be noted that within the context of Javascript the code
if(someVariable){
// do something
}
already reads like "If someVariable is truthy (which undefined is not) then....
But sure, if you only want to check for existance (a variable not being undefined) I won't argue against you if you say it's preferable to have a named function that makes that clear.
In that case I think it's clearer to only encapsulate the actual existence check (or what ever you want to check), not the conditional nature (because for that we already have the if-statement). So something like
function exists(x) {
return x !== undefined; // or something like that
}
function isNotNull(x) {
//TODO:
}
Then your code would become more explicit and readable, and you could combine the functions if you wanted
function neitherUndefinedNorNull(x){
return exists(x) && isNotNull(x);
}
if(neitherUndefinedNorNull(X)){
// your "regular" code here
}
If the code inside of the if-statement is repeated, then extract that as a function as well.
function myRepeatedCode() {
// do stuff
}
function someAlternativeCondition(x){
// test
}
if(neitherUndefinedNorNull ){
myRepeatedCode();
} else if(someAlternativeCondition(x)) {
myRepeatedCode();
}
// OR combine them in the same if-statement
if(neitherUndefinedNorNull(x) || someAlternativeCondition(x)){
myRepeatedCode();
}
Last edit: If you're chasing characters you could even write
// because of short-circuiting, myFunc1 and myFunc2 will only
// execute if myCond1 resp myCond2 is true (or truthy).
myCond1(x) && myFunc1(x)
myCond2(y) && myFunc2(y)
This is the perfect place to use Maybe:
const enumerable = true;
// data Maybe a = Nothing | Just a
const Maybe = {};
const Nothing = Object.create(Maybe);
const Just = value => Object.create(Maybe, {value: {enumerable, value}});
// instance Functor Maybe where
Nothing.map = _ => Nothing;
Maybe.map = function (fun) { return Just(fun(this.value)); };
// instance Applicative Maybe where
Maybe.of = Just;
Nothing.ap = _ => Nothing;
Maybe.ap = function (maybe) { return maybe.map(this.value); };
// instance Monad Maybe where
Nothing.chain = _ => Nothing;
Maybe.chain = function (kleisli) { return kleisli(this.value); };
Maybe follows the Fantasy Land Specification[1]. Using Maybe allows you to write code like this:
// userInput :: Maybe Data
// saveToDB :: Data -> Something
userInput.map(saveToDB); // :: Maybe Something
// valueFromDB :: Maybe Data
// performSomeAction :: Data -> Maybe Something
valueFromDB.chain(performSomeAction); // :: Maybe Something
// username :: Maybe String
// password :: Maybe Password
// validate :: String -> Password -> Something
Maybe.of(validate).ap(username).ap(password); // :: Maybe Something
Anyway, if you're really interested in functional programming then I suggest that you Learn You A Haskell.
[1] I don't agree with the Fantasy Land Specification on flipping the arguments of ap.
how about this, it can process the parameters at same time.
function test(a,b,c)
{
console.log("%s,%s,%s",a,b,c)
}
function check_and_run(param,action){
var args = Array.prototype.slice.call(arguments); //turn arguments to array
args.shift(); //remove param and action
args.shift();
if(param)
action.apply(this,args)
}
check_and_run(1,test,1,2,3) //this will invoke test(1,2,3)
check_and_run(0,test,1,2,3) //this will do nothing
Perhaps something like this:
function conFun(fnCondition, fnCall, defaultResult=undefined) {
return (...rest) => {
if( fnCondition(...rest) ) {
return fnCall(...rest)
}
return defaultResult;
}
}
const add = conFun(
(...rest) => rest.every(n => typeof n === 'number'),
(...rest) => rest.reduce((a, n) => a+n),
NaN);
add("1", "2"); //=> NaN
add(1, 2); //=> 3
So in your question you might be after the first argument not being undefined:
const firstDefined = (v) => typeof v !== 'undefined';
const cSomeFun = conFun(firstDefined, someFun, "");
cSomeFun(); // ==> ""
cSomeFun("test"); // ==> whatever someFun("test") returns
If you are just looking to call something based on non undefined arguments you can simply define it like this:
function callDefined(fn, ...rest) {
if( rest.every(firstDefined) ) {
return fn(...rest)
}
return undefined;
}
callDefined( saveToDB.bind(this, userInput), userInput);
callDefined( performSomeAction, valueFromDB);
callDefined( calidate.bind(this, username, password), username, password);
So I really couldn't find much on this. The idea is that I have a user input (text) and I want to check if its valid code in JS and then run it if it is.
I know that I can do if (typeof userInput === "function") { if the userInput was actually a function, but the user input is just a string input at this point, so I'm quite stuck, and it also contains any arguments or other code.
As an example, the input may be "alert('test')" and that would be valid, and I would like to run that, however something like "madeUpFunction(lol)" would be invalid.
I'm happy if I can just get functions working and not any JS code.
You can extract the string up until the first ( in order to get the function name, and then test that it exists using typeof eval(funcName). Then use the Function constructor to make sure that the syntax is valid for the rest of the arguments without actually executing the code.
You can then return the function which executes what the user entered, but note that there may be security issues if you decide to execute the function.
function parseFunctionCall(str) {
var funcName = str.slice(0, str.indexOf('('));
if (typeof eval(funcName) === 'function') {
return new Function(str);
} else {
throw new Error('Invalid function name');
}
}
console.log(parseFunctionCall("console.log('hi')"));
You can use eval("typeof "+ input) to achieve what you want. The argument of the eval() function is a string. If the string represents an expression, eval() evaluates the expression.
var myFunc = function(){};
var input = prompt('Enter input string');
if(eval("typeof "+input) === "function"){
document.getElementById('d1').innerHTML = "Yes it's a funtion";
}
else{
document.getElementById('d1').innerHTML = "Not a funtion";
}
<div id="d1">
</div>
Assuming this is in a browser and that that function you want to check is in the global scope:
if (typeof window[userInput] === "function" ) {
...
}
I've got a rather large plugin that I am currently writing in jQuery which is using a lot of internal functions that can accept varying arguments depending on the function.
I caught myself constantly writing the following in every function to stop the code from running if an argument hasn't been supplied or isn't valid:
add : function(args) {
if (args===undefined) return;
// function code;
},...
I was hoping that in a DRY type of sense it would be a good idea to write a little internal helper function that would do this for me.
Is this actually a good idea and most importantly what is the best/secure way to check for a varied range of acceptable arguments?
There are a lot of functions with multiple arguments in this plugin, for example:
load : function( filename , path , excludeFromRandom , callback ) {}
where filename is a string,
path is a string,
excludeFromRandom is a boolean and
callback can be a function or a string.
What is a good way to check for the existence and validity of these types of arguments without rewriting the same code over and over?
Any suggestions and ideas would be great.
Thanks for reading.
It depends to what extent you want to do this. In idea would be to create a validation function which takes a argument -> rule mapping. E.g.:
function foo(somestring, somenumber) {
var rules = {
'somestring': Validator.rules.isString,
'somenumber': Validator.rules.inRange(5,10);
};
}
Validator would contain the basic logic and some helper functions (rules):
var Validator = {
valid: function(args, rules) {
for(var name in rules) {
if(!rules[name](args[name])) {
return false;
}
}
return true;
},
rules: {
isString: function(arg) {
return (typeof arg === 'string');
},
inRange: function(x,y) {
return function(arg) {
return !isNaN(+arg) && x <= arg && arg <= y;
}
}
}
}
This is just a sketch, it certainly can be extended (like accepting multiple rules per argument), but it should give you some idea.
That said, you don't have to check every argument. Provide decent documentation. If people use your plugin in a wrong way, i.e. passing wrong argument types, then your code will throw an error anyway.
Update:
If want to do this very often, then a good idea is to write a wrapper function and you just pass the function and the rules to it:
function ensure(func, rules, context) {
context = context || this;
return function() {
if(Validator.valid(arguments, rules)) {
return func.apply(context, arguments);
}
return null; // or throw error, whatever you want
}
}
Then you can define your function normally as:
var foo = function(somestring, somenumber) {
// ...
};
and just add validation to it:
var rules = {...};
foo = ensure(foo, rules);
You could even consider to make ensure accept a callback which gets called on error or success of the function, instead of returning a value. There are a lot of possibilities.