I have been studying coding for 3 months and this is my first question to ask here. I am coding an application that will help Turkish learners conjugate Turkish words. I wrote some of the code using procedural way with functions, and now I want to refactor the code with OOP. Thus, I created a class and extended it to String class (Because I want to be able to use string methods for words). Then I wrote some public fields related to my class name.
class TurkishLettersData extends String
turkishAlphabet = {
v: {
voicing: "voiced",
...
},
ş: {
voicing: "voiceless",
...
}
}
The object goes much longer than that and there are several arrays following the object. I will use the object for word conjugation. More on that below.
As I wanted to use the parameter of the String class, I did not write a constructor function or super function. I can still use the parameter of String class while creating an instance.
When I wanted to add a method that would find the first letter of words, I encountered this problem. Basically, I want to code the part below:
findFirstLetter() {
return this.xxxxx.at(0)
}
However, as I do not know the name of the parameter of the String object, I cannot write any method to my class.
I searched the internet and asked the same question to ChatGPT to no avail.
So, what is the name of the parameter of String Object in JS?
EDIT:
Thank you everyone. I could solve my problem for now following Felix Kling's suggestion (return this.at(0)). I will check Bergi's idea of using composition and edit the question again.
I will use the turkishAlphabet object for word conjugation. For instance, the prepositions in on at are translated to Turkish as -de or -te suffixes (there are more though.) Even though the suffixes mean the same, the final letter of the word these suffixes will be used affects which one to use and there are several conditions for it. If the word ends with a voiced consonant (ev for house), we say evde (at the house), but if it ends with a voiceless consonant (iş for work), we say işte (at the work). A findLastLetter() method will find the last letter and check whether that letter is voiced or voiceless. This is just a small example.
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.
This question already has answers here:
trying to convert a letter to uppercase using .toUpperCase()... doesn't work?
(2 answers)
Closed 6 years ago.
I writing a small program that takes the English and the Spanish version of a word from two user inputs and stores them as objects:
function Dictionary(english, foreign){
this.english = english;
this.foreign = foreign;
}
Thes objects are then stored in an array; objectsArray[].
I then assign a method to the "Dictionary" prototype to make the inputted strings into uppercase:
Dictionary.prototype.capMethod = function(){
this.english.toUpperCase();
this.foreign.toUpperCase();
}
Once the user has then inputted all the translations (which they will later be tested on), I try to call the dictionaries' capMethod:
for(var x in objectsArray){
objectsArray[x].capMethod();
console.log(objectsArray[x].english + objectsArray[x].foreign + typeof objectsArray[x].english); }
The console, however, does not suggest they have been changed to uppercase. This is corroborated when the english and foreign values are returned to the user (later in the program) still as they were inputted.
I stress that there are other parts of the program where I could make this change but not understanding my mistake here seems like a poor reason to do it another way.
I do need to capitalise the strings that are stored in the dictionaries and there is ALOT of code around it so a JSfiddle would be cumbersome, I hope the above will be enough as the problem really seems to lie in the way I'm referencing the objects values. I also know there are several subtly different ways to reference object properties but I'm new to javascript and am struggling to wrap my head around it.
What am I doing wrong here?
in your function
Dictionary.prototype.capMethod = function(){
this.english.toUpperCase();
this.foreign.toUpperCase();
}
the result of the 'toUpperCase()' is not used.
this.english = this.english.toUpperCase();
would be better.
Would storing objects like this work for you?:
function store(english,foreign){
objectsArray.push({
english:english.toUpperCase(),
foreign:foreign.toUpperCase())
}
So, I dived head first in Marijn Haverbeke's Eloquent Javascript and swam directly to the Electronic Life chapter.
There we observe the spontaneous generation of an object :
{"#": Wall,"o": BouncingCritter}
Wall and BouncingCritter are defined elsewere :
function Wall() {}
function BouncingCritter() {
this.direction = randomElement(directionNames);
this.name = word();
};
BouncingCritter.prototype.act = function(view) {
if (view.look(this.direction) != " ")
this.direction = view.find(" ") || "s";
return {type: "move", direction: this.direction};
};
BouncingCritter.prototype.toString=function(){
return this.name +"\t"+ this.direction;
}
---> I don't get what sorcery is happening there.
Well, I see we're creating an object on the fly, and since it's going to be used only once, no need to define a class. OK.
I understand that hitherto this anonymous object has two properties, which are themselves classes, that will be instantiated several times down the road. I'm starting to flutter but I'll get along. One of those (Wall) is quite empty, which will later prove useful as "nothing" is somewhat better than 'undefined'. Fine.
What I don't get is the use of string constants "#" and "o" on the left hand side of the colon. Could someone please expand on this ?
Heartly thanking,
What I don't get is the use of string constants "#" and "o" on the left hand side of the colon. Could someone please expand on this ?
The property has to be called something. Those are just rather unhelpful names which tell you nothing about what the property actually holds.
… until you look at the context. From the link you provided:
The “#” characters in this plan represent walls and rocks, and the “o” characters represent critters.
It's using # as the name for the wall property because that is the symbol used to render it in the UI. Ditto "o"/citter.
(That still isn't a great name though: It tightly couples the internal name to the presentation of it, which would start to fall apart if the UI was later changed to use (for example) pretty graphics instead of ASCII art)
In this scenario it's more like a dictionnary. It just use to say that the character # or o represent respectivly the class Wall and BouncingCritter.
Edit (after reading your book as fast as i could): When he instanciate the World(map, legend), legend is the dictionnary. Later in the code he creates the grid and for every characters from the string representation of the world, he instanciates the correct class according to the legend dictionnary he gave var element = new legend[ch]();.
OK folks, thanks for your answers. I dug a bit further and came across a very clear and concise (nifty, indeed) explanation as to the ways of the object literal notation : Nifty Javascript - Objects.
What confused me most at first in
{"#": Wall,"o": BouncingCritter}
are the quotes surrounding properties names, and the fact that "#" would otherwise be an illegal character for a property name.
To wrap my head around this, I had to write it down, and I share below, for what it's worth.
The "legend" is anonymous classless object defined, when we construct the World,
by the block {"#": Wall,"o": BouncingCritter}
Says Marjin :
A legend is an object that tells us what each character
in the map means. It contains a constructor for every
character—except for the space character, which always
refers to null, the value we’ll use to represent empty
space.
In the World constructor, we populate the grid.space array according to what we
read from the 'map' (which is instantiated by the array 'plan').
The character read from the map (either 'o' or '#') serves as the key in the
hashtable (a.k.a "object") 'legend'. The corresponding value is a class (either
'Wall' or 'BouncingCritter') which is then instanciated. The resulting object is
finally stored in the grid.space array.
Note that the original literal notation {"#": Wall,"o": BouncingCritter} for
creation and the subsequent employ of square brackets in the function
'elementFromChar'
var element = new legend[ch]();
allows for the use of the
otherwise illegal character '#' as the name of the property.
Here be rant :
Needless to say, I'm not very happy with all this. I guess it's the kind of stunt that gives javascript a bad reputation sometimes. All in all, I'm starting to consider that the title of the book, "Eloquent Javascript", may be a little overstated or even plain misleading.
Granted, it is an impressive demonstration of object-fu maestria, but neither the code nor the text are specially clear. I had a very hard time stitching the code patches together and getting the project to work and I feel that the object breakdown used to model the problem is overly complicated. But heck, I'm learning, so my opinion is completely unauthorized ;-)
end-of-rant
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.
Every time i pass some parameters to a JavasScript or jQuery functon, i use some random letters. What are the correct letters for the corresponding variable types?
function(o){} for example is for a object. But what are the other letters? Do someone have a list of those?
I advise you not to assign names according to types but according to the data that the variable contain. If you pass an object that contains the configuration for a function call the variable configuration if you pass a variable that contains a name call it name and so on. In this way the code is more readable and understandable.
Any letter will do, there is no such thing as a standard for using letters as parameters.
However, using letters for parameters is bad practise, because a letter does not describe what the parameter is intended for.
Consider this example:
function ShowBusyCursor(s) {
//...
}
If you look at the function header, you cannot guess what the parameter s stands for. But if you change the code to this:
function ShowBusyCursor(cursorIsDisplayed) {
//...
}
The parameter cursorIsDisplayed is a lot more developer-friendly and tells you it's a boolean that can be set to true to display the cursor. If you used s, you would have to look into the code to figure that out.
Here is a good list of letters I could think of:
o - object
a - array
s - string
d - date
n - number
r - regexp
b - boolean
But seriously, jokes apart, I think you might be mixing up the packed/minified source with the actual source that developers write. For example, this little function looked like this originally:
function myFunction(personName) {
this.name = personName;
}
But after minifying, it becomes:
function myFunction(a){this.name=a}
packer is one such utility by Dean Edwards that will minify your Javascript. Play with your source code at this website and see the compressed output. Check the Shrink variables option on the right to see how parameters and other variables get renamed.
This however shouldn't affect how you write your code at all. Be it Javascript, or any other language, all identifiers - variables, function names, class names, etc. should be named after what they represent or do rather than obscure shorthands.
Re-iterating what mck89 said, it's better to go with explanatory variable names rather than just a letter for the type. What if you have more than one parameter of the same time, do you start appending numbers?
I have often seen explanatory variable names which include the type, for instance sFirstName would be a string denoted by the "s", bForce would be a boolean, oConfig would be an object and nSubTotal would be a number.
This is a variation of Hungarian notation, and I'd advise against using single-letter variable names. What if you need to pass in 2 of any one data type? Like others have said, it also doesn't represent the meaning of the variable very well. I think this is much better:
function foo(sFirstName, sLastName)
{
alert("Hi, my name is " + sFirstName + " " + sLastName);
}