介: 和大家一起探讨一下优雅代码
谈到好代码,我的第一想法就是优雅,那我们如何该写出好的代码,让阅读的人感受到优雅呢?首先简单探讨一下优雅代码的定义
关于好代码的定义,各路大神都给出了自己的定义和见解
首先要达成一致,我们写的代码,除了用于机器执行产生我们预期的效果之外,更多的时候是给人读的,可能是后续的维护人员,更多时候是一段时间后的作者本人,因此优雅面向不同的用户有两层含义的解读
这次,我们就来聊一聊,什么代码是优雅的代码,怎样写出优雅的代码
简单说就是类、方法、变量的命名要名副其实,要能描述清晰自己的职责。一个好的命名能输出更多的信息,它会告诉你,它为什么存在,它是做什么事的,应该怎么使用。一个简单的衡量标准是,如果命名完仍需要注释来补充语义,那就不是名副其实;
选个好名字要花时间,但省下的时间的时间比花掉的多,一旦发现有更好的名称,就换掉旧的。
举个栗子
public List<int[]> getItem() {
List<int[]> list1=new ArrayList<int[]>();
for (int[] x: theList)
if (x[0]==4)
list1.add(x);
return list1;
}
整体逻辑没啥问题,读完之后,就有很多问题在脑海中产生
代码应该体现所处的情景,比方说上述的代码所处情景是我们正在开发一种扫雷游戏,盘面是名为theList的单元格列表,那就将其名称改为gameBoard。
盘面上每个单元格都用一个简单数组表示。零下标条目是一种状态值,而这种状态值为4代表“已标记”。只要改为有意义的名称,代码就得到了改进。
更进一步,不用int数组来表示单元格,而是另写一个类。该类包括一个名副其实的函数(称为isFlagged),从而掩盖住哪个魔术数4,得到新的函数版本。
public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells=new ArrayList<Cell>();
for (Cell cell : gameBoard)
if (cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}
实际上,只要我们的代码有足够的表达力,能清晰的通过命名来做到名副其实,就不太需要注释,或者根本不需要;注释的存在往往是弥补我们无法用代码清晰表达意图的情况。可以想象一下,每次自己发现需要写注释的时候,是什么心态,担心此处代码明天自己看不懂或者别人看不懂,那有没有考虑用更好的语义的代码来替代。
但尽管有注释,也有好有坏,有时候注释也会撒谎,通常注释存在的越久,就离其描述的代码越远,变得越来越离谱;因为代码在变动在迭代,在注释和代码间可能会插入新的代码,旧代码我们通常copy来copy去,分离又重组,但注释一般不会修改,就会造成注释和描述的代码分离,对阅读者造成更大的迷惑。
我们在需要写注释的时候就要告诉自己,能不能用代码来进行描述。以下是一些坏代码的注释bad case
1. 一些被注释掉的代码
//something code
//something code
2. 位置标记
//begin
someting code;
//end
3. 签名标记
/** add by xiaoli*/
4. 非公用方法的javadoc
/**
* doSomething
*/
private void doSomething(){
}
5. 日志式注释
/** add xx
* update sometimes
* update sometimes
* update sometimes
*/
6. 误导性注释
//此处怎样xx
方法应该有多短小?没有明确约束,idea也不会限制你,但通常我们的方法不该长于一屏,至少多于一屏或者横向外溢到屏幕以外最直观的就会造成可读性体验差,读了下面忘记上面,左右拖拽等。对大多数笔记本来说一屏大概就30行左右。短小精简的方法要比30行短很多,比如
public String renderPageWithSetupAndTeardowns(Page page, boolean isSuite) throws Exception{
if(isTestPage(page)){
includeSetupAndTeardownPages(page,isSuite);
}
return page.getHtml();
}
if语句、else语句、while语句等,其中的代码应该只有一行,
改行通常是一个调用语句,这样不但能保持短小,还可以给调用方法命名一个有说明性的名字,进一步增加代码的可读性
一事精,便可动人。这个普世法则甚至适用于各种场合。像设计原则的单一职责模式,让类只有一个职责。如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致逻辑混乱,设计耦合。当一个职责发生变化时,可能会影响其它的职责。
另外,多个职责耦合在一起,会影响复用性。针对方法而言更是如此。方法作为程序的原子单元,保持单一会有效提升复用性。 那怎么判断一个方法是否只做了一件事。最简单的规则就是看看该方法是否能在拆出一个方法,且拆出去的方法是不同于该方法的诠释和实现。但是要注意同一方法的逻辑层级务必要一致。
抽象层级一致也是对方法只做一件事的更高要求,抽象层级不一致的代码一定是做了多件事。
我们读代码通常是自顶向下阅读,我们想让每个方法后面都跟着位于下一层级的方法,这样我们可以依着抽象层级向下阅读了。我们也需要这样阅读代码,先有整体在展示细节,这种叫向下规则。这也是保持方法短小,确保只做一件事的诀窍。一旦方法中混杂不同的抽象层级,会让人很迷惑,因为没办法这个方法中判断某个表达式是基础概念还是细节,更恶劣的是,一旦细节与基础概念混杂,更多的细节就会纠缠不清,举例子我们想写一个冰冻大象的需求
//把大象装进冰箱
public void frozenElephant(){
//1. 捕捉大象
//2. 运输大象
//3. 打开冰箱
//4. 放入大象
//5. 关闭冰箱
}
这个例子的1.2两步就不是一个层级的逻辑,是属于更高层级的抽象。3.4.5都是将大象放入冰箱的步骤,属于低层级的抽象。可以将代码拆分为如下实现,将高抽象层级的代码聚合提取出来,细节在分别单独实现,如下
public void frozenElephant(){
//1. 捕捉大象
catchElephant();
//2. 运输大象
transportElephant();
//将大象放入冰箱
putElephantInRefrigerator();
}
public void catchElephant(){
}
public void transportElephant(){
}
public void putElephantInRefrigerator(){
//打开冰箱
//放入大象
//关闭冰箱
}
针对错误码的判断会导致更深层次的嵌套结构,返回错误码就意味着要求调用者跟着处理错误,如下
if(deletePage()==OK){
if(registry.deleteReference(page.name)==OK){
if(configKeys.deleteKey(page.name.makeKey)==OK){
logger.log("page deleted")
}else{
logger.log("configKey not deleted")
}
}else{
logger.log("deleteReference from registry failed")
}
}else{
logger.log("delete failed")
return Error;
}
一般我们还需要将try/Catch代码块给抽离出去,另外形成方法。防止代码块过多搞乱代码结构,分不清错误处理还是正常流程。同时因为方法只做一件事,错误处理就是一件事,因此错误处理的方法不应该在做其他事,也就是如果一个方法中有try关键字,那try就是方法的开头。catch/finally代码块后面也不应该再有内容,如下
try{
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey);
}catch(Exception e){
logger.log(e.getMessage());
}
比如Lombok组件通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法 举例如下:
比如Apache Commons系列组件给我们提供了关于字符串、集合、IO操作等工具方法。这些组件是个大宝库,提供了不少轮子
beanUtils | JavaBean进行各种操作,克隆对象、属性等等 |
codec | 处理常用的编码方法的工具类包,例如DES、SHA1、MD5、Base64等. |
collections | java集合框架操作 |
configuration | java应用程序的配置管理类库 |
io | io工具的封装 |
lang | Java基本对象方法的工具类包 如StringUtils、ArrayUtils等等. |
logging | 提供的日志接口 |
net | 提供了客户端和服务器端的数据验证框架 |
重构是对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
在重构之前一定要知道,一旦开始对类和方法进行重构,就需要事前有完备的单元测试用例来保障重构的准确性,每次重构之后都要去执行对应的单元测试用例,验证重构的正确性!
如果在一个以上的地点看到相同的代码结构,可以肯定的是,想办法抽线出来合而为一,代码会变得更好。一般包含几个点的重复
遵循这样一条原则:每当感觉需要以注释来说明点什么的时候,就把需要说明的东西写进一个独立函数中,并以其用途(而非实现手法)命名,可以对一组甚至短短一行代码做这件事。哪怕替换后的函数调用动作比函数自身还长,只要函数名称能够解释其用途,就要毫不犹豫地那样做,关键不在于函数的长度,而在于函数“做什么”和“如何做”之间的语义距离。
对数据的修改经常导致出乎意料的结果和难以发现的bug。在一处更新数据,却没有意识到软件中的另一处期望着完全不同的数据,于是出现难以预料的bug,往往比较难排查(需要排查数据流转的整体链路),这就需要一些方法用于约束对数据的更新,降低数据可变性的风险。
所谓模块化,就是力求将代码分出区域,最大化区域内部的交互、最小化跨区域的交互。但是经常出现一个函数跟另一个模块中的函数或者数据交流格外频繁,远胜于与所处模块内部的交流,这就是模块功能不单一的典型情况。
点击查看原文,获取更多福利!
https://developer.aliyun.com/article/1117703?utm_content=g_1000366324
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
C语言中,if语句是一种常用的选择结构语句,用于根据条件选择性地执行不同的代码块。if语句的设计使得程序可以根据条件的真假进行分支控制,从而实现灵活的程序逻辑。本文将深入介绍C语言中如何使用if语句设计选择结构程序,包括if语句的语法、使用方法、常见应用场景以及注意事项,以帮助读者更好地理解和运用这一重要的编程概念。
以下是我整理的关于C语言的一些入门级资料,免费分享给大家:https://m.hqyjai.net/emb_study_blue_short.html?xt=zxy
开发中,变量名,函数名一般要做到清晰明了,尽量做到看名字就能让人知道你的意图,所以变量和函数命名是挺重要,今天来看看如果较优雅的方式给变量和函数命名。
一、变量
使用有意义和可发音的变量名
// 不好的写法 const yyyymmdstr = moment().format("YYYY/MM/DD"); // 好的写法 const currentDate = moment().format("YYYY/MM/DD");
对同一类型的变量使用相同的词汇
// 不好的写法 getUserInfo(); getClientData(); getCustomerRecord(); // 好的写法 getUser();
使用可搜索的名字
我们读的会比我们写的多得多,所以如果命名太过随意不仅会给后续的维护带来困难,也会伤害了读我们代码的开发者。让你的变量名可被读取,像 buddy.js 和 ESLint 这样的工具可以帮助识别未命名的常量。
// 不好的写法 // 86400000 的用途是什么? setTimeout(blastOff, 86400000); // 好的写法 const MILLISECONDS_IN_A_DAY = 86_400_000; setTimeout(blastOff, MILLISECONDS_IN_A_DAY);
使用解释性变量
// 不好的写法 const address = "One Infinite Loop, Cupertino 95014"; const cityZipCodeRegex = /^[^,\]+[,\\s]+(.+?)\s*(\d{5})?$/; saveCityZipCode( address.match(cityZipCodeRegex)[1], address.match(cityZipCodeRegex)[2] ); // 好的写法 const address = "One Infinite Loop, Cupertino 95014"; const cityZipCodeRegex = /^[^,\]+[,\\s]+(.+?)\s*(\d{5})?$/; const [_, city, zipCode] = address.match(cityZipCodeRegex) || []; saveCityZipCode(city, zipCode);
避免费脑的猜测
显式用于隐式
// 不好的写法 const locations = ["Austin", "New York", "San Francisco"]; locations.forEach(l => { doStuff(); doSomeOtherStuff(); // ... // ... // ... // 等等,“l”又是什么? dispatch(l); // 好的写法 const locations = ["Austin", "New York", "San Francisco"]; locations.forEach(location => { doStuff(); doSomeOtherStuff(); // ... // ... // ... dispatch(location); });
无需添加不必要的上下文
如果类名/对象名已经说明了,就无需在变量名中重复。
// 不好的写法 const Car = { carMake: "Honda", carModel: "Accord", carColor: "Blue" }; function paintCar(car) { car.carColor = "Red"; } // 好的写法 const Car = { make: "Honda", model: "Accord", color: "Blue" }; function paintCar(car) { car.color = "Red"; }
使用默认参数代替逻辑或(与)运算
// 不好的写法 function createMicrobrewery(name) { const breweryName = name || "Hipster Brew Co."; // ... } // 好的写法 function createMicrobrewery(name = "Hipster Brew Co.") { // ... }
二、函数
函数参数(理想情况下为2个或更少)
限制函数参数的数量是非常重要的,因为它使测试函数变得更容易。如果有三个以上的参数,就会导致组合爆炸,必须用每个单独的参数测试大量不同的情况。
一个或两个参数是理想的情况,如果可能,应避免三个参数。除此之外,还应该合并。大多数情况下,大于三个参数可以用对象来代替。
// 不好的写法 function createMenu(title, body, buttonText, cancellable) { // ... } createMenu("Foo", "Bar", "Baz", true); // 好的写法 function createMenu({ title, body, buttonText, cancellable }) { // ... } createMenu({ title: "Foo", body: "Bar", buttonText: "Baz", cancellable: true });
函数应该只做一件事
这是目前为止软件工程中最重要的规则。当函数做不止一件事时,它们就更难组合、测试和推理。可以将一个函数隔离为一个操作时,就可以很容易地重构它,代码也会读起来更清晰。
// 不好的写法 function emailClients(clients) { clients.forEach(client => { const clientRecord = database.lookup(client); if (clientRecord.isActive()) { email(client); } }); } // 好的写法 function emailActiveClients(clients) { clients.filter(isActiveClient).forEach(email); } function isActiveClient(client) { const clientRecord = database.lookup(client); return clientRecord.isActive(); }
函数名称应说明其作用
// 不好的写法 function addToDate(date, month) { // ... } const date = new Date(); // 从函数名称很难知道添加什么 addToDate(date, 1); // 好的写法 function addMonthToDate(month, date) { // ... } const date = new Date(); addMonthToDate(1, date);
函数应该只有一个抽象层次
当有一个以上的抽象层次函数,意味该函数做得太多了,需要将函数拆分可以实现可重用性和更简单的测试。
// 不好的写法 function parseBetterJSAlternative(code) { const REGEXES = [ // ... ]; const statements = code.split(" "); const tokens = []; REGEXES.forEach(REGEX => { statements.forEach(statement => { // ... }); }); const ast = []; tokens.forEach(token => { // lex... }); ast.forEach(node => { // parse... }); } // 好的写法 function parseBetterJSAlternative(code) { const tokens = tokenize(code); const syntaxTree = parse(tokens); syntaxTree.forEach(node => { // parse... }); } function tokenize(code) { const REGEXES = [ // ... ]; const statements = code.split(" "); const tokens = []; REGEXES.forEach(REGEX => { statements.forEach(statement => { tokens.push(/* ... */); }); }); return tokens; } function parse(tokens) { const syntaxTree = []; tokens.forEach(token => { syntaxTree.push(/* ... */); }); return syntaxTree; }
删除重复的代码
尽量避免重复的代码,重复的代码是不好的,它意味着如果我们需要更改某些逻辑,要改很多地方。
通常,有重复的代码,是因为有两个或多个稍有不同的事物,它们有很多共同点,但是它们之间的差异迫使我们编写两个或多个独立的函数来完成许多相同的事情。 删除重复的代码意味着创建一个仅用一个函数/模块/类就可以处理这组不同事物的抽象。
获得正确的抽象是至关重要的,这就是为什么我们应该遵循类部分中列出的 「SOLID原则」。糟糕的抽象可能比重复的代码更糟糕,所以要小心!说了这么多,如果你能做一个好的抽象,那就去做吧!不要重复你自己,否则你会发现自己在任何时候想要改变一件事的时候都要更新多个地方。
「设计模式的六大原则有」
把这六个原则的首字母联合起来(两个 L 算做一个)就是 SOLID (solid,稳定的),其代表的含义就是这六个原则结合使用的好处:建立稳定、灵活、健壮的设计。下面我们来分别看一下这六大设计原则。
「不好的写法」
function showDeveloperList(developers) { developers.forEach(developer => { const expectedSalary = developer.calculateExpectedSalary(); const experience = developer.getExperience(); const githubLink = developer.getGithubLink(); const data = { expectedSalary, experience, githubLink }; render(data); }); } function showManagerList(managers) { managers.forEach(manager => { const expectedSalary = manager.calculateExpectedSalary(); const experience = manager.getExperience(); const portfolio = manager.getMBAProjects(); const data = { expectedSalary, experience, portfolio }; render(data); }); }
「好的写法」
function showEmployeeList(employees) { employees.forEach(employee => { const expectedSalary = employee.calculateExpectedSalary(); const experience = employee.getExperience(); const data = { expectedSalary, experience }; switch (employee.type) { case "manager": data.portfolio = employee.getMBAProjects(); break; case "developer": data.githubLink = employee.getGithubLink(); break; } render(data); }); }
使用Object.assign设置默认对象
「不好的写法」
const menuConfig = { title: null, body: "Bar", buttonText: null, cancellable: true }; function createMenu(config) { configconfig.title = config.title || "Foo"; configconfig.body = config.body || "Bar"; configconfig.buttonText = config.buttonText || "Baz"; configconfig.cancellable = config.cancellable !== undefined ? config.cancellable : true; } createMenu(menuConfig);
「好的写法」
const menuConfig = { title: "Order", // User did not include 'body' key buttonText: "Send", cancellable: true }; function createMenu(config) { config = Object.assign( { title: "Foo", body: "Bar", buttonText: "Baz", cancellable: true }, config ); // config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} // ... } createMenu(menuConfig);
不要使用标志作为函数参数
标志告诉使用者,此函数可以完成多项任务,函数应该做一件事。如果函数遵循基于布尔的不同代码路径,请拆分它们。
// 不好的写法 function createFile(name, temp) { if (temp) { fs.create(`./temp/${name}`); } else { fs.create(name); } } // 好的写法 function createFile(name) { fs.create(name); } function createTempFile(name) { createFile(`./temp/${name}`); }
避免副作用(第一部分)
如果函数除了接受一个值并返回另一个值或多个值以外,不执行任何其他操作,都会产生副作用。副作用可能是写入文件,修改某些全局变量,或者不小心将你的所有资金都汇给了陌生人。
「不好的写法」
let name = "Ryan McDermott"; function splitIntoFirstAndLastName() { namename = name.split(" "); } splitIntoFirstAndLastName(); console.log(name); // ['Ryan', 'McDermott'];
「好的写法」
function splitIntoFirstAndLastName(name) { return name.split(" "); } const name = "Ryan McDermott"; const newName = splitIntoFirstAndLastName(name); console.log(name); // 'Ryan McDermott'; console.log(newName); // ['Ryan', 'McDermott'];
避免副作用(第二部分)
在JavaScript中,原始类型值是按值传递,而对象/数组按引用传递。对于对象和数组,如果有函数在购物车数组中进行了更改(例如,通过添加要购买的商品),则使用该购物车数组的任何其他函数都将受到此添加的影响。那可能很棒,但是也可能不好。来想象一个糟糕的情况:
用户单击“购买”按钮,该按钮调用一个purchase 函数,接着,该函数发出一个网络请求并将cart数组发送到服务器。由于网络连接不好,purchase函数必须不断重试请求。现在,如果在网络请求开始之前,用户不小心点击了他们实际上不需要的项目上的“添加到购物车”按钮,该怎么办?如果发生这种情况,并且网络请求开始,那么购买函数将发送意外添加的商品,因为它有一个对购物车数组的引用,addItemToCart函数通过添加修改了这个购物车数组。
一个很好的解决方案是addItemToCart总是克隆cart数组,编辑它,然后返回克隆。这可以确保购物车引用的其他函数不会受到任何更改的影响。
关于这种方法有两点需要注意:
// 不好的写法 const addItemToCart = (cart, item) => { cart.push({ item, date: Date.now() }); }; // 好的写法 const addItemToCart = (cart, item) => { return [...cart, { item, date: Date.now() }]; };
不要写全局函数
污染全局变量在 JS 中是一种不好的做法,因为可能会与另一个库发生冲突,并且在他们的生产中遇到异常之前,API 的用户将毫无用处。让我们考虑一个示例:如果想扩展 JS 的原生Array方法以具有可以显示两个数组之间差异的diff方法,该怎么办?可以将新函数写入Array.prototype,但它可能与另一个尝试执行相同操作的库发生冲突。如果其他库仅使用diff来查找数组的第一个元素和最后一个元素之间的区别怎么办?这就是为什么只使用 ES6 类并简单地扩展Array全局会更好的原因。
// 不好的写法 Array.prototype.diff = function diff(comparisonArray) { const hash = new Set(comparisonArray); return this.filter(elem => !hash.has(elem)); }; // 好的写法 class SuperArray extends Array { diff(comparisonArray) { const hash = new Set(comparisonArray); return this.filter(elem => !hash.has(elem)); } }
尽量使用函数式编程而非命令式
JavaScript不像Haskell那样是一种函数式语言,但它具有函数式的风格。函数式语言可以更简洁、更容易测试。如果可以的话,尽量喜欢这种编程风格。
「不好的写法」
const programmerOutput = [ { name: "Uncle Bobby", linesOfCode: 500 }, { name: "Suzie Q", linesOfCode: 1500 }, { name: "Jimmy Gosling", linesOfCode: 150 }, { name: "Gracie Hopper", linesOfCode: 1000 } ]; let totalOutput = 0; for (let i = 0; i < programmerOutput.length; i++) { totalOutput += programmerOutput[i].linesOfCode; }
「好的写法」
const programmerOutput = [ { name: "Uncle Bobby", linesOfCode: 500 }, { name: "Suzie Q", linesOfCode: 1500 }, { name: "Jimmy Gosling", linesOfCode: 150 }, { name: "Gracie Hopper", linesOfCode: 1000 } ]; const totalOutput = programmerOutput.reduce( (totalLines, output) => totalLines + output.linesOfCode, 0 );
封装条件
// 不好的写法 if (fsm.state === "fetching" && isEmpty(listNode)) { // ... } // 好的写法 function shouldShowSpinner(fsm, listNode) { return fsm.state === "fetching" && isEmpty(listNode); } if (shouldShowSpinner(fsmInstance, listNodeInstance)) { // ... }
避免使用非条件
// 不好的写法 function isDOMNodeNotPresent(node) { // ... } if (!isDOMNodeNotPresent(node)) { // ... } // 好的写法 function isDOMNodePresent(node) { // ... } if (isDOMNodePresent(node)) { // ... }
避免使用过多条件
这似乎是一个不可能完成的任务。一听到这个,大多数人会说,“没有if语句,我怎么能做任何事情呢?”答案是,你可以在许多情况下使用多态性来实现相同的任务。
第二个问题通常是,“那很好,但是我为什么要那样做呢?”答案是上面讲过一个概念:一个函数应该只做一件事。当具有if语句的类和函数时,这是在告诉你的使用者该函数执行不止一件事情。
「不好的写法」
class Airplane { // ... getCruisingAltitude() { switch (this.type) { case "777": return this.getMaxAltitude() - this.getPassengerCount(); case "Air Force One": return this.getMaxAltitude(); case "Cessna": return this.getMaxAltitude() - this.getFuelExpenditure(); } } }
「好的写法」
class Airplane { // ... } class Boeing777 extends Airplane { // ... getCruisingAltitude() { return this.getMaxAltitude() - this.getPassengerCount(); } } class AirForceOne extends Airplane { // ... getCruisingAltitude() { return this.getMaxAltitude(); } } class Cessna extends Airplane { // ... getCruisingAltitude() { return this.getMaxAltitude() - this.getFuelExpenditure(); } }
避免类型检查
JavaScript 是无类型的,这意味着函数可以接受任何类型的参数。有时q我们会被这种自由所困扰,并且很想在函数中进行类型检查。有很多方法可以避免这样做。首先要考虑的是一致的API。
// 不好的写法 function travelToTexas(vehicle) { if (vehicle instanceof Bicycle) { vehicle.pedal(this.currentLocation, new Location("texas")); } else if (vehicle instanceof Car) { vehicle.drive(this.currentLocation, new Location("texas")); } } // 好的写法 function travelToTexas(vehicle) { vehicle.move(this.currentLocation, new Location("texas")); }
不要过度优化
现代浏览器在运行时做了大量的优化工作。很多时候,如果你在优化,那么你只是在浪费时间。有很好的资源可以查看哪里缺乏优化,我们只需要针对需要优化的地方就行了。
// 不好的写法 // 在旧的浏览器上,每一次使用无缓存“list.length”的迭代都是很昂贵的 // 会为“list.length”重新计算。在现代浏览器中,这是经过优化的 for (let i = 0, len = list.length; i < len; i++) { // ... } // 好的写法 for (let i = 0; i < list.length; i++) { // ... }
原文:https://developer.51cto.com/art/202005/616073.htm
作者:前端小智
*请认真填写需求信息,我们会在24小时内与您取得联系。