Functions
Always write functions. Even if its just an experiment or example code, writing the code as a function provides you with a better representation of the problem at hand.
As a function the code is easier to read and understand defining the code as a verb, can often provide a simpler solution, keeps the namespace (scope) clean, and is portable
Do not use for...in as it requires guard functionality to ensure you are not traversing outside the objects prototype and own properties.
The guard typically used with for...in is
for (const name in object) {
if (object.hasOwnProperty(name)) {
Rather use for...of. With objects you can access keys, properties or both with Object.keys(, Object.values( or Object.entries(
Noise
Noise is code that does nothing but interfere with our ability to read and understand the code. There are many forms of code noise, in your code there are three types of noise.
Redundant and superfluous noise
You have let autoIncrementSchemaFieldName = null When a variable is declared it is automatically set to undefined there is no need to set the value to null
Comments
Comments have there place but comments are almost always because the code is not clear.
You have the comment // Find the auto increment field a clear indication that the code should be a function. If one assumes we know what the code should do then the comment is only noise.
Naming noise
Variable names must be easy to identify. Making names too long does not make code more readable, the reverse is true in a variety of ways.
The following code has a nasty bug that in standard context will not throw an error
let autoIncrementSchemaFieldName;
// ... code may assign name a value ...
autoIncrementSchemaFie1dName = name ?? idProperty;
Due to how we read names typos can be lost in the noise. There is a direct relationship between the length of a name, the chance of introducing an error, and our inability to spot the error.
General rules of thumb for variable name lengths.
- No more than 20 characters
- Use common abbreviation. Do not use ad-hoc or made up abbreviations.
- Infer via context (scope). The smaller the scope the shorter a name can safely be.
Semicolons ;
Yes JavaScript does not require the source code to have semicolons, however to parse JavaScript they are required and are thus inserted automatically before parsing.
Automatic semicolon insertion can be complicated and unless you can, off the top of your head, name all situations that can result in a semicolon not being inserted at the end of a line you should always use semicolons when there is a possibility of a ambiguous end of line.
Strict mode
If your code is not a module you should ALWAYS start the code with the directive "use strict";
Reasons to use Strict mode.
Strict mode will throw errors that are ignored in sloppy mode. Sloppy mode bugs can remain dormant until well after release.
Strict mode code always executes quicker (The optimizer has more optimization options)
Bullet proof
Bullet proof code is code that never exhibits undefined behavior.
Your code is not bullet proof as it does not come with a list of expected behaviors for unexpected data
A list of reasons your code is not bullet proof.
- What if
schema does not contain an autoIncrement nor a property id?
- What if
autoIncrement is not a boolean?
- What if
schema contains non objects?
- What if
schema is not an object?
And maybe outside the functions responsibility, but one would expect it to be.
- What if the object with
autoIncrement is not of type "number"?
- What if the default object is not
type "number" and there is no autoIncrement object?
Rewrite A
The following is a rewrite that matches the behavior of your code.
Note that the code has been moved into a function
"use strict";
function findIncName(schema, defaultName) {
for (const [name, entry] of Object.entries(schema)) {
if (entry.autoIncrement) { return name }
}
return defaultName;
}
console.log(findIncName({id: {}, code: {autoIncrement: true}}, "id"));
console.log(findIncName({id: {}, code: {autoIncrement: false}}, "id"));
Rewrite B
The following addresses some of the problems with the code.
Returns undefined when a name can not be defined according to the rules...
- Name must be of an existing property of schema,
- Be of type
"number"
- Have a boolean property
autoIncrement or be the default name
"use strict";
function findIncName(schema, defaultName) {
if (schema && typeof schema === "object") {
for (const [name, entry] of Object.entries(schema)) {
if (entry?.autoIncrement === true && entry.type === "number") { return name }
}
return schema[defaultName]?.type === "number" ? defaultName : undefined;
}
}