你不知道的JavaScript(下卷)(txt+pdf+epub+mobi电子书下载)


发布时间:2020-06-05 15:48:34

点击下载

作者:凯尔·辛普森

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

你不知道的JavaScript(下卷)

你不知道的JavaScript(下卷)试读:

前言

我相信你已经注意到了这一系列图书的封面上都有大大的“JS”,它并不是用来诅咒 JavaScript 的缩写,尽管我们大家都诅咒过这门语言的怪异之处。

从最早期的 Web 开始,JavaScript 就是驱动内容消费的交互式体验的基本技术。尽管闪烁的鼠标轨迹和恼人的弹出式广告可能是 JavaScript 起步的地方。但是近二十年之后,JavaScript 的技术和功能已经有了很大的发展,并且位于世界上使用最广泛的软件平台——Web 的核心,它的重要性几乎没有人再会质疑。

但是,作为一门编程语言,JavaScript 一直为人诟病,部分原因是其历史沿革,更重要的原因则是其设计理念。因为 JavaScript 这个名字,Brendan Eich 曾戏称它为“傻小弟”(相对于成熟的 Java 而言)。实际上,这个名字完全是政治和市场考量下的产物。两门语言之间千差万别,“JavaScript”之于“Java”就如同“Carnival”(嘉年华)之于“Car”(汽车)一样,两者之间并无半点关系。

JavaScript 在概念和语法风格上借鉴了其他编程语言,包括 C 风格的过程式编程和隐晦的 Scheme/Lisp 风格的函数式编程,这使得它能为不同背景的开发人员所接受,包括那些没有多少编程经验的人。用 JavaScript 编写一个“Hello World”程序非常简单。因此对于初学者而言,它是有吸引力和易学的。

JavaScript 可能是最容易上手的编程语言之一,但它的一些奇特之处使得它不像其他语言那样容易完全掌握。要想用 C 或者 C++ 开发一个完整的应用程序,开发者需要对该门语言有相当深入的了解。然而对于 JavaScript,即使我们用它开发了一个完整的系统也不见得就能深入理解它。

这门语言中有些复杂的概念隐藏得很深,却常常以一种看似简单的形式呈现。例如,将函数作为回调函数传递,这让 JavaScript 开发人员往往满足于使用这些现成便利的机制,而不愿去探究其中的原理。

JavaScript 是一门简单易用的语言,应用广泛,同时它的语言机制又十分复杂和微妙,即使经验丰富的开发人员也需要用心学习才能真正掌握。

JavaScript 的矛盾之处就在于此,它的阿喀琉斯之踵正是本书要解决的问题。因为无需深入理解就能用它来编程,所以人们常常放松对它的学习。使命

在学习 JavaScript 的过程中,碰到令人抓狂的问题或挫折时,如果置之不理或不求甚解(就像有些人习惯做的那样),我们很快就会发现自己根本无从发挥这门语言的威力。

尽管这些被称为 JavaScript 的“精华”部分,但我恳请读者朋友们将其看作“容易的”“安全的”或者“不完整的”部分。“你不知道的 JavaScript”系列丛书旨在介绍 JavaScript 的另一面,让你深入掌握 JavaScript 的全部,特别是那些难点。

JavaScript 开发人员常常满足于一知半解,不愿更深入地了解其深层原因和运作方式,本书要解决的正是这个问题。我们会直面那些疑难困惑,绝不回避。

我个人不会仅仅满足于让代码运行起来而不明就里,你也应该这样。本书中,我会逐步介绍 JavaScript 中那些不太为人所知的地方,最终让你对这门语言有一个全面的了解。一旦掌握了这些知识,那些技巧、框架和时髦术语等都将不在话下。

本系列丛书全面深入地介绍了 JavaScript 中常为人误解和忽视的重要知识点,让你在读完之后不论从理论上还是实践上都能对这门语言有足够的信心。

目前你对 JavaScript 的了解可能都来自那些自身就一知半解的“专家”,而这仅仅是冰山一角。读完本系列丛书后,你将真正了解这门语言。现在就让我们踏上阅读寻知之旅吧。综述

JavaScript 是一门优秀的语言。只学其中一部分内容很容易,但是要全面掌握则很难。开发人员遇到困难时往往将其归咎于语言本身,而不反省他们自己对语言的理解有多匮乏。本系列丛书旨在解决这个问题,使读者能够发自内心地喜欢上这门语言。 本书中的很多示例都假定你使用的是现代(以及未来)的 JavaScript 引擎环境,比如 ES6。有些代码在旧版本(ES6 之前)的引擎下可能不会像书中描述的那样工作。排版约定

本书使用了下列排版约定。● 黑体表示新术语或重点强调的内容。● 等宽字体(constant width)表示程序片段,以及正文中出现的变量、函数名、数据库、

数据类型、环境变量、语句和关键字等。● 加粗等宽字体(constant width bold)表示应该由用户输入的命令或其他文本。● 等宽斜体(constant width italic)表示应该由用户输入的值或根据上下文确定的值替换的文

本。 该图标表示提示或建议。

  该图标表示一般注记。

  该图标表示警告或警示。使用代码示例

补充材料(代码示例、练习等)可以从 http://bit.ly/ydkjs-up-going-code 和 http://bit.ly/ydkjs-es6beyond-code 下载。

本书是要帮你完成工作的。一般来说,如果本书提供了示例代码,你可以把它用在你的程序或文档中。除非你使用了很大一部分代码,否则无需联系我们获得许可。比如,用本书的几个代码片段写一个程序就无需获得许可,销售或分发 O'Reilly 图书的示例光盘则需要获得许可;引用本书中的示例代码回答问题无需获得许可,将书中大量的代码放到你的产品文档中则需要获得许可。

我们很希望但并不强制要求你在引用书中内容时加上引用说明。引用说明一般包括书名、作者、出版社和 ISBN。比如:“You Don't Know JavaScript: Up & Going by Kyle Simpson (O'Reilly). Copyright 2015 Getify Solutions, Inc., 978-1-491-92446-4”。

如果你觉得自己对示例代码的用法超出了上述许可的范围,欢迎你通过 permissions@oreilly.com 与我们联系。致谢

我要感谢很多人,是他们的帮助让本书以及整个系列得以出版。

首先,我必须感谢我的妻子 Christen Simpson 以及我的两个孩子 Ethan 和 Emily,容忍我整天坐在电脑前工作。即使不写作的时候,我的眼睛也总是盯着屏幕做一些与 JavaScript 相关的工作。我牺牲了很多陪伴家人的时间,这个系列的丛书才得以为读者深入全面地介绍 JavaScript。对于家庭,我亏欠太多。

我要感谢 O'Reilly 的编辑 Simon St.Laurent 和 Brian MacDonald,以及所有其他的编辑和市场工作人员。和他们一起工作非常愉快;本系列丛书的写作、编辑和制作都以开源方式进行,在此实验过程中,他们给予了非常多的帮助。

我要感谢所有为本系列丛书提供建议和校正的人,包括 Shelley Powers、Tim Ferro、Evan Borden、Forrest L. Norvell、Jennifer Davis、Jesse Harlin 等。十分感谢 Jenn Lukas 和 Rick Waldron 为本书作序。

我要感谢 JavaScript 社区中的许多人,包括 TC39 委员会的成员们,将他们的知识与我们分享,并且耐心详尽地回答我无休止的提问。他们是 John-David Dalton、Juriy“kangax” Zaytsev、Mathias Bynens、Axel Rauschmayer、Nicholas Zakas、Angus Croll、Reginald Braithwaite、Dave Herman、Brendan Eich、Allen Wirfs-Brock、Bradley Meck、Domenic Denicola、David Walsh、Tim Disney、Peter van der Zee、Andrea Giammarchi、Kit Cambridge、Eric Elliott、André Bargull、Caitlin Potter、Brian Terlson、Ingvar Stepanyan、Chris Dickinson、Luke Hoban,等等。还有很多人,我无法一一感谢。“你不知道的 JavaScript”系列丛书是由 Kickstarter 发起的,我要感谢近 500 名慷慨的支持者,没有他们的支持就没有这套系列丛书:

Jan Szpila、nokiko、Murali Krishnamoorthy、Ryan Joy、Craig Patchett、pdqtrader、Dale Fukami、ray hatfield、R0drigo Perez [Mx]、Dan Petitt、Jack Franklin、Andrew Berry、Brian Grinstead、Rob Sutherland、Sergi Meseguer、Phillip Gourley、Mark Watson、Jeff Carouth、Alfredo Sumaran、Martin Sachse、Marcio Barrios、Dan、AimelyneM、Matt Sullivan、Delnatte Pierre-Antoin、Jake Smith、Eugen Tudorancea、Iris、David Trinh、simonstl、Ray Daly、Uros Gruber、Justin Myers、Shai Zonis、Mom & Dad、Devin Clark、Dennis Palmer、Brian Panahi Johnson、Josh Marshall、Marshall、Dennis Kerr、Matt Steele、Erik Slagter、Sacah、Justin Rainbow、Christian Nilsson、Delapouite、D.Pereira、Nicolas Hoizey、George V. Reilly、Dan Reeves、Bruno Laturner、Chad Jennings、Shane King、Jeremiah Lee Cohick、od3n、Stan Yamane、Marko Vucinic、Jim B、Stephen Collins、Egir Porsteinsson、Eric Pederson、Owain、Nathan Smith、Jeanetteurphy、Alexandre ELISé、Chris Peterson、Rik Watson、Luke Matthews、Justin Lowery、Morten Nielsen、Vernon Kesner、Chetan Shenoy、Paul Tregoing、Marc Grabanski、Dion Almaer、Andrew Sullivan、Keith Elsass、Tom Burke、Brian Ashenfelter、David Stuart、Karl Swedberg、Graeme、Brandon Hays、John Christopher、Gior、manoj reddy、Chad Smith、Jared Harbour、Minoru TODA、Chris Wigley、Daniel Mee、Mike、Handyface、Alex Jahraus、Carl Furrow、Rob Foulkrod、Max Shishkin、Leigh Penny Jr.、Robert Ferguson、Mike van Hoenselaar、Hasse Schougaard、rajan venkataguru、Jeff Adams、Trae Robbins、Rolf Langenhuijzen、Jorge Antunes、Alex Koloskov、Hugh Greenish、Tim Jones、Jose Ochoa、Michael Brennan-White、Naga Harish Muvva、Barkóczi Dávid、Kitt Hodsden、Paul McGraw、Sascha Goldhofer、Andrew Metcalf、Markus Krogh、Michael Mathews、Matt Jared、Juanfran、Georgie Kirschner、Kenny Lee、Ted Zhang、Amit Pahwa、Inbal Sinai、Dan Raine、Schabse Laks、Michael Tervoort、Alexandre Abreu、Alan Joseph Williams、NicolasD、Cindy Wong、Reg Braithwaite、LocalPCGuy、Jon Friskics、Chris Merriman、John Pena、Jacob Katz、Sue Lockwood、Magnus Johansson、Jeremy Crapsey、Grzegorz Pawlowski、nico nuzzaci、Christine Wilks、Hans Bergren、charles montgomery、Ariel-Fogel、Ivan Kolev、Daniel Campos、Hugh Wood、Christian Bradford、Frédéric Harper、Ionut Dan Popa、Jeff Trimble、Rupert Wood、Trey Carrico、Pancho Lopez、Joel kuijten、Tom A Marra、Jeff Jewiss、Jacob Rios、Paolo Di Stefano、Soledad Penades、Chris Gerber、Andrey Dolganov、Wil Moore III、Thomas Martineau、Kareem、Ben Thouret、Udi Nir、Morgan Laupies、jory carson-burson、Nathan L Smith、Eric Damon Walters、Derry Lozano-Hoyland、Geoffrey Wiseman、mkeehner、KatieK、Scott MacFarlane、Brian LaShomb、Adrien Mas、christopher ross、Ian Littman、Dan Atkinson、Elliot Jobe、Nick Dozier、Peter Wooley、John Hoover、dan、Martin A. Jackson、Héctor Fernando Hurtado、andy ennamorato、Paul Seltmann、Melissa Gore、Dave Pollard、Jack Smith、Philip Da Silva、Guy Israeli、@megalithic、Damian Crawford、Felix Gliesche、April Carter Grant、Heidi、jim tierney、Andrea Giammarchi、Nico Vignola、Don Jones、Chris Hartjes、Alex Howes、john gibbon、David J. Groom、BBox、Yu Dilys Sun、Nate Steiner、Brandon Satrom、Brian Wyant、Wesley Hales、Ian Pouncey、Timothy Kevin Oxley、George Terezakis、sanjay raj、Jordan Harband、Marko McLion、Wolfgang Kaufmann、Pascal Peuckert、Dave Nugent、Markus Liebelt、Welling Guzman、Nick Cooley、Daniel Mesquita、Robert Syvarth、Chris Coyier、Rémy Bach、Adam Dougal、Alistair Duggin、David Loidolt、Ed Richer、Brian Chenault、GoldFire Studios、Carles Andrés、Carlos Cabo、Yuya Saito、roberto ricardo、Barnett Klane、Mike Moore、Kevin Marx、Justin Love、Joe Taylor、Paul Dijou、Michael Kohler、Rob Cassie、Mike Tierney、Cody Leroy Lindley、tofuji、Shimon Schwartz、Raymond、Luc De Brouwer、David Hayes、Rhys Brett-Bowen、Dmitry、Aziz Khoury、Dean、Scott Tolinski-Level Up、Clement Boirie、Djordje Lukic、Anton Kotenko、Rafael Corral、Philip Hurwitz、Jonathan Pidgeon、Jason Campbell、Joseph C.、SwiftOne、Jan Hohner、Derick Bailey、getify、Daniel Cousineau、Chris Charlton、Eric Turner、David Turner、Joel Galeran、Dharma Vagabond、adam、Dirk van Bergen、dave ♥♫★ furf、Vedran Zakanj、Ryan McAllen、Natalie Patrice Tucker、Eric J. Bivona、Adam Spooner、Aaron Cavano、Kelly Packer、Eric J、Martin Drenovac、Emilis、Michael Pelikan、Scott F. Walter、Josh Freeman、Brandon Hudgeons、vijay chennupati、Bill Glennon、Robin R.、Troy Forster、otaku_coder、Brad、Scott、Frederick Ostrander、Adam Brill、Seb Flippence、Michael Anderson、Jacob、Adam Randlett、Standard、Joshua Clanton、Sebastian Kouba、Chris Deck、SwordFire、Hannes Papenberg、Richard Woeber、hnzz、Rob Crowther、Jedidiah Broadbent、Sergey Chernyshev、Jay-Ar Jamon、Ben Combee、luciano bonachela、Mark Tomlinson、Kit Cambridge、Michael Melgares、Jacob Adams、Adrian Bruinhout、Bev Wieber、Scott Puleo、Thomas Herzog、April Leone、Daniel Mizieliński、Kees van Ginkel、Jon Abrams、Erwin Heiser、Avi Laviad、David newell、Jean-Francois Turcot、Niko Roberts、Erik Dana、Charles Neill、Aaron Holmes、Grzegorz Ziólkowski、Nathan Youngman、Timothy、Jacob Mather、Michael Allan、Mohit Seth、Ryan Ewing、Benjamin Van Treese、Marcelo Santos、Denis Wolf、Phil Keys、Chris Yung、Timo Tijhof、Martin Lekvall、Agendine、Greg Whitworth、Helen Humphrey、Dougal Campbell、Johannes Harth、Bruno Girin、Brian Hough、Darren Newton、Craig McPheat、Olivier Tille、Dennis Roethig、Mathias Bynens、Brendan Stromberger、sundeep、John Meyer、Ron Male、John F Croston III、gigante、Carl Bergenhem、B.J. May、Rebekah Tyler、Ted Foxberry、Jordan Reese、Terry Suitor、afeliz、Tom Kiefer、Darragh Duffy、Kevin Vanderbeken、Andy Pearson、Simon Mac Donald、Abid Din、Chris Joel、Tomas Theunissen、David Dick、Paul Grock、Brandon Wood、John Weis、dgrebb、Nick Jenkins、Chuck Lane、Johnny Megahan、marzsman、Tatu Tamminen、Geoffrey Knauth、Alexander Tarmolov、Jeremy Tymes、Chad Auld、Sean Parmelee、Rob Staenke、Dan Bender、Yannick derwa、Joshua Jones、Geert Plaisier、Tom LeZotte、Christen Simpson、Stefan Bruvik、Justin Falcone、Carlos Santana、Michael Weiss、Pablo Villoslada、Peter deHaan、Dimitris Iliopoulos、seyDoggy、Adam Jordens、Noah Kantrowitz、Amol M、Matthew Winnard、Dirk Ginader、Phinam Bui、David Rapson、Andrew Baxter、Florian Bougel、Michael George、Alban Escalier、Daniel Sellers、Sasha Rudan、John Green、Robert Kowalski、David I. Teixeira (@ditma)、Charles Carpenter、Justin Yost、Sam S、Denis Ciccale、Kevin Sheurs、Yannick Croissant、Pau Fracés、Stephen McGowan、Shawn Searcy、Chris Ruppel、Kevin Lamping、Jessica Campbell、Christopher Schmitt、Sablons、Jonathan Reisdorf、Bunni Gek、Teddy Huff、Michael Mullany、Michael Fürstenberg、Carl Henderson、Rick Yoesting、Scott Nichols、Hernán Ciudad、Andrew Maier、Mike Stapp、Jesse Shawl、Sérgio Lopes、jsulak、Shawn Price、Joel Clermont、Chris Ridmann、Sean Timm、Jason Finch、Aiden Montgomery、Elijah Manor、Derek Gathright、Jesse Harlin、Dillon Curry、Courtney Myers、Diego Cadenas、Arne de Bree、Joao Paulo Dubas、James Taylor、Philipp Kraeutli、Mihai Paun、Sam Gharegozlou、joshjs、Matt Murchison、Eric Windham、Timo Behrmann、Andrew Hall、joshua price、Théophile Villard

这套系列丛书的写作、编辑和制作都是以开源的方式进行的。我要感谢 GitHub 让这一切成为可能!

再次向我没能提及的支持者们表示感谢。这套系列丛书属于我们每一个人,希望它能够帮助更多的人更好地了解 JavaScript,让当前和未来的社区贡献者受益。第一部分起步上路序

你最近新学的技能是什么?

可能是一门外语,比如意大利语或德语。可能是一个图像编辑工具,如 Photoshop。也可能是某种厨艺或者木工活,又或是某种健身项目。请回忆一下你最终掌握这项技能的那个时刻,那应该就是你突然顿悟的一刻。当你学会操控台锯或者理解了法语中阳性名词和阴性名词之间的区别时,事情就从模糊变得明朗清晰起来。那时感觉如何?是不是非常不可思议?

现在,再往前回忆一下你掌握这项新技能之前的情形。那时你是什么感觉呢?可能有点恐惧又有点心慌,是不是?在某一刻,我们还不了解自己现在已经掌握的知识,这完全没有任何问题;每个人都是从某个起点开始学习的。学习新技能是一场令人激动的探险,特别是当你想要高效学习某个主题时。

我教授过很多初级的编程课程。跟着我学习的学生通常之前已经试着通过博客或复制、粘贴代码来自学过 HTML 或者 JavaScript 这样的主题,但是他们并没有能够真正掌握编码知识来实现想要的目标。而且,由于并没有真正掌握某些编程主题的细节,他们便无法编写功能强大的代码或调试自己的作品,因为他们并没有真正理解所发生的一切。

我一直坚信要以正确的方法授课,这意味着我会讲授 Web 标准、语义标记、注释良好的代码以及其他的最佳实践。我会详细讲解涉及的主题,解释如何做以及这么做的原因,而不仅仅是扔出代码以供复制、粘贴。努力理解自己的代码后,你就可以更好地完成任务,同时自己也会得到进步。此时代码不再仅仅只是你的工作,更是你的作品。这就是我喜欢本书内容的原因。Kyle 带领我们深入了解语法和术语,对 JavaScript 这个语言进行了出色、全面的介绍。本书并没有流于表面,而是确实有助于我们真正理解概念。

就像只学会如何在 Photoshop 中打开、关闭和保存文档是不够的,只能够将 jQuery 代码片段复制到你的网站上也是不够的。的确,只需要学习一些与编程相关的基础知识,我就能够编写并共享自己的设计。但如果没有对工具及其背后原理的正确理解,我怎么能够定义一个网格或创建一个明晰的类型系统呢?又如何才能优化 Web 上的图像呢?对 JavaScript 来说也是一样的。如果不清楚循环的工作模式、变量的定义以及作用域的含义,那么我们就无法编写自己所能实现的最佳代码。我们不能接受退而求其次的作品,毕竟这是我们自己的作品。

你对 JavaScript 的探索越深入,它就会变得越清晰。或许你对闭包、对象和方法这样的词汇目前来说还不是很熟悉,但本书将帮助你明晰这些术语。我希望你在开始学习本书时记住自己学习某样东西前后的感受。这可能很艰巨,但为了要开始一段磨砺你的知识宝剑的精彩之旅,你已经翻阅至此。本书第一部分是我们理解编程的起点。享受你顿悟的时刻吧!——Jenn Lukas(http://jennlukas.com, @jennlukas),前端顾问第1章深入编程

欢迎来到“你不知道的 JavaScript”系列。

本部分介绍了编程中的一系列基本概念,并有助于你更好地理解本系列其余几本书的内容。当然,本部分的内容会更偏向于 JavaScript(常简写为 JS)。如果你是刚开始学习编程或 JavaScript,那么本部分将会简单探讨你起步和继续学习所需要了解的概念。

本部分一开始会从很高的层次来介绍编程的基本原则。基本上假设你在阅读“你不知道的 JavaScript”系列图书时几乎没有编程经历,并想要通过学习这几本书从 JavaScript 这个视角开始理解编程。

第 1 章总结了深入学习和实践编程所需要的知识,此外还有许多其他介绍编程的优秀资源,这些资源可以帮助你更深入地探索这些主题。除了第 1 章的知识,我建议你还要利用这些资料来更深入地学习。

在熟悉了常用的基础编程概念后,第 2 章将帮助你熟悉 JavaScript 的编程风格。第 2 章介绍了 JavaScript 的含义,但再次声明,这并不是完整的指南——这是“你不知道的 JavaScript”系列其余几本图书的主旨!

如果你已经对 JavaScript 有了一定的了解,那么可以先查看第 3 章来了解“你不知道的 JavaScript”系列图书的简介,然后直接阅读你所感兴趣的章节!1.1 代码

让我们从头开始。

程序常被称为源码或代码,它是一组特定的指令,用来指示计算机要执行哪些任务。虽然对 JavaScript 来说可以直接在浏览器的开发者终端中输入代码,但代码通常会被保存在文本文件中,我们将在后文中对此进行简单介绍。

指令的格式和组合规则被称为计算机语言,有时也被称为语法,这非常类似于英语中告诉你如何拼写单词以及如何使用单词和标点符号来构造有效的句子。语句

在计算机语言中,执行特定任务的一组单词、数字和运算符被称为语句。在 JavaScript 中,一条语句可能如下所示:a = b * 2;

其中的字符 a 和 b 称为变量(参见 1.7 节),它们就好比是可以存放东西的小盒子。在程序中,变量保存程序要使用的值(比如数字 42)。你可以将它们想象成值本身的替代符。

相比之下,2 本身就是一个值,称为字面值,因为它独立存在而没有保存在变量之中。

其中的字符 = 和 * 是运算符(参见 1.4 节),它们对值和变量执行动作,如赋值和进行乘法运算。

JavaScript 的多数语句都是以分号(;)结尾的。

粗略地说,语句 a = b * 2; 告诉计算机获取变量 b 的当前值,然后将这个值乘以 2,再将计算结果保存到另一个名为 a 的变量中。

程序就是多个这样语句的集合,它们合起来描述了程序要执行的所有步骤。1.2 表达式

语句由一个或多个表达式组成。一个表达式是对一个变量或值的引用,或者是一组值和变量与运算符的组合。

举例来说,a = b * 2; 这个语句中有四个表达式。● 2 是一个字面值表达式。● b 是一个变量表达式,表示获取它的当前值。● b * 2 是一个算术表达式,表示进行乘法运算。● a = b * 2 是一个赋值表达式,意思是将表达式 b * 2 的结果赋值

给变量 a(我们将在后文中深入介绍赋值)。

一个独立的表达式也可以称为表达式语句,如下所示:b * 2;

这种表达式语句不是很常用,或者说不是很有用,因为它通常不会对程序的运行起到任何作用,它只是取得 b 的值并乘以 2,但是却没有对结果有任何影响。

更常用的表达式语句是调用表达式语句(参见 1.11 节),因为整个语句本身就是一个函数调用表达式:alert( a );执行程序

这些编程语句的集合是如何通知计算机来执行任务的呢?程序需要被执行,我们也将这一过程称为运行程序。

a = b * 2 这样的语句便于开发者读写,但实际上计算机并不能直接理解这种形式。因此,需要通过计算机上一个专门的工具(解释器或编译器)将你编写的代码翻译成计算机可以理解的命令。

对某些计算机语言来说,在程序被执行时,对命令的翻译通常是自上而下逐行执行的,这通常被称为代码解释。

对另外一些语言来说,这种翻译是预先进行的,被称为代码编译,这样一来,当执行程序时,实际上运行的是已经编译好的、可以执行的计算机指令。

基本上可以说 JavaScript 是解释型的,因为每次执行 JavaScript 源码时都需要进行处理。但这么说并不完全精确。JavaScript 引擎实际上是动态编译程序,然后立即执行编译后的代码。 有关 JavaScript 编译的更多信息,参见本系列《你不知道1的 JavaScript(上卷)》第一部分中的前两章。

1此书已由人民邮电出版社出版。——编者注1.3 实践

本章将通过简单的代码片段来介绍每个编程概念,这些代码(当然)是用 JavaScript 编写的。

非常重要的一点是,在阅读本章时,你应该通过亲自编写代码来实践每个概念,并且你可能需要花一点时间反复阅读本章。最简单的方法是,使用最方便的浏览器(Firefox、Chrome、IE 等)的开发者工具来实践。一般来说,你可以通过菜单项或者快捷键来打开开发者终端。有关在你喜欢的浏览器中打开和使用终端的更多详细信息,参见“掌握开发者工具终端”(http://blog.teamtreehouse.com/mastering-developer-tools-console)。如果要在终端中一次输入多行,那么可以使用 + 组合键来另起一行。一旦点击 键,终端会立即执行已输入的所有代码。

我们来熟悉一下在终端中运行代码的流程。首先,建议你在浏览器中打开一个空白的标签页。我更喜欢在地址栏中输入 about:blank 来实现这一点。然后,确保你的开发者终端是开启状态,就像我们之前提到的那样。

现在,输入如下代码,并观察代码的执行:a = 21;b = a * 2;console.log( b );

在 Chrome 浏览器的终端中输入前面的代码将会产生如下所示的输出:

你可以自己试一下。学习编程的最好方法就是编写代码!1.3.1 输出

在前面的代码片段中,我们使用了 console.log(..)。现在我们来简单了解一下这行代码做了些什么。

可能你已经猜到了,这就是我们在开发者终端打印文本(即向用户输出)的方法。我们应该对这个语句的两点解释一下。

首先,log( b ) 这一部分是一个函数调用(参见 1.11 节)。我们将变量 b 传给这个函数,请求它将 b 的值打印到终端中。

其次,console. 这一部分是 log(..) 函数所在的对象引用。我们将在第 2 章中深入介绍对象及其属性。

创建可见输出的另外一个方法是运行 alert(..) 语句。如下所示:alert( b );

如果运行这个语句,那么你就会发现输出并没有打印到终端中,而是弹出一个“OK”对话框,变量 b 的内容会呈现在对话框中。然而,在终端中学习和运行程序时,使用 console.log(..) 通常比使用 alert(..) 更加方便,因为这样无需与浏览器界面交互就可以一次输出多个变量。

我们在本部分中使用 console.log(..) 作为输出方法。1.3.2 输入

在讨论输出的同时,你可能也会好奇如何实现输入(即如何接收用户的信息)。

最常用的方法是,通过 HTML 页面向用户显示表单元素(如文本框)用于输入,然后通过 JavaScript 将这些值读取到程序变量中。

还有另一种更为简单的获取输入的方法,用于简单的学习和展示,这也是我们将会使用的方法,即 prompt(..) 函数:age = prompt( "Please tell me your age:" );console.log( age );

你可能已经猜到了,传给 prompt(..) 的消息会打印到弹出窗口中,本例中是 "Please tell me your age:"。

如下图所示:

输入文本并点击“OK”后,你就可以看到输入的值会保存到变量 age 中,接着通过 console.log(..) 输出:

为了简化难度,在学习基本编程概念时,本部分中使用的示例都不需要输入。但既然你已经学习了如何使用 prompt(..),如果想要挑战自我,你可以在自己的示例中使用输入。1.4 运算符

使用运算符,我们可以对变量和值执行操作。我们已经在前文中看到了 = 和 * 这两个 JavaScrit 运算符。

运算符 * 执行算术乘法。很简单,对吧?

等号运算符 = 用于赋值——我们先计算 = 右边(源值)的值,然后将它存入左边(目标变量)指定的变量中。 这种赋值方法的顺序看起来是反的,有点奇怪。有些人可能更习惯将顺序调过来,将源值放在左边,目标变量放在右边,不用 a = 42 这种形式,而是 42 -> a(这不是合法的 JavaScript)。但问题是,a = 42 这种顺序以及类似的变体在现代编程语言中是非常流行的。如果感觉不太习惯的话,那么你就要花点时间来习惯它,并将它植入到你的思维中。

考虑:a = 2;b = a + 1;

在上述示例中,我们将值 2 赋给变量 a。然后,我们取得变量 a 的值(仍然是 2),加上 1,得到结果 3,再将这个值保存在变量 b 中。

虽然 var 严格意义上说并不是一个运算符,但每个程序都会用到这个关键词,因为它是声明(也就是创建)变量(参见 1.7 节)的基本方法。

在使用变量前总是应该先声明变量。一个变量在每个作用域(参见 1.11 节)中只需要声明一次;声明之后可以按照需要多次使用。如下所示:var a = 20;a = a + 1;a = a * 2;console.log( a ); // 42

以下是 JavaScript 中最常用的一些运算符。● 赋值=,如 a = 2 就表示将值 2 保存在变量 a 中。● 算术+(加)、-(减)、*(乘)、/(除),如 a * 3。● 复合赋值+=、-=、*= 和 /= 是复合运算符,可以将算术运算符与赋值

组合起来,比如,a += 2 等同于 a = a + 2。● 递增 / 递减++ 表示递增,-- 表示递减,比如 a++ 就类似于 a = a + 1。● 对象属性访问如 console.log() 中的 .。对象是在名为属性的位置中持有其他值的值。obj.a 指的是

一个名为 obj 的对象值,并伴有一个属性名为 a 的属性。也可以

通过 obj["a"] 这种形式访问属性。参见第 2 章。● 相等==(粗略相等)、===(严格相等)、!=(粗略不等)和 !

==(严格不等),如 a == b。参见 2.1 节。● 比较<(小于)、>(大于)、<=(小于或粗略等于)和 >=(大

于或粗略等于),如 a <= b。参见 2.1 节。● 逻辑&&(与)和 ||(或),如 a || b 就表示 a 或者 b。这些运算符用于表示复合条件(参见 1.9 节),比如 a 或 b

为真。 有关运算符的更多细节以及这里没有覆盖到的更多介绍,参见 Mozilla 开发者网络的“表达式与运算符”(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators)。1.5 值与类型

如果你向手机店的店员咨询某款手机的价格,他会回答说“99.99”(也就是 99.99 美元),那么他给你的是一个实际的美元数,表示购买手机需要付的金额(加上税)。如果你想要买两部这款手机,那么可以很容易地算出价格为 199.98 美元。

如果这个店员拿起另一个类似的手机,声称它是“免费的”(很可能要签约),这时他并没有给出一个具体的数字,而是价格($0.00)的另外一种表示方法——“免费”。

接着,如果你询问手机是否附带充电器,那么你得到的答案只会是“是”或“否”。

同样,当在程序中表达某些值时,根据将对这些值进行的操作,你可以为这些值选择不同的表示方法。

在编程术语中,对值的不同表示方法称为类型。JavaScript 为以下这些基本值提供了内置类型。● 在计算时,你需要的是一个数字(number)。● 在屏幕上打印一个值时,你需要的是一个字符串(string,一个

或多个字符、单词或句子)。● 在程序中作出决策时,你需要的是一个布尔值(boolean,true

或者 false)。

直接包含在源码中的值被称为字面值。字符串字面值由双引号("...")或单引号('…')围住,二者的唯一区别只是风格不同。数字和布尔型字面值可以直接表示(如 42、true 等)。

考虑:"I am a string";'I am also a string';42;true;false;

除了字符串 / 数字 / 布尔值类型,编程语言通常还会提供数组、对象、函数等。我们将在本章和下一章中更深入地介绍值和类型。类型转换

如果需要在屏幕上打印出一个数字,那么就需要将这个值转化为字符串,在 JavaScript 中,这种转化称为“类型转换”。类似地,如果向电子商务网页的表单中输入一系列数字字符,那么这都是字符串,但如果需要使用这些值进行数学计算,则需要将其转换为数字。

JavaScript 为类型间的强制转换提供了几种不同的机制。举例来说:var a = "42";var b = Number(a);console.log( a ); // "42"console.log( b ); // 42

如上所示,Number(..)(一个内置函数)的使用是一种显式的类型转换,可以将任意类型转换为数字类型。这应该是很直观的。

但是,如果需要进行比较的是不同类型的两个值,那么会怎么样呢?这就是一个很有争议的问题了,需要隐式的类型转换。

如果要比较字符串 "99.99" 和数字 99.99,多数人会认为它们是相等的,但它们其实并不完全相同,难道不是吗?它们是两种表示方法下的同一个值,属于两种不同的类型。你可以说它们是“粗略相等”,是这样吗?

为了帮助你处理这些常见的情形,JavaScript 有时会隐式地将值转换到匹配的类型。

因此,如果你使用 == 粗略相等运算符来判断 "99.99" == 99.99 是否成立,JavaScript 会将左边的 "99.99" 转换为等价的数字类型 99.99。这时比较就变成了 99.99 == 99.99,当然为 true 了。

尽管隐式类型转换的设计意图是为了提供便利,但如果你没有花时间学习其行为方式的规则的话,它也可能会产生误导。而多数 JavaScript 开发者从来没有花时间来学习这一知识,所以他们普遍感觉隐式类型转换令人迷惑,并且会让程序产生出乎意料的 bug。他们认为应该尽量避免隐式类型转换。隐式类型转换甚至被称为是语言设计中的缺陷。

然而,隐式类型转换是可以学习的机制,任何想要严肃对待 JavaScript 编程的人都应该学习。不仅仅是因为一旦掌握了其规则,就不会再被它迷惑,实际上这也可以提高你的程序质量!所以为此付出努力是十分值得的。 有关类型转换的更多信息,参见下一章和本系列《你不知2道的 JavaScript(中卷)》第一部分中的第 4 章。

2此书已由人民邮电出版社出版。——编者注1.6 代码注释

手机商店的店员可能会草草记下新发布手机的特性或者其公司提供的新套餐。这些笔记只是给店员看的,而不是给顾客阅读的。然而,通过记录要向顾客提供的信息以及提供方式,这些笔记可以帮助店员提高自己的工作质量。

这里可以学到的最重要的一点是,编写代码并不只是为了给计算机看。在给计算机看的同时,代码同样要给开发者阅读。

计算机只关心机器码,也就是那些编译之后得到的二进制 0 和 1 序列。要想得到同样的 0 和 1 序列,几乎有无数种程序写法。而你选择的程序编写方案很重要,这不只是对你个人来说,对小组的其他成员,甚至对未来的你也同样很重要。

编写程序时不仅应该努力做到让程序能够正确执行,而且应该做到使代码阅读起来也是容易理解的。你可能需要花费很多精力为变量(参见 1.7 节)和函数(参见 1.11 节)选择一个好的名字。

另一个非常重要的部分是代码注释。这是程序中的文本,将其插入程序只是为了向人类解释说明代码的执行。解释器 / 编译器会忽略这些注释。

有关如何编写注释良好的代码有很多种观点;我们确实无法定义绝对的普遍标准。但是以下这些观察结论和指导原则是很有用的。● 没有注释的代码不是最优的。● 过多注释(比如每行一个)可能是拙劣代码的征兆。● 代码应该解释为什么,而非是什么。如果编写的代码特别容易令

人迷惑的话,那么注释也可以解释一下实现原理。

JavaScript 中的注释有两种类型:单行注释和多行注释。

考虑:// 这是一个单行注释/* 而这是 一个多行 注释。 */

如果想要将注释放到单个语句上方或者一行的末尾,那么可以使用单行注释 //。这一行中位于 // 之后直到行尾的所有内容都会被当作注释(因此会被编译器忽略)。单行注释的内容没有限制。

考虑:var a = 42; // 42是生命的意义

多行注释 /* .. */ 适用于在注释中需要多行解释的情况。

以下是多行注释常用的一个场景:/* 使用下面的值是因为 可以看到它回答了 宇宙中所有的问题 */var a = 42;

多行注释也可以出现在行中的任意位置,甚至可以出现在行中间,因为 */ 会结束注释。如下所示:var a = /* 任意值 */ 42;console.log( a ); // 42

唯一不能出现在多行注释中的是 */,因为这会被解释为注释的结束。

开始学习编程时一定要养成注释代码的习惯。在本章后面的内容中,你会看到我使用注释来进行解释,所以你在自己的练习中也应该这么做。相信我,如果你这么做的话,每个阅读你代码的人都会感谢你的!1.7 变量

大多数的实用程序都需要跟踪值的变化,因为程序在执行任务时会对值进行各种操作,值会不断发生变化。

在程序中实现这一点的最简单方法是将值赋给一个符号容器,这个符号容器称为变量,使用这个名字是因为这个容器中的值是可以变化的。

在某些编程语言中,你需要声明一个变量(容器)用于存放指定类型的值(如数字或字符串)。通过避免不想要的值转换,人们认为这种静态类型(也称为类型强制)提高了程序的正确性。

其他语言强调的是值的类型而不是变量的类型。弱类型(也称为动态类型)允许一个变量在任意时刻存放任意类型的值。这种方式允许一个变量在程序的逻辑流中的任意时刻代表任意类型的值,人们认为这样可以提高程序的灵活性。

JavaScript 采用了后一种机制——动态类型,这也就是说,变量可以持有任意类型值而不存在类型强制。

前面提到过,我们使用 var 语句声明一个变量。注意,声明中没有额外的类型信息。考虑以下这个简单的程序:var amount = 99.99;amount = amount * 2;console.log( amount ); // 199.98// 将amount转化为一个字符串, 并在开头添加 "$"amount = "$" + String( amount );console.log( amount ); // "$199.98"

变量 amount 开始时持有值 99.99,然后持有 amount * 2 的结果值,也就是 199.98。

第一个 console.log(..) 命令需要隐式地转换类型,将数字值转换为字符串用于输出。

然后语句 amount = "$" + String(amount) 显式地将值 199.98 转换为字符串,并在开头加上字符 "$"。此时,amount 持有字符串值 "$199.98",所以第二个 console.log(..) 语句打印输出时就不需要转换类型了。

JavaScript 开发者应该注意到变量 amount 表示值 99.99、199.98 和 "$199.98" 的这种灵活性。静态类型的狂热支持者可能会单独使用一个变量,例如,使用 amountStr 来保存最后的 "$199.98",因为这是一个不同的类型。

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载