关于JS你该知道的(错误)和不知道的(技巧)
你该知道的(容易犯的错误)
- 忽略异步函数
// Incorrect: Ignoring the asynchronous nature of setTimeout
console.log("Start");
setTimeout(() => console.log("Timeout"), 0);
console.log("End");
// Correct: Understanding and handling asynchronous code
console.log("Start");
setTimeout(() => console.log("Timeout"), 0);
Promise.resolve().then(() => console.log("Promise"));
console.log("End");
- 错误的作用域
// Incorrect: Variable declared without proper scoping
function incorrectScope() {
for (var i = 0; i < 5; i++) {
// 'i' is now global, not local to the loop
}
console.log(i); // Outputs 5
}
// Correct: Using 'let' for block-scoped variables
function correctScope() {
for (let i = 0; i < 5; i++) {
// 'i' is local to the loop block
}
// console.log(i); // Error: 'i' is not defined
}
- 内存泄露
// Incorrect: Creating a memory leak with event listeners
function createMemoryLeak() {
const element = document.getElementById("myElement");
element.addEventListener("click", function handleClick() {
// Some logic
});
// Forgot to remove the event listener
}
// Correct: Removing event listeners to avoid memory leaks
function avoidMemoryLeak() {
const element = document.getElementById("myElement");
function handleClick() {
// Some logic
}
element.addEventListener("click", handleClick);
// Remove the event listener when it's no longer needed
// element.removeEventListener("click", handleClick);
}
- 未处理异常错误
// Incorrect: Inadequate error handling
function fetchData() {
try {
// Fetch data from an API
fetch("https://api.example.com/data")
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.log(error.message));
} catch (error) {
console.log("Error occurred:", error.message); // This won't catch fetch errors
}
}
// Correct: Proper error handling with fetch
async function fetchDataCorrect() {
try {
const response = await fetch("https://api.example.com/data");
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error("Error occurred:", error.message);
}
}
- 忽略浏览器兼容性
// Incorrect: Assuming browser features work uniformly
document.getElementById("myElement").remove(); // Not supported in some older browsers
// Correct: Checking for feature support before usage
const element = document.getElementById("myElement");
if (element && element.remove) {
element.remove();
} else {
// Fallback or alternative approach
element.parentNode.removeChild(element);
}
- 笨重的响应
// Incorrect: Relying solely on a framework without understanding basics
const element = React.createElement("div", null, "Hello, World!");
ReactDOM.render(element, document.getElementById("root"));
// Correct: Understanding the framework and underlying principles
const element = <div>Hello, World!</div>;
ReactDOM.render(element, document.getElementById("root"));
- 低性能的代码
// Incorrect: Inefficient use of loops
const array = [1, 2, 3, 4, 5];
for (let i = 0; i < array.length; i++) {
console.log(array[i]);
}
// Correct: Using forEach for better performance
const array = [1, 2, 3, 4, 5];
array.forEach(item => console.log(item));
- 垃圾注释
// Incorrect: Lack of comments and documentation
function calculateTotal(price, quantity) {
return price * quantity;
}
// Correct: Adding meaningful comments for better understanding
/**
* Calculates the total cost based on the given price and quantity.
* @param {number} price - The unit price of the item.
* @param {number} quantity - The quantity of items.
* @returns {number} The total cost.
*/
function calculateTotal(price, quantity) {
return price * quantity;
}
你不知道的(qi技yin巧)
- 使用别名进行解构 解构赋值是一个强大的功能。您知道可以在赋值期间为变量添加别名吗?
const { prop1: newName1, prop2: newName2 } = object;
在这里,我们将prop1
和分别重命名prop2
为newName1
和newName2
。
- 内存缓存以提高性能 内存缓存是一种缓存函数结果以获得更好性能的技术。这是一个简单的实现:
const memoizedFunction = (function () {
const cache = {};
return function (args) {
if (!(args in cache)) {
cache[args] = computeResult(args);
}
return cache[args];
};
})();
通过缓存结果,我们避免了冗余计算。
- 函数组合的柯里化 柯里化允许创建可重用和可组合的函数。看看这个简洁的柯里化函数:
const curry = (fn, ...args) =>
args.length >= fn.length ? fn(...args) : (...moreArgs) => curry(fn, ...args, ...moreArgs);
这样,您可以轻松创建部分应用的函数。
- 去抖和节流 控制函数执行的速率至关重要。使用去抖和节流来有效处理频繁事件。
const debounce = (func, delay) => {
let timeoutId;
return function (...args) {
const context = this;
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(context, args);
}, delay);
};
};
const throttle = (func, interval) => {
let lastExecTime = 0;
let timeoutId;
return function (...args) {
const context = this;
const currentTime = new Date().getTime();
if (currentTime - lastExecTime >= interval) {
func.apply(context, args);
lastExecTime = currentTime;
} else {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(context, args);
lastExecTime = currentTime;
}, interval - (currentTime - lastExecTime));
}
};
};
这些技术可以防止过多的函数调用,从而提高性能。
- 动态对象键 使用方括号表示法动态创建对象键:
const dynamicKey = 'key';
const obj = { [dynamicKey]: 'value' };
当密钥在运行时确定时,这很方便。
- 可选链接 可选链接简化了嵌套属性的访问,无需进行大量检查。
// Noobs:
let nestedValue;
if (object && object.property && object.property.nested) {
nestedValue = object.property.nested;
} else {
nestedValue = 'default';
}
// Pro:
let nestedValue = object?.property?.nested ?? 'default';
这有助于防止“无法读取未定义的‘嵌套’属性”错误,并使代码更加简洁。
- 箭头函数 箭头函数提供了定义函数的简洁语法。
// Noobs:
function add(a, b) {
return a + b;
}
// Pro:
const add = (a, b) => a + b;
箭头函数对于简短的匿名函数特别有用。
- 数组解构 解构不仅仅适用于对象;也适用于对象。它也适用于数组!
// Noobs:
const array = [1, 2, 3];
const first = array[0];
const second = array[1];
// Pro:
const [first, second] = [1, 2, 3];
这使得数组元素的处理更加简单。
- 对象解构 与数组解构类似,此技术用于对象。
// Noobs:
const user = { name: 'John', age: 30 };
const name = user.name;
const age = user.age;
// Pro:
const { name, age } = { name: 'John', age: 30 };
解构对象以简洁地提取值。
- 验证代理 使用代理对象进行输入验证。
const validator = new Proxy({}, {
set: function (target, prop, value) {
if (prop === 'age' && typeof value !== 'number') {
throw new Error('Age must be a number.');
}
target[prop] = value;
}
});
代理可以拦截和验证属性分配,提供强大的输入控制。
OK
现在已经探索了 10 个高级 JavaScript 技巧。花时间尝试每一种并将它们集成到您的编码工具包中。