1. 使用 === 代替 ==
javascript 使用两种不同的相等运算符: === and 是严格相等运算符, and 是非严格运算符。在比较时始终使用严格相等被认为是最佳实践。!====!=
"If two operands are of the same type and value, then === produces true and !== produces false." - JavaScript: The Good Parts
但是,使用 == and 时!=,您会在使用不同类型时遇到问题。当您比较的值具有不同的类型时,非严格运算符会尝试强制它们的值,您可能会得到意想不到的结果。
2. eval()不好
对于那些不熟悉的人,该 eval() 函数使我们可以访问 javaScript 的编译器。本质上,我们可以通过将字符串的结果作为 eval().
这不仅会大大降低脚本的性能,而且还会带来巨大的安全风险,因为它为传入的文本授予了太多的权力。躲开它!
3.不要使用速记
从技术上讲,您可以省略大多数花括号和分号。大多数浏览器会正确解释以下内容:
if (someVariableExists) x = false
但是,考虑一下:
if (someVariableExists) x = false anotherFunctionCall();
你可能认为上面的代码相当于:
if (someVariableExists) { x = false; anotherFunctionCall(); }
不幸的是,你错了。实际上,这意味着:
if (someVariableExists) { x = false; } anotherFunctionCall();
您会注意到,缩进模仿了花括号的功能。不用说,这是一种可怕的做法,应该不惜一切代价避免。唯一应该省略花括号的是单行,即使这是一个备受争议的话题。
if(2 + 2 === 4) return 'nicely done';
永远考虑未来
如果以后需要在这个 if 语句中添加更多命令怎么办?为此,您需要重写此代码块。底线——省略时要小心。
4.使用 JSLint
JSLint 是由 Douglas Crockford 编写的调试器。只需粘贴到您的脚本中,它就会快速扫描代码中的任何明显问题和错误。
“JSLint 获取一个 JavaScript 源并对其进行扫描。如果它发现问题,它会返回一条描述问题的消息以及源中的大致位置。问题不一定是语法错误,尽管它经常是。JSLint 着眼于某种风格约定和结构问题。它并不能证明你的程序是正确的。它只是提供了另一双眼睛来帮助发现问题。” - JSLint 文档
在签署脚本之前,通过 JSLint 运行它,以确保您没有犯任何粗心的错误。
5. 将脚本放在页面底部
这个技巧已经在本系列的上一篇文章中推荐过。不过,由于它非常合适,我将粘贴信息。
请记住——主要目标是让用户尽可能快地加载页面。加载脚本时,浏览器在加载整个文件之前无法继续。因此,用户将不得不等待更长的时间才能注意到任何进展。
如果您的 JS 文件的唯一目的是添加功能(例如,在单击按钮后),请继续将这些文件放在底部,就在结束 body 标记之前。这绝对是最佳实践。
更好的
<p>And now you know my favorite kinds of corn. </p> <script type="text/javascript" src="path/to/file.js"></script> <script type="text/javascript" src="path/to/anotherFile.js"></script> </body> </html>
6. 在 For 语句之外声明变量
当执行冗长的 for 语句时,不要让引擎比它必须的更努力。例如:
坏的
for(let i = 0; i < someArray.length; i++) { let container = document.getElementById('container'); container.innerHtml += 'my number: ' + i; console.log(i); }
请注意,我们必须如何确定每次迭代的数组长度,以及每次如何遍历 dom 以找到“容器”元素——效率极低!
更好的
let container = document.getElementById('container'); for(let i = 0, len = someArray.length; i < len; i++) { container.innerHtml += 'my number: ' + i; console.log(i); }
7. 构建字符串的最快方法
for 当您需要遍历数组或对象时,不要总是使用您的方便的花花公子 语句。发挥创造力,为手头的工作找到最快的解决方案。
let arr = ['item 1', 'item 2', 'item 3', ...]; let list = '<ul><li>' + arr.join('</li><li>') + '</li></ul>';
我不会用基准来烦你;你只需要相信我(或自己测试)。这是迄今为止最快的方法!
无论抽象层后面发生了什么,使用诸如 之类的本机方法 join()通常比任何非本机替代方法都要快得多。— James Padolsey,james.padolsey.com
8. 使用模板文字
我们用双引号或单引号创建的字符串有很多限制。您可能想用模板文字替换一些字符串,以便更轻松地使用它们。模板文字是使用反引号字符 ( `) 创建的,它们提供了许多优点。您可以将表达式放入其中或创建多行字符串。
let person = 'Monty'; let fruits = 'apples'; let activity = 'playing games'; let day = 'Monday'; let sentence1 = person + ' will be eating ' + fruits + ' and ' + activity + ' on ' + day + '.'; console.log(sentence1); // Output: Monty will be eating apples and playing games on Monday. let sentence2 = `${person} will be eating ${fruits} and ${activity} on ${day}.`; console.log(sentence2); // Output: Monty will be eating apples and playing games on Monday.
如您所见,我们不必像使用单引号或双引号创建的常规字符串文字那样不断地进出模板文字。这减少了任何与打字相关的错误的机会,并帮助我们编写更清晰的代码。
9. 减少全局变量
“通过将您的全球足迹减少到一个名称,您可以显着减少与其他应用程序、小部件或库进行不良交互的机会。” — 道格拉斯·克罗克福德
let name = 'Jeffrey'; let lastName = 'Way'; function doSomething() {...} console.log(name); // Jeffrey -- or window.name
更好的
let DudeNameSpace = { name : 'Jeffrey', lastName : 'Way', doSomething : function() {...} } console.log(DudeNameSpace.name); // Jeffrey
注意我们是如何“减少我们的足迹”到只是一个可笑的命名 DudeNameSpace 对象。
10. 考虑使用 let 和 const
该 let 关键字允许我们创建在它们自己的块中作用域的局部变量。该 const关键字允许我们创建无法重新分配其值的局部块范围变量。在声明变量时,您应该考虑在适当的情况下使用let and const 关键字。请记住,const 关键字只能防止重新分配。它不会使变量不可变。
var person_name = "Adam"; let name_length = person_name.length; const fav_website = "code.tutsplus。com"; if(person_name.length < 5) { var person_name = "Andrew"; let name_length = person_name.length; // Throws an error if not commented out! // fav_website = "webdesign.tutsplus。com"; console.log(`${person_name} has ${name_length} characters.`); // Output: Andrew has 6 characters. } console.log(`${person_name} has ${name_length} characters.`); // Output: Andrew has 4 characters.
在上面的例子中,person_name变量的值也在块外更新if,我们在块内修改它之后。另一方面, name_length它是块作用域的,因此它在块外保留其原始值。
11. 注释你的代码
一开始可能看起来没有必要,但相信我,你 想尽可能地注释你的代码。几个月后你回到项目,却发现你不能轻易记住你的思路是什么,会发生什么?或者,如果您的一位同事需要修改您的代码怎么办?始终,始终注释代码的重要部分。
// Cycle through array and echo out each name. for(var i = 0, len = array.length; i < len; i++) { console.log(array[i]); }
12. 拥抱渐进增强
始终在 JavaScript 被禁用时进行补偿。可能会想,“我的大多数观众都启用了 JavaScript,所以我不会担心它。” 然而,这将是一个巨大的错误。
你有没有花一点时间在关闭 JavaScript 的情况下查看漂亮的滑块?(下载 Web Developer Toolbar 以轻松实现此目的。)它可能会彻底破坏您的网站。根据经验,在设计您的网站时假设 JavaScript 将被禁用。然后,一旦你这样做了,开始逐步增强你的布局!
13. 不要将字符串传递给 setInterval or setTimeOut
考虑以下代码:
setInterval( "document.getElementById('container').innerHTML += 'My new number: ' + i", 3000 );
这段代码不仅效率低下,而且它的功能也与函数相同eval 。永远不要将字符串传递给 setInterval and setTimeOut。相反,传递一个函数名。
setInterval(someFunction, 3000);
14. 使用 {} 代替 new Object()
在 JavaScript 中有多种创建对象的方法。也许更传统的方法是使用 new 构造函数,如下所示:
var o = new Object(); o.name = 'Jeffrey'; o.lastName = 'Way'; o.someFunction = function() { console.log(this.name); }
但是,这种方法会收到“不良做法”的烙印。它实际上并没有害处,但它有点冗长和不寻常。相反,我建议您使用对象文字方法。
更好的
var o = { name: 'Jeffrey', lastName = 'Way', someFunction : function() { console.log(this.name); } };
请注意,如果您只是想创建一个空对象, {} 就可以了。
var o = {};
“对象文字使我们能够编写支持许多功能的代码,但仍然为我们的代码实现者提供了一个相对简单的过程。无需直接调用构造函数或维护传递给函数的参数的正确顺序。”
15. 使用 [] 代替 new Array()
这同样适用于创建新数组。
好的
var a = new Array(); a[0] = "Joe"; a[1] = 'Plumber';
更好的
var a = ['Joe','Plumber'];
“JavaScript 程序中的一个常见错误是在需要数组时使用对象,或者在需要对象时使用数组。规则很简单:当属性名称是小的连续整数时,您应该使用数组。否则,使用目的。” — 道格拉斯·克罗克福德
16. 使用展开运算符
您是否曾经遇到过想将数组的所有项作为单个元素传递给其他函数的情况,或者您想将一个数组中的所有值插入另一个数组?扩展运算符 ( ...) 允许我们做到这一点。这是一个例子:
let people = ["adam", "monty", "andrew"] let more_people = ["james", "jack", ...people, "sajal"] console.log(more_people) // Output: Array(6) [ "james", "jack", "adam", "monty", "andrew", "sajal" ]
17. 小心 for ... in 陈述
循环访问对象中的项目时,您可能会发现您还检索了方法函数或其他继承的属性。为了解决这个问题,请始终将您的代码包装在一个if 使用 hasOwnProperty.
for (key in object) { if (object.hasOwnProperty(key) { ...then do something... } }
这个技巧来自 Douglas Crockford 的JavaScript: The Good Parts。
18. 阅读,阅读,阅读……
虽然我是 Web 开发博客的忠实粉丝(比如这个!),但在吃午饭或睡觉前真的没有书可以替代。始终在您的床头柜上放一本 Web 开发书籍。这是我最喜欢的一些 JavaScript。
面向对象的 JavaScript
JavaScript:好的部分
学习 JavaScript
阅读它们......多次。我仍然!
19. 自执行函数
与其调用函数,不如让函数在页面加载或调用父函数时自动运行非常简单。只需将您的函数包装在括号中,然后附加一个额外的集合,它实际上调用了该函数。
(function doSomething() { return { name: 'jeff', lastName: 'way' }; })();
20.原生 JavaScript 总是比使用库更快
JavaScript 库,例如 jquery 和 lodash,可以在编码时为您节省大量时间——尤其是使用 ajax 操作。话虽如此,请始终牢记库永远不会像原始 JavaScript 一样快(假设您的代码正确)。
jQuery 的 each() 方法非常适合循环,但使用原生 for 语句总是快一盎司。
21.使用解构快速分配变量值
我们已经在本文前面了解了 JavaScript 中的扩展运算符。解构在某种意义上有点相似,它也解包存储在数组中的值。不同之处在于我们可以将这些解压缩的值分配给唯一的变量。
[] 语法类似于使用速记创建数组 。但是,这次括号位于赋值运算符的左侧。这是一个例子:
let [person, fruit, , day] = ['Monty', 'apple', 'reading', 'tomorrow']; var sentence = `${person} will eat an ${fruit} ${day}.`; console.log(sentence); // Output: Monty will eat an apple tomorrow.
您是否注意到我们只是通过不传递变量名来跳过将第三个数组元素分配给任何变量?这使我们可以避免为不需要的值分配变量。
22. 迭代器和 for ... of 循环
JavaScript 中的迭代器是实现 next()方法以返回一个对象的对象,该对象存储序列中的下一个值,true 或者 false取决于是否还有剩余的值。这意味着如果您实现了迭代器协议,您就可以创建自己的迭代器对象。
JavaScript 也有一些内置的迭代器,如 String, Array,Map等。您可以使用for ... of 循环对它们进行迭代。for 与常规循环相比,这更简洁且不易出错 。
let people = ["Andrew", "Adam", "James", "Jack"]; let people_count = people.length; for(let i = 0; i < people_count; i++) { console.log(people[i]); } /* Andrew Adam James Jack */ for(person of people) { console.log(person); } /* Andrew Adam James Jack */
使用 for...of循环,我们不必跟踪数组的总长度或当前索引。这可以在创建嵌套循环时降低代码复杂性。
23. async 和 await
您可以使用 async关键字来创建异步函数,该函数总是显式或隐式地返回一个 Promise。您创建的异步函数可以通过停止执行直到返回的 Promise 得到解决来利用该 await 关键字。函数之外的代码 async 将继续正常执行。
async function delayed_hello() { console.log("Hello Adam!"); let promise = new Promise((resolve) => { setTimeout(() => resolve("Hello Andrew!"), 2000) }); let result = await promise; console.log(result); } console.log("Hello Monty!"); delayed_hello(); console.log("Hello Sajal!"); /* Hello Monty! Hello Adam! Hello Sajal! Hello Andrew! */
在上面的示例中, "Hello Andrew"两秒后记录,而所有其他 hello 都立即记录。delayed_hello() 对函数 的调用会"Hello Adam" 立即记录,但要等待承诺解决才能记录 "Hello Andrew"。
24.使用箭头函数
最近添加到 JavaScript 的另一个重要特性是箭头函数。它们带来了许多好处。首先,它们使 JavaScript 的功能元素更吸引眼球并且更容易编写。
看看我们如何实现没有箭头函数的过滤器:
const nums = [1,2,3,4,5,6,7,8]; const even_nums = nums.filter( function (num) { return num%2 == 0; } )
在这里,我们传递给过滤器的回调函数对任何偶数都返回 true。
箭头函数使这更具可读性和简洁性:
const nums = [1,2,3,4,5,6,7,8]; const even_nums = nums.filter(num => num%2 == 0)
箭头函数的另一个显着好处是它们不定义范围,而是在父范围内。这可以防止使用this关键字时可能出现的许多问题。箭头函数中没有绑定this。this箭头函数内部的值与父作用域中的值相同。但是,这意味着箭头函数不能用作构造函数或方法。
25.使用Javascriptincludes()方法
JavaScript 中的方法确定字符串是否包含指定的字符,或者数组是否包含指定的元素。如果找到字符串或元素,则此函数返回 true;否则,它返回 false。 includes()
const str = 'This String contains the word accept'; console.log(str.includes('accept')); //output:true
值得注意的是,includes()Strings 上的方法区分大小写。如果无论大小写都想匹配一个字符串,只需先将目标字符串变为小写即可。
const str = 'This String contains the word accept'; console.log(str.toLowerCase().includes('string')); //output: true
26.并行运行 Promise
最好并行运行您的异步任务,因为它可以使您的应用程序更快且响应更快。如果您的任务不依赖于彼此的结果,只需将它们打包Promise.all并并行运行即可。
async将/await和 结合起来真的很棒Promise.all,但是您必须仔细考虑哪些部分是顺序发生的,哪些部分是并行发生的。Promise.all这是一个使用和同时从 URL 数组中获取文本的示例await。
const urls = ["https://en.wikipedia.org/wiki/Canada", "https://en.wikipedia.org/wiki/Nigeria", "https://en.wikipedia.org/wiki/Vietnam"] const countryInfo = await Promise.all(urls.map( async url => const resp = await fetch(url); return resp.text(); }));
这会将数组中的 URL 映射到异步函数数组。每个异步函数都会从 URL 中获取文本并返回它。由于这是一个异步函数,它实际上是一个Promise. Promise.all将等待这些承诺,并在它们全部完成后返回它们加载的文本数组。
27.提取或处理字符串时使用正则表达式
Regex(正则表达式)是一个非常强大甚至有趣的工具。如果您发现自己使用 and 之类的方法对字符串进行复杂的搜索和操作indexOf(),substring()则应该使用正则表达式。
正则表达式使您能够搜索复杂的模式,并替换或提取与这些模式匹配的文本。
正则表达式的一个经典用途是验证输入。例如,以下正则表达式可用于验证美国的五位数邮政编码:
const zipRegex = /\d{5}/ console.log(zipRegex.test("12345")) //output: true console.log(zipRegex.text("B3K 1R2")) //output: false
28.将 JavaScript 放在一个单独的文件中
JavaScript 可以写在<script>HTML 的标签中,也可以保存在自己的文件中并链接到 HTML 中。这有助于以这种方式将不同类型的代码相互隔离,并使您的代码更易于理解和组织良好。
将 JavaScript 保存在 HTML 之外的单独文件中有助于跨多个 HTML 文件重用代码。它提供了更轻松的代码阅读,并节省了加载时间,因为 Web 浏览器可以缓存外部 JavaScript 文件。
29.使用 Splice 从数组中删除项目
我见过开发人员使用该delete方法从数组中删除一个项目。这是不正确的,因为该delete函数用对象替换undefined而不是删除它。在 JavaScript 中,根据值从数组中删除元素的最佳方法是使用该函数来发现该值在数组中的索引号,然后使用该函数删除该索引值。 indexOf()splice()
var items = ["apple","orange","berries","strawberry"]; items.splice(2,1); console.log(items); //output: ['apple', 'orange', 'strawberry']
30.学习单元测试
当我作为开发人员第一次开始添加单元测试时,我经常发现错误。测试是确保您的代码没有错误的最有效方法。Jest是一个很好的起点,但还有其他选项同样易于使用。在部署任何代码之前,应该对其进行单元测试以确保其符合质量标准。这促进了一个以质量为优先的可靠工程环境。单元测试可以在产品开发生命周期中节省时间和金钱,并帮助开发人员设计更好、更高效的代码。
就是这样,伙计们
所以你有了它:30 个 JavaScript 初学者的基本技巧。谢谢阅读。
- 永远考虑未来
- 更好的
- 坏的
- 更好的
- 更好的
- 更好的
- 好的
- 更好的