产品特色
编辑推荐
适读人群 :JavaScript程序员及爱好者。 通过全书归纳的68个行之有效的方法和大量具体实例,你将学会:
更好地使用基于原型的面向对象编程方式
数组和字典对象的微妙区别和解决方案
JavaScript函数和变量作用域语义方面的精确、务实的解说
一些有用的JavaScript编程模式和惯用法,比如选项对象和方法链
使用JavaScript独特的“运行到完成”的方式深入阐释并发
内容简介
本书由资深 JavaScript 技术专家 David Herman 所著。书中基于 JavaScript 标准的新版本阐明了 JavaScript 语言的内部运作机制――帮助你充分利用 JavaScript 语言的表现力。通过全书归纳的 68 个行之有效的方法和大量具体实例,作者详细讲解了如何更有效地运用这门灵活且富有表现力的语言,以及如何规避其缺陷。你将学到如何选择正确的编程风格,管理一些超出意料的问题,以及成功使用 JavaScript 编程完成从数据结构到并发的方方面面。
无论你写了多久的 JavaScript 代码,本书都将有助于增进你对这门强大的编程语言的理解,助你编写更可预测、更可靠且具维护性的程序。
作者简介
David Herman,资深JavaScript技术专家,Ecma TC39委员会成员,负责JavaScript的标准化工作。他拥有格林内尔学院的计算机科学学士学位和美国东北大学的计算机科学硕士及博士学位,现任Mozilla研究院高级研究员。
精彩书评
这是一本绝不辜负 Effective 软件开发系列期望的编程书籍。对于任何一位想要做到严谨编程的 JavaScript 开发者来说,这本书绝对不容错过。本书阐述了 JavaScript 内部工作细节,以期帮助读者更好地利用 JavaScript 语言优势。
——Erik Arvidsson,高级软件工程师
很少有像 David 这样的编程语言极客能如此舒适、 友好地讲解编程语言。他带我们领会 JavaScript 的语法和语义,这个过程既令人陶醉又极其深刻。本书以舒适的节奏额外提供了一些“有问题”的现实案例。当读完这本书后,你会感觉自己获得了一种强大而全面的掌控能力。
——Paul Irish,Google Chrome 开发主管
在阅读本书之前,我以为它只是另一本关于如何更好地使用 JavaScript 编程的书籍。然而它远不止如此,它还会使你更深入地理解 JavaScript 这门语言,这一点至关重要。如果没有这层对 JavaScript 的深入理解,那么你绝不会懂得语言本身的任何东西,知道其他的程序员是如何编写代码的。
如果你想成为一名真正优秀的 JavaScript 开发者,那么请阅读此书。就我而言,我多么希望在一次用 JavaScript 编程时就已经阅读了它。
——Anton Kovalyov,JSHint 开发者
如果你正在寻找一本正式且极具可读性及洞察力的 JavaScript 语言书籍的话,那不用舍近求远了。JavaScript 开发者能够从其中找到珍贵的知识宝藏,甚至技术精湛的 JavaScript 程序员也一定能从中获益。对于有其他语言经验而想一头扎进 JavaScript 世界的从业人员来说,本书是迅速学习 JavaScript 的必读之物。然而,不管你的背景如何,都不得不承认作者 Dave Herman 在探索 JavaScript 方面做得非常棒——JavaScript 的优势部分、不足部分或介于两者之间的所有内容都囊括于本书之中。
——Rebecca Murphey,Bocoup 高级 JavaScript 开发者
对于任何一位理解 JavaScript 并且想要完全掌握它的人来说,本书都是必不可少的读物。Dave Herman 带给了读者深刻的、具有研究和实践意义的 JavaScript 语言理解,通过一个接一个的例子指导并帮助读者达到与他同样的理解高度。这不是一本寻求捷径的书籍,恰恰相反,它是一本难得的将经验提炼为指南的书籍。它是一本为数不多让我毫不犹豫推荐的关于 JavaScript 的书籍。
——Alex Russell,TC39 成员,Google 软件工程师
很少有人能有机会学到大师的手艺。这本书弥补了这种遗憾,其对 JavaScript 的研究就像随一位时间旅行哲学家回到公元前 5 世纪与柏拉图一同学习一般。
——Rick Waldron,JavaScript 传教士,Bocoup
目录
推荐序
前言
致谢
关于作者
Chapter 1: Accustoming Yourself to JavaScript
Item 1: Know Which JavaScript You Are Using
Item 2: Understand JavaScript’s Floating-Point Numbers
Item 3: Beware of Implicit Coercions
Item 4: Prefer Primitives to Object Wrappers
Item 5: Avoid using == with Mixed Types
Item 6: Learn the Limits of Semicolon Insertion
Item 7: Think of Strings As Sequences of 16-Bit Code Units
Chapter 2: Variable Scope
Item 8: Minimize Use of the Global Object
Item 9: Always Declare Local Variables
Item 10: Avoid with
Item 11: Get Comfortable with Closures
Item 12: Understand Variable Hoisting
Item 13: Use Immediately Invoked Function Expressions to Create Local Scopes
Item 14: Beware of Unportable Scoping of Named Function Expressions
Item 15: Beware of Unportable Scoping of Block-Local Function Declarations
Item 16: Avoid Creating Local Variables with eval
Item 17: Prefer Indirect eval to Direct eval
Chapter 3: Working with Functions
Item 18: Understand the Difference between Function, Method, and Constructor Calls
Item 19: Get Comfortable Using Higher-Order Functions
Item 20: Use call to Call Methods with a Custom Receiver
Item 21: Use apply to Call Functions with Different Numbers of Arguments
Item 22: Use arguments to Create Variadic Functions
Item 23: Never Modify the arguments Object
Item 24: Use a Variable to Save a Reference to arguments
Item 25: Use bind to Extract Methods with a Fixed Receiver
Item 26: Use bind to Curry Functions
Item 27: Prefer Closures to Strings for Encapsulating Code
Item 28: Avoid Relying on the toString Method of Functions
Item 29: Avoid Nonstandard Stack Inspection Properties
Chapter 4: Objects and Prototypes
Item 30: Understand the Difference between prototype, getPrototypeOf, and__proto__
Item 31: Prefer Object.getPrototypeOf to __proto__
Item 32: Never Modify __proto__
Item 33: Make Your Constructors new-Agnostic
Item 34: Store Methods on Prototypes
Item 35: Use Closures to Store Private Data
Item 36: Store Instance State Only on Instance Objects
Item 37: Recognize the Implicit Binding of this
Item 38: Call Superclass Constructors from Subclass Constructors
Item 39: Never Reuse Superclass Property Names
Item 40: Avoid Inheriting from Standard Classes
Item 41: Treat Prototypes As an Implementation Detail
Item 42: Avoid Reckless Monkey-Patching
Chapter 5: Arrays and Dictionaries
Item 43: Build Lightweight Dictionaries from Direct Instances of Object
Item 44: Use null Prototypes to Prevent Prototype Pollution
Item 45: Use hasOwnProperty to Protect Against Prototype Pollution
Item 46: Prefer Arrays to Dictionaries for Ordered Collections
Item 47: Never Add Enumerable Properties to Object.prototype
Item 48: Avoid Modifying an Object during Enumeration
Item 49: Prefer for Loops to for...in Loops for Array Iteration
Item 50: Prefer Iteration Methods to Loops
Item 51: Reuse Generic Array Methods on Array-Like Objects
Item 52: Prefer Array Literals to the Array Constructor
Chapter 6: Library and API Design
Item 53: Maintain Consistent Conventions
Item 54: Treat undefined As “No Value”
Item 55: Accept Options Objects for Keyword Arguments
Item 56: Avoid Unnecessary State
Item 57: Use Structural Typing for Flexible Interfaces
Item 58: Distinguish between Array and Array-Like
Item 59: Avoid Excessive Coercion
Item 60: Support Method Chaining
Chapter 7: Concurrency
Item 61: Don’t Block the Event Queue on I/O
Item 62: Use Nested or Named Callbacks for Asynchronous Sequencing
Item 63: Be Aware of Dropped Errors
Item 64: Use Recursion for Asynchronous Loops
Item 65: Don’t Block the Event Queue on Computation
Item 66: Use a Counter to Perform Concurrent Operations
Item 67: Never Call Asynchronous Callbacks Synchronously
Item 68: Use Promises for Cleaner Asynchronous Logic
Index
前言/序言
推荐序
众所周知,我在1995年5月用10天时间创建了JavaScript语言。迫于现实的压力和冲突管理的势在必行,我将JavaScript设计为“看起来像Java”、“对初学者来说极简单”、“在网景浏览器中几乎能控制它的一切”的编程语言。
鉴于极具挑战性的要求和非常短的时间表,我的解决方案除了正确获得了两大特性(第一类函数、对象原型)之外,还将JavaScript设计得从一开始就极具延展性。我知道一些开发者不得不为最开始的几个版本“打补丁”来修正错误,这些先驱的方法比我使用内置库胡乱拼凑的方法要好。举例来说,虽然许多编程语言都限制了可变性,在运行时不能修改或扩展内置对象,或者标准库的名称绑定不能通过赋值被覆盖,但是JavaScript几乎允许完全改变每个对象。
总的来说,我相信这是一个很好的设计决定。它明确了某些领域的挑战(如在浏览器的安全边界内,安全地混用可信和不可信的代码)。对于JavaScript来说,支持所谓的猴子补丁是很重要的。凭借它,开发者可以编辑标准对象来解决Bug和仿效“未来”的功能改造一些旧的浏览器(称为polyfill库的shim,在美式英语中称为spackle)。
除了这些平凡的应用之外,JavaScript的可塑性鼓励用户沿着几个更富有创造性的方向形成和发展创新网络。这使得用户仿效其他编程语言,创建了许多工具包和框架库:基于Ruby的Prototype、基于Python的MochiKit、基于Java的Dojo及基于Smalltalk的TIBET。随后是jQuery库(“JavaScript的新浪潮”),2007年,我第一次看到它,我觉得自己似乎是一个后来者。它暴风雨般地引领着JavaScript的世界,异于其他编程语言,从旧的JavaScript库中学习,开辟了浏览器的“查询和做”(query and do)模型,从根本上简化了浏览器。
这引领着JavaScript用户群及其创新网络,使JavaScript的风格自成一派。这种风格仍在仿效和简化其他的程序库,也促成了现代Web标准化的工作。
在这一演变过程中,JavaScript保持了向后兼容,当然默认情况下,它是可变的。另外,在ECMAScript标准最新的版本中新增了一些方法来冻结对象和封闭对象的属性,以防止对象扩展和属性被覆盖。JavaScript的演进之旅远未结束。这就像生活的语言和生物系统一样,变化始终存在。在此之前,我无法预见一个单一的横扫其他程序库的“标准库”或编码风格。
任何语言都是怪癖的,或者语言几乎都是受限地执行常见的上佳实践。JavaScript是一门怪癖的或者充满限制主义色彩的编程语言。因此,与大多数其他的编程语言相比,想要高效地使用JavaScript编程,开发人员必须学习和追求优秀的风格、正确的用法和上佳的实践。当考虑如何做到最高效,我相信避免过度编程和构建刚性或教条式的风格指南是至关重要的。
本书以一种平衡的方式讲解JavaScript编程。它基于一些具体的实证和经验,而不迂回于刚性或过度的方法。我认为对于许多寻找在不牺牲表现力的前提下,还可以自由采用新思想和编程范式来编写高效JavaScript的人来说,本书是一位重要的助手和可信赖的向导。它也是一本备受关注、充满乐趣和拥有许多令人叹为观止的示例的读物。
最后,自2006年以来,我有幸结识David Herman。那是我第一次以Mozilla代表的身份邀请他作为特邀专家在Ecma标准化机构工作。Dave深刻、谦逊的专家意见及他的热情让JavaScript在书中的每一页大放异彩。本书精彩绝伦!
——Brendan Eich
《代码炼金术:精益求精的JavaScript编程之道》 在瞬息万变的数字时代,JavaScript已不仅仅是网页的脚本语言,它已演变成一门强大而灵活的编程范式,渗透到前端、后端、移动端乃至桌面应用的各个角落。然而,掌握JavaScript的语法和特性,与编写出优雅、高效、可维护的代码,是截然不同的境界。正如一位技艺精湛的工匠,深谙材料的特性,巧用工具,才能打造出经久不衰的杰作。这本书,正是为每一位渴望将JavaScript技艺推向新高度的开发者而作。 本书并非泛泛而谈的JavaScript教程,它深入挖掘了JavaScript语言的本质,聚焦于那些能够显著提升代码质量、优化开发效率、增强程序健壮性的“关键艺术”。我们不在此罗列语言的冰山一角,而是专注于那些在实际项目开发中,往往被忽视却又至关重要的细微之处。通过一系列精炼的实践指南和深入的原理剖析,本书旨在引导读者超越“能用”的层面,迈向“精妙”的境界。 为何要追求“有效”的JavaScript? 在快速迭代的开发环境中,代码的质量直接关系到项目的生死存亡。冗余的代码、难以理解的逻辑、隐藏的性能瓶颈、易于引发的bug,这些都可能成为项目延期、维护成本飙升的罪魁祸首。有效的JavaScript编程,意味着我们能够: 提升代码的可读性与可维护性: 清晰的代码如同一面镜子,能够清晰地反映出开发者的意图,降低了团队协作的沟通成本,使得bug的定位和修复更加高效。 优化程序性能: 即使是最简单的JavaScript代码,也可能因为不当的设计而导致性能下降,尤其是在处理大规模数据或复杂交互时,性能问题会变得尤为突出。 增强代码的健壮性: 编写能够优雅处理各种异常情况的代码,能够最大程度地减少程序崩溃的风险,提升用户体验。 促进代码的复用与扩展: 遵循设计原则编写的代码,更容易被重用,也为未来的功能扩展奠定了坚实的基础。 培养更深层次的语言理解: 通过理解代码背后的原理,能够更自信地驾驭JavaScript的强大功能,并为学习新的语言特性或框架打下坚实基础。 本书的核心理念与内容展望: 本书将围绕“精益求精”的核心理念,从多个维度深入探讨JavaScript的有效实践。我们将避开那些已成为共识的基础知识,转而关注那些能真正带来质变的“进阶”和“精妙”之处。 一、 语言特性的深度挖掘与妙用 JavaScript的语言特性丰富而强大,但其某些深层的特性往往容易被误解或滥用。本书将带领你重新审视这些核心特性,并探索其更高级、更精妙的应用方式。 原型链与继承的理解与实践: 摆脱对传统面向对象继承的刻板印象,深入理解JavaScript原型链的工作机制,并学会利用原型链实现更灵活、更高效的继承模式,避免“类继承”的陷阱。 闭包的真正力量: 闭包不仅仅是函数作用域的延伸,它在数据封装、模块化、状态管理等方面拥有不可替代的作用。我们将探讨如何巧妙地运用闭包来构建更加健壮和可控的代码。 `this`关键字的纠缠与解脱: `this`关键字是JavaScript中最具迷惑性的概念之一。本书将通过清晰的原理分析和丰富的实例,帮助你彻底理解`this`在不同上下文中的绑定规则,让你不再为`this`而烦恼。 异步编程的精妙艺术: 从回调函数到Promise,再到async/await,JavaScript的异步编程模型一直在演进。我们将深入剖析各种异步模式的优缺点,并提供如何在实际项目中选择和运用最适合的异步解决方案,以避免“回调地狱”和管理复杂的异步流程。 二、 编码风格与设计模式的实践智慧 良好的编码风格和合理的设计模式是构建高质量代码的基石。本书将聚焦于那些经过实践检验的、能够显著提升代码质量的编码实践和设计模式。 模块化与代码组织: 如何有效地组织和管理大型JavaScript项目?我们将探讨不同的模块化方案(如CommonJS、ES Modules),以及如何通过清晰的模块划分来提高代码的可读性、可测试性和可维护性。 函数式编程的优雅之道: 函数式编程范式在JavaScript中展现出独特的魅力。我们将介绍函数式编程的核心概念,如纯函数、不可变性、高阶函数等,并展示如何将这些概念融入日常编码中,编写出更简洁、更易于推理的代码。 常见JavaScript设计模式的应用: 并非所有设计模式都适用于JavaScript。本书将重点介绍那些在JavaScript开发中尤为实用且能够解决实际问题的设计模式,并提供如何灵活运用这些模式来优化代码结构和解决复杂问题的指导。 错误处理与防御性编程: 如何编写能够应对各种异常情况的代码?我们将探讨有效的错误处理策略,以及如何通过防御性编程来减少潜在的bug,提升程序的稳定性。 三、 性能优化与内存管理的精细考量 性能是衡量代码质量的重要指标。即使是微小的性能优化,在大型应用中也能带来显著的提升。 JavaScript引擎的工作原理浅析: 了解JavaScript引擎(如V8)如何执行代码,能够帮助我们写出更符合引擎优化习惯的代码,从而提升性能。 DOM操作的性能陷阱与优化: DOM操作是前端性能的常见瓶颈。我们将深入分析DOM操作的底层机制,并提供一系列优化技巧,以最小化DOM操作对性能的影响。 事件处理与委托的高效之道: 如何高效地管理事件监听器,避免内存泄漏?我们将探讨事件委托的原理和最佳实践。 内存泄漏的识别与预防: 内存泄漏是JavaScript开发中一个隐蔽的敌人。本书将指导你如何识别常见的内存泄漏模式,并提供预防措施。 四、 工具与测试的现代实践 现代JavaScript开发离不开强大的工具链和完善的测试体系。 代码质量工具的应用: Linting工具(如ESLint)和代码格式化工具(如Prettier)能够帮助我们强制执行统一的编码风格,提前发现潜在的错误。 单元测试与集成测试的重要性: 测试是保证代码质量的最后一道防线。我们将强调测试的重要性,并指导如何编写有效的单元测试和集成测试。 调试技巧与工具的使用: 掌握有效的调试技巧和浏览器开发者工具的使用,能够显著提升我们定位和解决问题的效率。 谁将从本书中受益? 有一定JavaScript基础,但希望提升代码质量和开发效率的开发者。 希望深入理解JavaScript语言本质,从而写出更健壮、更优雅代码的前端工程师、后端工程师(Node.js)。 正在经历项目维护困难,或希望优化现有代码库的开发团队。 对JavaScript的进阶特性和最佳实践充满好奇的开发者。 结语: 《代码炼金术:精益求精的JavaScript编程之道》不仅仅是一本书,它更是一种态度,一种对卓越代码的不懈追求。它将带领你走进JavaScript的深层世界,解锁那些被隐藏的强大力量,让你成为一名真正意义上的“JavaScript大师”。翻开这本书,让我们一起踏上这段精益求精的编程之旅,用更智慧、更高效的方式,铸造出经得起时间考验的JavaScript代码。