01. Scroll to top method
You can use the scrollTo() method to scroll to a specific location on the page.
window.scrollTo({
top: 0,
behaviour: "smooth",
});
02. Double tilde for Math.floor
Using two tildes (~~) is a quick way to perform a Math.floor operation.
let num = 5.67;
let rounded = ~~num;
03. Converting string to number without parseInt
The plus operator (+) can be used to convert a string to a number.
let str = "42";
let num = +str;
04. The optional chaining operator ?.
The optional chaining operator (?.) allows you to handle potentially undefined properties.
let user = {
address: {
street: "123 Main St"
}
};
let street = user?.address?.street;
05 .The logical OR operator for setting default values
Use the logical OR operator (||) to set default values for your application.
let name = getUsername() || "Guest";
06. Object.entries for iterating over object properties
Object.entries returns an array of a given object’s own enumerable property [key, value] pairs.
let person = { name: "John", age: 30};
for(let [key, value] of Object.entries(person)){
console.log('${key}: ${value}');
}
07. Count h1 on page
This will print the amount of h1 tags on a page.
console.log(document.getElementsByTagName('h1'));
08. Swapping vars without a temporary variable
Example of swapping the values of a and b without using a temporary variable.
let a = 5, b = 10;
[a, b] = [b, a];
09. Using Array.from to create arrays
Array.from can be used to create arrays in a concise way.
let array = Array.from({length: 5}, (_, index) => index + 1);
10. Checking for NaN
NaN is the only value in JavaScript that is not equal to itself.
let value = "Not a Number";
if(value !== value){
console.log("NaN");
}
11. Exponential operator
console.log(2**3); // 8
12. Nullish coalescing operator (??)
The nullish coalescing (??) operator is a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined, and otherwise returns its left-hand side operand.
const foo = null ?? 'default string';
console.log(foo);
// Expected output: "default string"
13. Editplus
Eliminar ids
id="([0-9a-z]+)"
14.
15.
16.
17.
100 lesser known CSS tricks — the ultimate collection
https://medium.com/@creativebyte/100-lesser-known-css-tricks-the-ultimate-collection-675cf8b60031
1. Use `let` and `const` Instead of `var`
Problem: `var` has function scope which can lead to bugs and unpredictable behavior.
Solution: Use `let` and `const` which have block scope.
let count = 0;
const PI = 3.14;
2. Default Parameters
Problem: Functions can fail if arguments are not provided.
Solution: Use default parameters to set fallback values.
function greet(name = 'Guest') {
return `Hello, ${name}!`;
}
console.log(greet()); // "Hello, Guest!"
3. Template Literals
Problem: String concatenation can be cumbersome and error-prone.
Solution: Use template literals for cleaner and more readable string interpolation.
const name = 'John';
const greeting = `Hello, ${name}!`;
console.log(greeting); // "Hello, John!"
4. Destructuring Assignment
Problem: Extracting values from objects and arrays can be verbose.
Solution: Use destructuring assignment to extract values more succinctly.
const user = { name: 'Jane', age: 25 };
const { name, age } = user;
console.log(name, age); // "Jane" 25
5. Arrow Functions
Problem: Traditional function expressions can be verbose and don’t bind `this` lexically.
Solution: Use arrow functions for shorter syntax and lexical `this`.
const add = (a, b) => a + b;
console.log(add(2, 3)); // 5
6. Spread Operator
Problem: Combining arrays or objects can be cumbersome.
Solution: Use the spread operator to easily combine arrays and objects.
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = […arr1, …arr2];
console.log(combined); // [1, 2, 3, 4, 5, 6]
7. Rest Parameters
Problem: Handling a variable number of function arguments can be tricky.
Solution: Use rest parameters to capture all arguments in an array.
function sum(…args) {
return args.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
8. Short-Circuit Evaluation
Problem: Writing conditional statements can be verbose.
Solution: Use short-circuit evaluation to write concise conditions.
const isLoggedIn = true;
const user = isLoggedIn && { name: 'Jane', age: 25 };
console.log(user); // { name: 'Jane', age: 25 }
9. Optional Chaining
Problem: Accessing deeply nested properties can lead to errors if any part of the chain is `null` or `undefined`.
Solution: Use optional chaining to safely access nested properties.
const user = { profile: { name: 'Jane' } };
const userName = user?.profile?.name;
console.log(userName); // "Jane"
10. Nullish Coalescing
Problem: Using `||` to provide default values can give unexpected results if the value is `0` or `””`.
Solution: Use nullish coalescing (`??`) to provide default values only when `null` or `undefined`.
const user = { name: '', age: 0 };
const userName = user.name ?? 'Anonymous';
const userAge = user.age ?? 18;
console.log(userName); // ""
console.log(userAge); // 0
11. Object Property Shorthand
Problem: Assigning variables to object properties can be repetitive.
Solution: Use property shorthand to simplify object creation.
const name = 'Jane';
const age = 25;
const user = { name, age };
console.log(user); // { name: 'Jane', age: 25 }
12. Dynamic Property Names
Problem: Creating objects with dynamic property names can be verbose.
Solution: Use computed property names to dynamically create object properties.
const propName = 'age';
const user = { name: 'Jane', [propName]: 25 };
console.log(user); // { name: 'Jane', age: 25 }
13. Array `map()`, `filter()`, and `reduce()`
Problem: Iterating over arrays to transform, filter, or accumulate values can be repetitive.
Solution: Use `map()`, `filter()`, and `reduce()` for common array operations.
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4]
const sum = numbers.reduce((total, num) => total + num, 0);
console.log(sum); // 15
14. String `includes()`, `startsWith()`, and `endsWith()`
Problem: Checking if a string contains, starts with, or ends with a substring can be verbose.
Solution: Use `includes()`, `startsWith()`, and `endsWith()` for simpler string checks.
const str = 'Hello, world!';
console.log(str.includes('world')); // true
console.log(str.startsWith('Hello')); // true
console.log(str.endsWith('!')); // true
15. Array and Object Destructuring in Function Parameters
Problem: Extracting values from arrays or objects passed as function parameters can be verbose.
Solution: Use destructuring in function parameters to directly extract values.
const user = { name: 'Jane', age: 25 };
function greet({ name, age }) {
return `Hello, ${name}! You are ${age} years old.`;
}
console.log(greet(user)); // "Hello, Jane! You are 25 years old."
16. Default Values in Destructuring
Problem: Handling missing properties when destructuring objects can be cumbersome.
Solution: Use default values in destructuring to provide fallback values.
const user = { name: 'Jane' };
const { name, age = 18 } = user;
console.log(name); // "Jane"
console.log(age); // 18
17. Object `assign()`
Problem: Cloning or merging objects can be verbose and error-prone.
Solution: Use `Object.assign()` to clone or merge objects.
const target = { a: 1 };
const source = { b: 2 };
const merged = Object.assign(target, source);
console.log(merged); // { a: 1, b: 2 }
18. Array `find()` and `findIndex()`
Problem: Finding an element or its index in an array can be cumbersome with loops.
Solution: Use `find()` and `findIndex()` for more readable code.
const users = [
{ id: 1, name: 'Jane' },
{ id: 2, name: 'John' },
];
const user = users.find(u => u.id === 1);
console.log(user); // { id: 1, name: 'Jane' }
const index = users.findIndex(u => u.id === 1);
console.log(index); // 0
19. Array `some()` and `every()`
Problem: Checking if some or all elements in an array meet a condition can be verbose.
Solution: Use `some()` and `every()` for cleaner code.
const numbers = [1, 2, 3, 4, 5];
const hasEven = numbers.some(num => num % 2 === 0);
console.log(hasEven); // true
const allEven = numbers.every(num => num % 2 === 0);
console.log(allEven); // false
20. Array `flat()` and `flatMap()`
Problem: Flattening nested arrays or mapping and flattening arrays can be cumbersome.
Solution: Use `flat()` and `flatMap()` for more readable code.
const nested = [1, [2, [3, [4]]]];
const flat = nested.flat(2);
console.log(flat); // [1, 2, 3, [4]]
const mapped = [1, 2, 3].flatMap(x => [x, x * 2]);
console.log(mapped); // [1, 2, 2, 4, 3, 6]
21. Array `from()` and `of()`
Problem: Creating arrays from iterable objects or arguments can be verbose.
Solution: Use `Array.from()` and `Array.of()` for cleaner code.
const set = new Set([1, 2, 3]);
const arrFromSet = Array.from(set);
console.log(arrFromSet); // [1, 2, 3]
const arrOfNumbers = Array.of(1, 2, 3);
console.log(arrOfNumbers); // [1, 2, 3]
22. Parameter Destructuring in Callbacks
Problem: Accessing properties of objects passed to callbacks can be verbose.
Solution: Use destructuring in callback parameters for cleaner code.
const users = [
{ id: 1, name: 'Jane' },
{ id: 2, name: 'John' },
];
users.forEach(({ id, name }) => {
console.log(`User ID: ${id}, User Name: ${name}`);
});
23. Optional Callback Functions
Problem: Handling optional callback functions can be cumbersome.
Solution: Use short-circuit evaluation to call optional callbacks.
function fetchData(url, callback) {
fetch(url)
.then(response => response.json())
.then(data => {
callback && callback(data);
});
}
24. Promisify Callbacks
Problem: Converting callback-based functions to promises can be cumbersome.
Solution: Use a utility function to promisify callbacks.
function promisify(fn) {
return function (…args) {
return new Promise((resolve, reject) => {
fn(…args, (err, result) => {
if (err) reject(err);
else resolve(result);
});
});
};
}
const readFile = promisify(require('fs').readFile);
readFile('path/to/file.txt', 'utf8')
.then(data => console.log(data))
.catch(err => console.error(err));
25. Async/Await for Synchronous-Like Code
Problem: Writing asynchronous code with promises can be verbose and hard to read.
Solution: Use async/await to write asynchronous code in a synchronous style.
async function fetchData(url) {
try {
const response = await fetch(url);
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData('https://api.example.com/data');
26. Chaining Promises
Problem: Handling multiple asynchronous operations sequentially can be cumbersome.
Solution: Chain promises to handle multiple asynchronous operations.
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
console.log('Data:', data);
return fetch('https://api.example.com/more-data');
})
.then(response => response.json())
.then(moreData => {
console.log('More Data:', moreData);
})
.catch(error => {
console.error('Error:', error);
});
27. Promise.all for Concurrent Execution
Problem: Handling multiple asynchronous operations concurrently can be challenging.
Solution: Use `Promise.all` to handle concurrent asynchronous operations.
const fetchData1 = fetch('https://api.example.com/data1').then(response => response.json());
const fetchData2 = fetch('https://api.example.com/data2').then(response => response.json());
Promise.all([fetchData1, fetchData2])
.then(([data1, data2]) => {
console.log('Data 1:', data1);
console.log('Data 2:', data2);
})
.catch(error => {
console.error('Error:', error);
});
28. Debounce Function
Problem: Frequent function calls, such as during a window resize event, can degrade performance.
Solution: Use a debounce function to limit the rate at which a function is executed.
function debounce(func, wait) {
let timeout;
return function (…args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
window.addEventListener('resize', debounce(() => {
console.log('Window resized');
}, 200));
29. Throttle Function
Problem: Limiting the rate of function execution for events that fire frequently, like scroll or resize.
Solution: Use a throttle function to limit the execution rate of a function.
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function (…args) {
if (!lastRan) {
func.apply(this, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(() => {
if (Date.now() - lastRan >= limit) {
func.apply(this, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
}
window.addEventListener('scroll', throttle(() => {
console.log('Window scrolled');
}, 200));
30. Deep Clone Objects
Problem: Cloning nested objects can be tricky and error-prone.
Solution: Use structured cloning or libraries like Lodash to deep clone objects.
const obj = { a: 1, b: { c: 2 } };
const deepClone = JSON.parse(JSON.stringify(obj));
console.log(deepClone); // { a: 1, b: { c: 2 } }
31. Memoization
Problem: Repeatedly calling expensive functions can degrade performance.
Solution: Use memoization to cache results of expensive function calls.
function memoize(func) {
const cache = new Map();
return function (…args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = func.apply(this, args);
cache.set(key, result);
return result;
};
}
const expensiveFunction = memoize((num) => {
console.log('Computing…');
return num * 2;
});
console.log(expensiveFunction(2)); // "Comput
ing…" 4
console.log(expensiveFunction(2)); // 4
32. Currying Functions
Problem: Creating functions with multiple parameters can be cumbersome.
Solution: Use currying to create functions with partially applied parameters.
function curry(func) {
return function curried(…args) {
if (args.length >= func.length) {
return func.apply(this, args);
}
return function (…nextArgs) {
return curried.apply(this, args.concat(nextArgs));
};
};
}
const sum = (a, b, c) => a + b + c;
const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)); // 6
console.log(curriedSum(1, 2)(3)); // 6
33. Partial Application
Problem: Calling functions with repetitive arguments can be tedious.
Solution: Use partial application to pre-apply some arguments to a function.
function partial(func, …presetArgs) {
return function (…laterArgs) {
return func(…presetArgs, …laterArgs);
};
}
const multiply = (a, b, c) => a * b * c;
const double = partial(multiply, 2);
console.log(double(3, 4)); // 24
34. Function Composition
Problem: Combining multiple functions into a single operation can be cumbersome.
Solution: Use function composition to combine multiple functions.
const compose = (…funcs) => (arg) =>
funcs.reduceRight((prev, fn) => fn(prev), arg);
const add = (x) => x + 1;
const multiply = (x) => x * 2;
const addThenMultiply = compose(multiply, add);
console.log(addThenMultiply(5)); // 12
35. Function Pipelining
Problem: Applying a series of functions to a value can be verbose.
Solution: Use function pipelining to apply a series of functions in sequence.
const pipe = (…funcs) => (arg) =>
funcs.reduce((prev, fn) => fn(prev), arg);
const add = (x) => x + 1;
const multiply = (x) => x * 2;
const addThenMultiply = pipe(add, multiply);
console.log(addThenMultiply(5)); // 12
36. Self-Invoking Functions
Problem: Executing a function immediately upon definition can be cumbersome.
Solution: Use an Immediately Invoked Function Expression (IIFE).
(function () {
console.log('This runs immediately!');
})();
37. Avoid Global Variables
Problem: Global variables can lead to conflicts and unintended side effects.
Solution: Use local variables and modules to avoid polluting the global namespace.
// Using local variables
function doSomething() {
let localVariable = 'This is local';
console.log(localVariable);
}
// Using modules
const myModule = (function () {
let privateVariable = 'This is private';
return {
publicMethod() {
console.log(privateVariable);
},
};
})();
myModule.publicMethod(); // "This is private"
38. Encapsulation with Closures
Problem: Exposing internal details of a function can lead to misuse.
Solution: Use closures to encapsulate internal details.
function createCounter() {
let count = 0;
return {
increment() {
count++;
return count;
},
decrement() {
count - ;
return count;
},
};
}
const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.decrement()); // 1
39. Module Pattern
Problem: Organizing code into reusable modules can be challenging.
Solution: Use the module pattern to create reusable and encapsulated code.
const myModule = (function () {
let privateVariable = 'This is private';
function privateMethod() {
console.log(privateVariable);
}
return {
publicMethod() {
privateMethod();
},
};
})();
myModule.publicMethod(); // "This is private"
40. Singleton Pattern
Problem: Ensuring only one instance of a class is created can be challenging.
Solution: Use the singleton pattern to create a single instance.
const singleton = (function () {
let instance;
function createInstance() {
return {
name: 'Singleton Instance',
};
}
return {
getInstance() {
if (!instance) {
instance = createInstance();
}
return instance;
},
};
})();
const instance1 = singleton.getInstance();
const instance2 = singleton.getInstance();
console.log(instance1 === instance2); // true
41. Factory Pattern
Problem: Creating objects with complex initialization can be cumbersome.
Solution: Use the factory pattern to create objects.
function createUser(name, role) {
return {
name,
role,
sayHello() {
console.log(`Hello, my name is ${this.name} and I am a ${this.role}`);
},
};
}
const admin = createUser('Alice', 'admin');
const user = createUser('Bob', 'user');
admin.sayHello(); // "Hello, my name is Alice and I am an admin"
user.sayHello(); // "Hello, my name is Bob and I am a user"
42. Observer Pattern
Problem: Managing state changes and notifying multiple components can be challenging.
Solution: Use the observer pattern to manage state changes and notify observers.
function Subject() {
this.observers = [];
}
Subject.prototype = {
subscribe(observer) {
this.observers.push(observer);
},
unsubscribe(observer) {
this.observers = this.observers.filter((obs) => obs !== observer);
},
notify(data) {
this.observers.forEach((observer) => observer.update(data));
},
};
function Observer(name) {
this.name = name;
}
Observer.prototype.update = function (data) {
console.log(`${this.name} received data: ${data}`);
};
const subject = new Subject();
const observer1 = new Observer('Observer 1');
const observer2 = new Observer('Observer 2');
subject.subscribe(observer1);
subject.subscribe(observer2);
subject.notify('New data available'); // "Observer 1 received data: New data available" "Observer 2 received data: New data available"
43. Event Delegation
Problem: Adding event listeners to multiple elements can degrade performance.
Solution: Use event delegation to manage events efficiently.
document.getElementById('parent').addEventListener('click', (event) => {
if (event.target && event.target.matches('button.className')) {
console.log('Button clicked:', event.target.textContent);
}
});
44. Avoid Using `eval()`
Problem: Using `eval()` can lead to security vulnerabilities and performance issues.
Solution: Avoid using `eval()` and use safer alternatives.
// Avoid
const code = 'console.log("Hello, world!")';
eval(code); // "Hello, world!"
// Use safer alternatives
const func = new Function('console.log("Hello, world!")');
func(); // "Hello, world!"
45. Using `for…of` for Iteration
Problem: Iterating over arrays with `for…in` can be error-prone.
Solution: Use `for…of` to iterate over arrays and other iterable objects.
const arr = [1, 2, 3, 4, 5];
for (const value of arr) {
console.log(value);
}
// 1
// 2
// 3
// 4
// 5
Do not use ~~x to truncate numbers to integers; use Math.trunc() instead. Due to using 32-bit representation for numbers, both ~-1 and ~4294967295 (232 - 1) result in 0.