I found out earlier today that split() doesn't work if attached to a single value.
I would like to write my own split() method so that if I sent it a single value, it creates an array with a single value.
Q: Should I change the split prototype or write a function?
var SPLIT=function(X) {
return X.toString().split()
}
To clarify, split() does work with a "single value". The problem in your last question was that the value returned was not a string, and hence the .toString() is necessary.
In my opinion, there's no need to write another function for this. Simply remember to convert your values to a string before calling .split() on it.
If you must have a function that does this, then to answer your question, create a new function and don't modify the prototype. While it may seem harmless to modify the prototype of Number or Object in this case, it's generally considered bad practice as other code (e.g. libraries you're using) may not be expecting it.
Related
So I have came across a curious question that I can't find its answer anywhere and there isn't much documentation on what eval does when you pass to it string literals.
If I do eval("alert(1)") I will get an alert box with 1, however, when I do eval`alert(1)` I just get an array with "alert(1)" I am not sure where that is coming from, isn't it supposed to be treated the same as the previous example?
Also, eval`${1}` returns an array with two empty elements, why?
What you're running into is something to do with tagged templates.
Essentially, you are doing string interpolation and using a function to decide how to create the string. The first argument is expected to be an Array that contains all of the string parts (everything between ${var} declarations). The return of any function used this way is expected to be the string. The reason you are seeing 2 entries is because this function returns a raw format in addition to the one it tried to create using the tag function.
I have an interesting task for the job interview.
String with numbers and underscores must be converted to the number with just one native function call. This code will work only in Chrome.
someFunc('1_22_333') = 122333;
Does anyone know what this function is? Maybe this is one of the new features?
Maybe a trick question? Chrome will convert 1_22_333 to 122333 without any function applied at all, because ES6 supports underscores in numbers by default.
If it's a string, however, Number(), parseInt(), and parseFloat() either fail with NaN or just give you a 1, stopping at the first underscore.
There is one function that will do the trick, however: the dreaded eval().
with just one native function call
Emphasis mine. If this is the exact requirement, then you can try to skirt the rules. The answer from kshetline already shows you can use eval but if it was me who was giving the interview, I'd very much want people to not use eval. So, for me the one function call requirement can be fulfilled by using replace:
function someFunc(arg) {
return +arg.replace(/_/g, "")
}
console.log(someFunc('1_22_333'))
So, this is one call to String#replace and the unary plus operator.
This is somewhat exploiting technicalities, however:
The question never specifies not to use operators, it just says single function call. Since the requirement doesn't explicitly forbid non-function operations, then the operator is not outside the rules.
.replace is also a method not a function, since it's a property of the String object. However, this is a bit more of a philosophical distinction - you can certainly point out that JS has a very loose distinction between methods and functions. All methods are simply functions that are attached to an object and (usually but not always) use the this context.
If that second point is contested, then feel free to bend the rules even harder - if a method won't cut it, then a method shouldn't count as part of the requirement for one function call. The same way the + operator doesn't count. So, in that case, this code should pass the requirement:
function someFunc(arg) {
var method = String.prototype.replace;
var fn = method.bind(arg);
return +fn(/_/g, "");
}
console.log(someFunc('1_22_333'))
I've broken it down for easier reasoning. You can also just write +String.prototype.replace.bind(arg)(/_/g, "")
String.prototype.replace is not a function call, it's fetching a value of an object. In this case it's the String prototype but doesn't matter.
Function#bind is a method call. If it doesn't count as a function, then it's allowed. This will return a new function that you can execute. If somebody complained that technically .replace is a method, then technically, the return result of .bind is definitely not.
This is creative interpretation on many point but I still find it a better answer than eval.
split() is a prototype function in JavaScript which can be called on a string and accepts a string value (and returns an array) e.g."hello world".split(" ") will split the "hello world" string on spaces (i.e will return an array: ["hello", "world"]
split() JS documentary:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split
join() is a prototype function in JavaScript which can be called on an array and accepts a string value (and returns a string) e.g. ["my", "name", "is", "Sam"].join(" ") will return my name is Sam
join() JS documentary:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/join#:~:text=The%20join()%20method%20creates,returned%20without%20using%20the%20separator.
Soo, a combination of split().join() is similar to a replace function but is more reliable
So split on the "_" character ("1_22_333".split("_") will return ["1", "22", "333"] and join("") on that array will return "122333"
const num = "1_22_333";
const newNum = Number(num.split("_").join(""))
I have a text input.
I want the user to be able to fill out a value in that text input like some of these examples:
results[0].address_components[0].long_name
results[0].formatted_address
fo.o[0].bar (where fo.o is a single key)
etc. (pretty much literally anything)
Then I want to take that value and use it as a key on some parsed JSON. So like...
$.parseJSON('data.json').results[0].address_components[0].long_name would return something like San Francisco.
How can I do this?
If I save the input value as a variable, say selector, and then try $.parseJSON('data.json')[selector] it just comes back undefined.
If I try to regex the selector and convert all instances of [ into . and remove all ] and split at . then reduce, then selectors like fo.o (one key) will break...
Thanks in advance!
You should generally set the results of parseJSON to a variable, rather than parse it every time you access it. parseJSON is generally going to go down to C code (depending on the environment), but it will still be really inefficient to call it over and over.
var res = $.parseJSON('data.json');
From there, you can access it like you would any other JavaScript object:
res.results, which is identical to res["results"] (which, in your case appears to be some kind of array).
A string key with special characters (., -, and pretty much anything non a-zA-Z0-9) is always accessed via the second form: res["fo.o"].
Note that this chains, so you can access res["fo.o"]["bar"] exactly as you'd address res["fo.o"].bar.
I would recommend using a JavaScript library like lodash for this (if this is feasible in your project, otherwise looking at its implementation might help):
It provides a large set of utility functions. The get function does exactly what you are looking for, namely it resolves a path on an object.
Sample code (assuming _ is your lodash reference):
var path = 'results[0].address_components[0].long_name'; // the user input
var data = $.parse('data.json');
var result = _.get(data, path); // resolves the path on the data object
As for the fo.o property name, I doubt there would be an easy solution, as this essentially makes your syntax ambiguous. How would you distinguish between a property fo.o and fo?
use eval. You would put everything as a string. So just concatenate strings based on the input. Then eval it. for example:
var str = "$.parseJSON('data.json').results[0].address_components[0].long_name";
and then eval it at runtime.
var result = eval(str);
Every time I assign a string, I'd actually like to assign a string object, without the extra code.
This var foo = "bar";
becomes var foo = new String("bar");
Basically hi-jacking the assignment.
Follow-up:
If the above is not possible is there a way to prototype the string variable type, rather than the String object?
As pointed out by armando, the foo would be a string type, but is essentially a customized array. It would be nice to be able to prototype functions to that class.
No this is not possible
If it was possible, you really would not want to do this, at least not globally.
The string variable type does not have all the extra overhead that an object does.
Note: the string array that is created (in your case, foo) would have other properties (eg foo.length)
Objects come at a performance hit
It's not quite what you're looking for, but you may want to look at Overriding assignment operator in JS
My JavaScript code stores a lot of data in arrays. I want to retrieve a key using something similar to what I wrote below. It key that should be retrieved is based on variables that are page-dependent . The following code doesn't work. Can anyone give me a solution to this problem?
This is part of a script that does automatic conjugation. (looks for SUBJECT in a div and then looks for VERB in another div and then conjugates the verb by retrieving the conjugated form from the array)
function getarray(Array,Key) {
return Array[Key];
}
Example of how it should work:
verb = innerhtmlfromdiv;
subject = innerhtmlfromotherdiv;
function getarray(Array,Key) {
return Array[Key]; }
conjugatedverb = getarray(verb,subject);
htmltextbox.value = conjugatedverb;
First off, what you want is an Object, not an Array. I'm guessing that you're new to javascript and your previous language was either PHP or PERL, and so you think what you're using is an "Associative Array".
The basics: There is no such thing as Associative arrays in Javascript. There is Objects, and a non-primitive subclass of Object called Array, which has some methods for dealing with Numericly named object properties, and a magic length property.
Since the keys you are dealing with are strings, not numbers, you have no use for Arrays.
Javascript Objects on the other hand are similar to an Associative array in php, or a hash in perl. (but they are not exactly the same thing).
As you have no doubt discovered, with an Object, you can use subscript notation to access certain properties, as in
verbs["go"] = "went";
this is equivilent to
verbs.go = "went";
a common mistake is to think that the dot notation is only used for objects, and the subscript notation for "associative arrays", because this is how it works in PHP. In javascript the two notations are interchangable. Since Arrays are a subclass of Object, the above examples work on them as well (but they don't use any special properties of Arrays).
As for your specific problem:
You need an object full of objects.
so for instance
var verbs = {
"do":{"Truck":"Drive","Blender":"Turn On","Bike":"Ride"},
"take":{"Money":"Steal","Julie":"Accompany","Lever":"Pull}
}
then your function would be:
function conjugate (verb, subject) {
return verbs[verb][subject];
}
and an example of its use would be
conjugate("do","Truck") // returns "Drive"
Try changing the parameter name Array to something else. Array is the name of a built-in function/object in javascript.
I don't quite get the point of the function. This is like writing:
function getValue(var) {return var}
Why not just get the value the normal way without wrapping it in a useless function:
conjugatedverb = verb[subject];
htmltextbox.value = conjugatedverb;
Also, your code doesn't make sense when you claim to do an innerHTML from an element and somehow get an object instead of a string. What is really going on? I think your problem starts even before this snippet of code.