每个Javascript开发者都应当知道的那些事

499 查看

Javascript是一种日益增长的语言,特别是现在ECMAScript规范按照每年的发布时间表发布。伴随着这门语言的规模化和快速发展,掌握JS(不仅仅是jQuery)的重要性,变得更加重要。

这不是一篇自称是 JS 开发者知识圣杯的权威指南。不过里面绝对有一些我曾经错过的,有一些我可能是错用的,还有一些你可能不同意每个JS开发者应该知道的东西。

如何FizzBuzz

译者注:FizzBuzz是英国学校里常玩的游戏,从1数到100,如果遇见了3的倍数要说Fizz,5的倍数到说Buzz,如果即是3的倍数又是5的倍数要说FizzBuzz。

(FizzBuzz测试)通常被认为是一个不错的编码练习,用来在面试初期过程中淘汰没有经验的开发人员,你会惊讶地发现许多Javascript开发人员不知道如何编写一个基本的FizzBuzz测试。

FizzBuzz测试没啥实际用途。它纯粹是一个简单的练习,用来测试候选人潜在的编码能力。

记住在你将面试前端或Javascript开发岗位的大多数公司中,极有可能会问你一个FizzBuzz问题:你准备好了吗?

这是经典的FizzBuzz:

记住,你可能会被要求解决FizzBuzz的不同变种。我去面试过一次,被要求解决基本变种,然后另外两个变种。

这个特别的示例在3的倍数输出“Fizz”。在5的倍数输出“Buzz”,在即是3的倍数又是5的倍数输出“FizzBuzz”。

注意:在早些时候这个实现就有稍微改动。使用条件 if 语句,如果它不是一个条件的倍数,数字被打印出来。现有的解决方案可以工作,但没有打印不满足条件的数字或使用条件 if。

= = 和 = = = 的区别

两个比较运算符你可能熟悉。然而,你知道双重和三重等于比较运算符之间的区别吗?Javascript linter告诉你使用三重等于,但你知道为什么吗?

= = 双重等于(又名松等于)不会比较类型,它将在语句中将值进行类型转换。这就是所谓的强制类型转换,它被认为是一个有害的操作。

正如你所看到的,带单引号的24是一个字符串,将被转换成数字。虽然这在某种情况下可能是我们期望的行为,但允许比较运算符改变类型可能不是你想要做的。

不推荐使用双重等于,最理智的Javascript linter在默认情况下将抛出一个错误来告诉你使用严格的相等比较运算符来替换。如果你想强制转换值,在条件外做而不是在里面。

= = =三重等于(又名严格相等)将比较类型,但不会做类型转换,意味着他们在不被转换的情况下比较。因为没有强制类型转换,三重等于速度更快,作为推荐的方法用来比较各种各样的值。这意味着如果条件等于true,两种类型需要相同。

和上面的例子一样,但是三重等于:

返回false的原因是因为我们对一个字符串和一个数字进行比较。显然它们是两个不同的类型,因此它将返回false。

我强烈建议你在Mozilla开发者网站阅读更多关于等于比较符。它有一些很棒的解释(比我解释得更好),还有一些例子。

如何在不使用第三方库的情况下查询DOM

你可能知道如何使用jQuery查询DOM,但你能使用Javascript原生方法而不是通过使用第三方库来做吗?

我不只是在谈论能够通过ID或具有特定的class元素查询页面元素,我的意思是jQuery倾向使用表达式在DOM查找元素。

这里有相当多我们可以使用的原生方法,他们和jQuery一样强大,用来在页面查找一个或多个元素。我们可以使用选择器比如first-child,last-child等等。你会惊讶有这么好的原生DOM查询方法。

学习这些原生方法,并在比如jQuery的地方使用它们:

我在必要时链接了Mozilla开发者文档做进一步的阅读。任何地方你看到一个链接,如果是你不太熟悉的东西,我强烈建议你点击它。

  • document.getElementById——通过ID查找元素的经典查询。
  • document.getElementsByClassName——通过className在DOM中查找元素。
  • document.querySelector——这是一个很好的方法。它拥有jQuery $()的所有力量,它是原生的。它将只返回它发现的第一个元素。
  • document.querySelectorAll——几乎和上面的方法一样,除了它返回多个元素,而不仅仅是第一个。
  • document.getElementsByTagName——这允许查询特定标记名的元素。想在页面或span标签中找到所有DIV元素吗?这是你想要的方法。

值得一提的是querySelector和querySelectorAll方法也可以使用在一个元素上,意味着你可以使用这些方法查询一个元素的内容。

详读Element.querySelector 和 Element.querySelectorAll的使用例子。

变量提升

Javascript是一种有趣的语言,变量的声明,会将声明提升到作用域的顶部。这意味着你可以在当前作用域(比如一个函数被认为是自己的作用域)定义它之前就引用一个变量。

作为一个经验法则:永远在你需要的作用域顶部定义你的变量。如果你在脚本文件(或者在函数中)的顶部使用 ‘use strict’;而你在一个变量被定义之前使用它将抛出一个错误。

大多数Javascript linter比如Jshint,当你没有使用 ‘use strict’的定义会提示,所以提示你应用最佳实践,这样在变量定义前你不可能使用它。

一如既往,Mozilla开发人员文档有一些很好的关于语法和类型的JavaScript文章,这里有一篇关于变量提升的内容

如何使用浏览器的开发者工具

更具体地是如何调试Javascript,但也注意到你在开发者工具中用到的其他工具。如何设置断点和单步进入应用程序的特定子集的代码。

这些工具很重要,因为它们可跟踪潜在的复杂应用程序的运行步骤,找到导致一个问题或特定瓶颈的原因是什么。了解如何设置一个断点,如何在分子层面(细层面)真正深入到你的代码,看看发生了什么。

理解捆绑在Chrome、Firefox 和后期版本的 Internet Explorer 上的工具是你必不可少的技能,特别是如果你发现自己大量地使用Javascript。同时注意到各种开发工具插件,比如Google Chrome上的Batarang 扩展,它允许你调试AngularJS应用程序。

使用恰当的工具找到实际问题,不要在此之前盲目地优化你的代码。在没有搞清楚问题前解决问题,被称为过早优化,这会浪费时间。

控制台命令

除了知道如何在Chrome、Firefox 或 Internet Explorer开发工具中使用分析和调试工具,你还应该注意到各种控制台命令。

你可能已经知道console.log,还有console.error。但实际上有不少控制台命令可以使用。

请记住,有些命令在不同浏览器下可能无法正常工作。我一直留意应该被现代浏览器良好支持的命令列表,但在你往代码中加入可能不被支持的命令之前,你得试一试。

  • console.log——基本的 logging ,用来记录在我的代码中发生的动作的基本消息。格式化标识符在console调用时也被支持。
  • console.error——在代码中记录错误。我在AJAX请求的错误回调和其他会抛出错误的地方使用console.error。和console.log类似,这个方法还包括一个堆栈,用于跟踪错误在哪里。
  • console.dir(对象)——这个方便的方法可以在你的控制台窗口打印一个Javascript对象的内容。很方便。
  • console.group(标题)——这允许你通过一个可选的标题创建一组的控制台日志记录命令。意思你可以将类似的日志信息分组,比如当一段代码负责一个任务时。
  • console.groupCollapsed——和上述方法完全相同,除了最开始是折叠的,没有打开。
  • console.groupEnd——这允许你结束上面定义的组。
  • console.time(标签)——允许你测量一段特定的Javascript代码运行需要多长时间,以毫秒为单位。对测量可能的瓶颈方法尤其有效。
  • console.timeEnd(标签)——类似于groupEnd方法,这允许你停止计时器记录功能,同时运行时间将在控制台打印出来。
  • copy(字符串)——在Chrome和Firefox控制台有这个方法,它允许你将一个字符串的内容复制到剪贴板。打开开发工具,试试它,它有时可以派上用场。

理解 this

this关键字,这是不理解其工作原理的Javascript开发人员产生挫败感的一个最大来源之一。真的很容易落入大量陷阱中的某个:“this”最大的问题是什么,取决于你的Javascript结构。

在更传统的编程语言中this是由类实例化的当前对象的一个引用。但Javascript并不是一个传统的编程语言,所以this实际上属于拥有方法的对象。

在Javascript中记住this的最简单方法就是记住它的拥有者,即父亲。this的值将总是等于拥有者,除非通过call,apply或者bind改变。

在下面这个函数中,this实际上是window:

你可能会想:在一个方法中引用this时为什么this会等于window?如果你知道答案,那么很棒,但如果不知道,继续阅读,我们将解释为什么。

当你像上面定义一个函数,它绑定到全局window这个全局对象上。记得我们上面提到的,Javascript将this作为拥有方法的对象对待,而不是当前的对象?

将this的值改变成完全属于它自己的新对象(而不是窗口):

代码控可能会谴责我刚才做的事情。记住我们只是稍微触及了基本概念。但如你所见,this的值不再是window。为什么?

最简单的解释是什么时候我们使用new关键字,我们创建一个全新的上下文(因为new关键字),new操作符将创建一个全新的对象。

在以下示例中,我们将创建一个虚构的API库,它有一个方法从服务器获取数据。如你所见,我们正在创建一个叫API的对象并添加了方法。

因为我们已经创建了一个新对象,有些神奇的事发生了。上下文从全局对象切换到我们创建API对象上。