在 Javascript 和 ReactJS 中你应该(几乎)永远不要做的 10 件事(附代码示例)

文章列举了在JavaScript编程中应避免的事项,包括使用全局变量、eval()函数、阻塞主线程、过多DOM操作和忽略错误处理。同时,强调了ReactJS开发中应注意的问题,如直接操作DOM、在render中使用setState、过度使用有状态组件以及忽视性能优化。建议开发者遵循最佳实践,确保代码的可维护性和高效性。
摘要由CSDN通过智能技术生成

Javascript——要避免的事情
作为一般准则,为了编写可维护且高效的代码,您应该避免使用 JavaScript 做以下十件事:

1.避免使用全局变量
全局变量会导致命名冲突,使调试变得困难,并导致意想不到的后果。使用局部变量并遵循适当的范围界定技术。

例子:
// Avoid using global variables

// Outdated: Using var for global variable declaration
var globalVar = ‘I am a global variable’;

function foo() {
console.log(globalVar);
}

foo(); // Outputs: I am a global variable

// Updated: Using let for local variable declaration
let localVar = ‘I am a local variable’;

function bar() {
let localVar = ‘I am a local variable inside a function’; // Shadows the globalVar
console.log(localVar);
}

bar(); // Outputs: I am a local variable inside a function
console.log(localVar); // Outputs: I am a local variable

// Updated: Using const for constant variable declaration
const constVar = ‘I am a constant variable’;

// Trying to reassign a constant variable will result in an error
// constVar = ‘Trying to reassign a constant variable’; // Throws an error

在此示例中,我们避免使用全局变量,而是在适当的函数范围内使用局部变量。是globalVar一个全局变量,可以从代码的任何部分访问,但它也可能导致命名冲突和意外后果。另一方面,localVarandinnerVar是局部变量,它们分别在demonstrateLocalVariables函数和 theinnerFunction范围内。这有助于防止命名冲突,使调试更容易,并产生更可预测的代码行为。

  1. 避免使用 eval()
    使用 eval() 会带来安全风险和潜在漏洞,因为它会执行任意代码。尽可能使用替代方法,例如使用 JSON.parse() 来解析 JSON 数据。

3.避免阻塞主线程
JavaScript 在单线程环境中运行,长时间运行的任务阻塞主线程会导致用户界面无响应。使用异步编程技术,例如 Promises 或 async/await,以避免阻塞主线程。

例子:
// Function that simulates a long-running task
function doSomeLongRunningTask() {
return new Promise((resolve) => {
setTimeout(() => {
console.log(‘Long-running task complete’);
resolve();
}, 3000); // Simulating a 3-second task
});
}

// Function that uses Promises to avoid blocking the main thread
function runAsyncTask() {
console.log(‘Starting asynchronous task’);
return doSomeLongRunningTask()
.then(() => {
console.log(‘Asynchronous task complete’);
})
.catch((error) => {
console.error(‘Error in asynchronous task:’, error);
});
}

console.log(‘Before running asynchronous task’);
runAsyncTask();
console.log(‘After running asynchronous task’);

// Output:
// Before running asynchronous task
// Starting asynchronous task
// After running asynchronous task
// Long-running task complete
// Asynchronous task complete
在此示例中,doSomeLongRunningTask()模拟需要 3 秒才能完成的长时间运行的任务。我们没有阻塞主线程并导致用户界面无响应,而是将任务包装在 Promise 中并使用.then()和.catch()来处理异步结果。这允许主线程继续运行,并且用户界面在执行长时间运行的任务期间保持响应。

4.避免过多的DOM操作
就性能而言,操作 DOM(文档对象模型)可能代价高昂。尽可能减少不必要的 DOM 操作、批量 DOM 更新并使用事件委托。

例子:
// Bad practice: Excessive DOM manipulation
function updateElementInnerTextBad() {
for (let i = 0; i < 1000; i++) {
const element = document.createElement(‘p’);
element.innerText = Element ${i};
document.body.appendChild(element);
}
}

// Good practice: Minimize DOM manipulation
function updateElementInnerTextGood() {
const container = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
const element = document.createElement(‘p’);
element.innerText = Element ${i};
container.appendChild(element);
}
document.body.appendChild(container);
}

// Call updateElementInnerTextBad
console.time(‘Bad DOM manipulation’);
updateElementInnerTextBad();
console.timeEnd(‘Bad DOM manipulation’);

// Call updateElementInnerTextGood
console.time(‘Good DOM manipulation’);
updateElementInnerTextGood();
console.timeEnd(‘Good DOM manipulation’);
在此示例中,我们有两个函数updateElementInnerTextBad,updateElementInnerTextGood它们创建 1000 个

元素并将其附加到 DOM。但是,updateElementInnerTextBad直接在循环中操作 DOM,这可能效率低下并导致性能问题。另一方面,updateElementInnerTextGood通过创建文档片段、将元素附加到片段,然后在单个操作中将整个片段附加到 DOM,最大限度地减少 DOM 操作。这种方法更有效并且可以带来更好的性能,尤其是在处理大量 DOM 元素时。

5.避免忽略错误处理
忽视错误处理会导致意外行为和调试困难。始终适当地处理错误并使用 try-catch 块或错误回调来优雅地处理 JavaScript 代码中的错误。

例子:
// Bad practice: Ignoring error handling
function badErrorHandling() {
try {
// Code that may throw an error
const result = someFunctionThatMayThrowError();
console.log(Result: ${result});
} catch (error) {
// Ignoring the error
}
}

// Good practice: Proper error handling
function goodErrorHandling() {
try {
// Code that may throw an error
const result = someFunctionThatMayThrowError();
console.log(Result: ${result});
} catch (error) {
// Handle the error appropriately
console.error(Error: ${error.message});
}
}

// Call badErrorHandling
console.log(‘Bad Error Handling:’);
badErrorHandling(); // Error may be silently ignored

// Call goodErrorHandling
console.log(‘Good Error Handling:’);
goodErrorHandling(); // Error will be properly handled
在此示例中,我们有两个函数badErrorHandling,goodErrorHandling它们使用 try-catch 块来处理函数抛出的潜在错误someFunctionThatMayThrowError()。但是,badErrorHandling通过不对其执行任何操作来忽略错误,这可能会导致无提示故障并使调试问题变得困难。另一方面,goodErrorHandling通过使用方法将错误消息记录到控制台来正确处理错误console.error()。这允许更好的错误识别和解决,使代码更健壮和可靠。

  1. 避免使用同步 XMLHttpRequest (XHR) 请求
    同步 XHR 请求会阻塞主线程并对用户体验产生负面影响。使用异步 XMLHttpRequest 或现代替代方案(如 Fetch API 或 Axios)进行异步数据检索。

  2. 避免使用过时或不必要的 JavaScript 功能
    JavaScript 是一种不断发展的语言,了解最新的语言特性和最佳实践非常重要。避免使用可能不再被推荐或支持的已弃用或过时的 JavaScript 功能。

以下是现代 JavaScript 开发中应避免的 10 个过时的 JavaScript 特性:

varfor 变量声明:var是在 JavaScript 中声明变量的旧方法,并且有一些怪癖和局限性,例如没有块级作用域并且容易提升。建议使用letorconst代替变量声明。

function用于定义函数的关键字:function用于定义函数的关键字有一些限制,例如不支持箭头函数,并且可能存在作用域和提升问题。建议改用箭头函数或function表达式。

==用于相等比较:由于类型强制,松散相等比较可能会产生意想不到的结果。建议使用严格相等比较来=避免类型强制问题。

document.write():此功能过去常用于将内容直接写入 HTML 文档,但它被认为已过时并且会导致文档结构、性能和安全性问题。建议改用 DOM 操作方法。

eval():此函数将一串 JavaScript 代码作为代码执行,由于潜在的安全风险、代码注入漏洞和性能问题,这可能很危险。一般不建议在现代 JavaScript 代码中使用eval()。

arguments对象:arguments对象在过去常用于访问函数参数,但它有局限性并且容易出错。建议改用剩余参数或扩展语法。

for…in用于迭代对象的循环:for…in循环可能存在可枚举属性和原型链遍历问题。建议使用for…oforObject.keys()迭代对象属性。

escape()和unescape():这些函数用于 URL 编码和解码,但它们被认为已过时且不安全。建议使用encodeURIComponent()anddecodeURIComponent()代替。

proto:此属性用于访问对象的原型,但它被认为已过时并且已被弃用,以支持Object.getPrototypeOf()并Object.setPrototypeOf()获得更好的性能和兼容性。

with():此语句用于为对象属性创建临时范围,但被认为已过时且容易出错。它可能导致意外行为,不建议在现代 JavaScript 代码中使用。

务必了解最新的 JavaScript 标准和最佳实践,并避免使用可能导致现代 JavaScript 开发中的性能、安全性和兼容性问题的过时功能。

8.避免过度使用或低效使用循环
循环可能会占用大量资源,尤其是对于大型数据集。注意循环性能,并使用 map()、filter() 和 reduce() 等技术来实现更高效、更简洁的数组操作。

例子:
// Inefficient use of loops
const numbers = [1, 2, 3, 4, 5];
const sum = 0;

for (let i = 0; i < numbers.length; i++) {
sum += numbers[i];
}

console.log(sum);
在此示例中,我们使用for循环来计算数字数组的总和。然而,这种方法效率低下,因为它需要使用索引访问数组中的每个元素,并且即使我们只需要计算和,循环也需要遍历整个数组。

一种更有效的方法是使用reduce()方法,它允许我们在单次迭代中计算总和,而不需要循环:
// Efficient use of reduce method
const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((acc, curr) => acc + curr, 0);

console.log(sum);
在这个更新的例子中,我们使用方法reduce()来计算数字数组的总和。该reduce()方法以回调函数为参数,对数组的每个元素调用,并将结果累加到参数中acc。0方法中的第二个参数reduce()指定累加器的初始值。这种方法更有效,因为它避免了不必要的迭代并提供了更简洁和可读的代码。

  1. 避免在主线程中使用阻塞或 CPU 密集型操作
    JavaScript 是单线程的,CPU 密集型操作会导致浏览器无响应。将繁重的计算或耗时的任务卸载到 Web Worker 或其他后台线程。

例子:
// Blocking operation in the main thread
function fibonacci(n) {
if (n <= 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}

// Blocking operation in the main thread
console.log(fibonacci(40));
在这个例子中,我们有一个使用递归计算斐波那契数列的函数。然而,这种方法是阻塞和 CPU 密集型的,因为它执行多次递归调用,导致计算时间长。如果使用较大的 值调用此函数n,它会阻塞主线程并导致浏览器变得无响应。

为了避免阻塞主线程,我们可以使用异步技术,例如 Web Workers 或 Promises,将 CPU 密集型任务卸载到单独的线程或使用非阻塞算法。下面是一个使用 Web Worker 的例子:
// Using Web Workers to offload computation to a separate thread
// main.js
const worker = new Worker(‘fibonacciWorker.js’);

worker.postMessage(40); // Send data to the worker

worker.onmessage = function(event) {
console.log(event.data); // Receive computed result from the worker
};

// fibonacciWorker.js
function fibonacci(n) {
if (n <= 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}

self.onmessage = function(event) {
const result = fibonacci(event.data); // Compute result
self.postMessage(result); // Send result back to the main thread
};
在这个更新的示例中,我们使用一个单独的 Web Worker 来执行 Fibonacci 计算,让主线程可以自由处理用户交互并防止阻塞。方法postMessage()用于在主线程和worker之间发送数据,事件onmessage用于接收计算结果。这种方法确保主线程保持响应并提供更好的用户体验。

10.避免仅仅依赖客户端验证
可以绕过客户端验证,这不是可靠的安全措施。始终在服务器端验证输入以确保数据完整性和安全性。

ReactJS——要避免的事情
由于 React 是用于构建用户界面的流行 JavaScript 库,因此在使用 React 时要避免做以下十件事,以确保代码高效且可维护:

1.避免直接操作DOM
React 旨在通过其虚拟 DOM (vDOM) 抽象有效地管理 DOM。document.getElementById避免使用or等​​技术直接操作 DOM innerHTML,而是使用 React 的声明式方法来管理 UI。

setState2.避免在render方法 中 使用
setState在方法中使用修改状态render会导致渲染的无限循环。render通过只渲染基于道具和状态的 UI 组件来保持方法的纯净。

3.避免使用太多不必要的重新渲染
重新渲染会影响性能。shouldComponentUpdate通过使用、React.memo或PureComponent来优化组件渲染,避免不必要的重新渲染。

4.避免使用forceUpdate
在大多数情况下应避免使用forceUpdate,因为它会绕过 React 的正常重新渲染机制并可能导致不可预测的行为。

5.避免refs过度 使用
虽然refs对于访问 DOM 元素或管理焦点很有用,但过度使用refs会导致代码变得面条状,并使管理应用程序中的状态和数据流变得更加困难。更喜欢提升状态或使用回调函数来管理组件交互。

6.避免使用大量有状态组件
在具有大量有状态组件的大型应用程序中,管理状态可能会变得复杂。考虑使用 Redux 或 MobX 等状态管理库来更有效地集中和管理应用程序状态。

例子:
import React, { useState } from ‘react’;

const App = () => {
const [count, setCount] = useState(0);

const increment = () => {
setCount(count + 1);
};

return (


Count: {count}


Increment

);
};

export default App;
在这个例子中,我们有一个简单的App组件,它显示一个计数值和一个递增按钮。该count值是使用useState钩子管理的,它允许我们在功能组件中管理本地状态。

useState通过使用和之类的钩子useEffect,我们可以管理功能组件中的局部状态和副作用,从而无需创建大量有状态类组件。这种方法避免了与类组件相关的潜在性能问题并简化了代码库,使其更易于维护和调试。

7.避免在JS中过度使用内联样式或CSS
虽然 React 支持内联样式和 CSS-in-JS,但过度使用这些技术会使管理和维护样式变得更加困难。考虑使用外部 CSS 文件或 CSS 模块来更好地分离关注点。

8.避免忽略组件生命周期方法
React 具有生命周期方法,例如componentDidMount, componentDidUpdate,componentWillUnmount可用于管理组件生命周期事件。忽略这些方法可能会导致无法处理的副作用或内存泄漏。

  1. 避免使用匿名函数作为 props
    将匿名函数作为 props 传递可能会导致不必要的子组件重新渲染。相反,使用useCallback或 之类的记忆技术React.memo来防止不必要的重新渲染。

10.避免忽视性能优化
React 提供了各种性能优化,如延迟加载、代码拆分和记忆化。忽略这些优化可能会导致应用程序性能下降和加载时间变慢。

请记住,最佳实践和性能优化可能因 React 应用程序的特定要求和复杂性而异。重要的是要了解 React 的最新功能和最佳实践,并不断审查和优化您的代码,以确保高效且可维护的 React 应用程序。

结论
就 JavaScript 最佳实践而言,没有放之四海而皆准的解决方案。这一切都是关于了解您的项目的独特背景和要求——如果您能够了解效率低下的工程团队的一些最常见特征,则加分。要编写真正健壮和高效的代码,请确保您深入了解 JavaScript 及其局限性,紧跟行业标准,并且永不停止学习。不断磨练您的技能并保持好奇心,以确保您始终处于游戏的顶端!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Q shen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值