企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] 在我们第一次开始写程序的时候,都是以 Hello World 开始的。或者: ~~~ printf("hello,world"); ~~~ 又或许: ~~~ alert('hello,world'); ~~~ 过去的十几年里,试过用二十几种不同的语言,每个都是以 hello,world 作为开头。在一些特定的软件,如 Nginx,则是 **It Works**。 这是一个很长的故事,这个程序最早出现于1972年,由贝尔实验室成员布莱恩·柯林汉撰写的内部技术文件《A Tutorial Introduction to the Language B》之中。不久,同作者于1974年所撰写的《Programming in C: A Tutorial》,也延用这个范例;而以本文件扩编改写的《C语言程序设计》也保留了这个范例程式。工作时,我们也会使用类似于 hello,world 的 boilerplate 来完成基本的项目创建。 同时需要注意的一点是,在每个大的项目开始之前我们应该去找寻好开发环境。搭建环境是一件非常重要的事,它决定了你能不能更好地工作。毕竟环境是生产率的一部分。高效的程序员和低效程序员间的十倍差距,至少有三倍是因为环境差异。 因此在这一章里,我们将讲述几件事情: 1. 使用怎样的操作系统 2. 如何去选择工具 3. 如何搭建相应操作系统上的环境 4. 如何去学习一门语言 ## 工具只是辅助 一个好的工具确实有助于编程,但是他只会给我们带来的是帮助。我们写出来的代码还是和我们的水平保持着一致的。 什么是好的工具,这个说法就有很多了,但是有时候我们往往沉迷于事物的表面。有些时候 Vim 会比 Visual Studio 强大,当你只需要修改的是一个配置文件的时候,简单且足够快捷——在我们还未用 VS 打开的时候,我们已经用 Vim 做完这个活了。 > “好的装备确实能带来一些帮助,但事实是,你的演奏水平是由你自己的手指决定的。” – 《REWORK》 ### WebStorm 还是 Sublime? 作为一个 IDE 有时候忽略的因素会过多,一开始的代码由类似于 Sublime text 之类的编辑器开始会比较合适。于是我们又开始陷入 IDE 及 Editor 之战了,无聊的时候讨论一下这些东西是有点益处的。相互了解一下各自的优点,也是不错的,偶尔可以换个环境试试。 刚开始学习的时候,我们只需要普通的工具,或者我们习惯了的工具去开始我们的工作。我们要的是把主要精力放在学习的东西上,而不是工具。刚开始学习一种新的语言的时候,我们不需要去讨论哪个是最好的开发工具,如 Java,有时候可能是 Eclipse,有时候可能是 Vim,如果我们为的只是去写一个 hello,world。在 Eclipse 上浪费太多的时间是不可取的,因为他用起来的效率可不比你在键盘上敲打来得快,当你移动你的手指去动你的鼠标的时候,我想你可以用那短短的时间完成编译,运行了。 #### 工具是为了效率 寻找工具的目的和寻找捷径是一样的,我们需要更快更有效率地完成我们的工作,换句话说,我们为了获取更多的时间用于其他的事情。而这个工具的用途是要看具体的事物的,如果我们去写一个小说、博客的时候,word 或者 web editor 会比 tex studio 来得快,不是么。我们用 TEX 来排版的时候会比我们用 WORD 排版的时候来得更快,所以这个工具是相对而论的。有时候用一个顺手的工具会好很多,但是不一定会是事半功倍的。我们应该将我们的目标专注于我们的内容,而不是我们的工具上。 我们用 Windows 自带的画图就可以完成裁剪的时候,我们就没必要运行起 GIMP 或者 Photoshop 去完成这个简单的任务。效率在某些时候的重要性,会比你选择的工具有用得多,学习的开始就是要去了解那些大众推崇的东西。 #### 了解、熟悉你的工具 Windows 的功能很强大,只是大部分人用的是只是小小一部分。而不是一小部分,即使我们天天用着,我们也没有学习到什么新的东西。和这个就如同我们的工具一样,我们天天用着他们,如果我们只用 Word 来写写东西,那么我们可以用 Abiword 来替换他。但是明显不太可能,因为强大的工具对于我们来说有些更大的吸引力。 如果你负担得起你手上的工具的话,那么就尽可能去了解他能干什么。即使他是一些无关仅要的功能,比如 Emacs 的煮咖啡。有一本手册是最好不过的,手册在手边可以即时查阅,不过出于环保的情况下,就不是这样子的。手册没有办法即时同你的软件一样更新,电子版的更新会比你手上用的那个手册更新得更快。 Linux 下面的命令有一大堆,只是我们常用的只有一小部分——20%的命令能够完成80%的工作。如同 CISC 和 RISC 一样,我们所常用的指令会让我们忘却那些不常用的指令。而那些是最实用的,如同我们日常工作中使用的 Linux 一样,记忆过多的不实用的东西,不比把他们记在笔记上实在。我们只需要了解有那些功能,如何去用他。 ### 语言也是一种工具 越来越多的框架和语言出现、更新得越来越快。特别是这样一个高速发展的产业,每天都在涌现新的名词。如同我们选择语言一样,选择合适的有时候会比选得顺手的来得重要。然而,这个可以不断地被推翻。 当我们熟悉用 Python、Ruby、PHP 等去构建一个网站的时候,JavaScript 用来做网站后台,这怎么可能——于是 Node.js 火了。选择工具本身是一件很有趣的事,因为有着越来越多的可能性。 过去 PHP 是主流的开发,不过现在也是,PHP 为 WEB 而生。有一天 Ruby on Rails 出现了,一切就变了,变得高效,变得更 Powerful。MVC 一直很不错,不是么?于是越来越多的框架出现了,如 Django,Laravel 等等。不同的语言有着不同的框架,JavaScript 上也有着合适的框架,如 AngularJS。不同语言的使用者们用着他们合适的工具,因为学习新的东西,对于多数的人来说就是一种新的挑战。在学面向对象语言的时候,人们很容易把程序写成过程式的。 没有合适的工具,要么创造一个,要么选择一个合适的。 #### 小结 学习 Django 的时候习惯了有一个后台,于是开始使用 Laravel 的时候,寻找 Administartor。需要编译的时候习惯用 IDE,不需要的时候用 Editor,只是因为有效率,嵌入式的时候 IDE 会有效率一点。 以前不知道 WebStorm 的时候,习惯用 DW 来格式化 HTML,Aptana 来格式化 JavaScript。 以前,习惯用 WordPress 来写博客,因为可以有移动客户端,使用电脑时就不喜欢打开浏览器去写。 等等 等 ## 提高效率的工具 在提交效率的 N 种方法里:有一个很重要的方法是使用快捷键。熟练掌握快捷键可以让我们随着自己的感觉编写程序——有时候如果我们手感不好,是不是就说明今天不适合写代码!笑~~ 由于我们可能使用不同的操作系统来完成不同的工具。下面就先说说一些通用的、不限操作的工具: ### 快速启动软件 在我还不和道有这样的工具的时候,我都是把图标放在下面的任务栏里: ![](https://box.kancloud.cn/2016-05-16_57398daedd0f7.png) Windows任务栏 直到有一天,我知道有这样的工具。这里不得不提到一本书《卓有成效的程序员》,在书中提到了很多提高效率的工具。使用快捷键是其中的一个,而还有一个是使用快速启动软件。于是,我在 Windows 上使用了 Launcy: ![](https://box.kancloud.cn/2016-05-16_57398daf09e15.png) Launchy 通过这个软件,我们可以在电脑上通过输入软件名,然后运行相关的软件。我们不再需要点击某个菜单,再从菜单里选中某个软件打开。 ### IDE 尽管在上一篇中,我们说过 IDE 和编辑器没有什么好争论的。但是如果是从头开始搭建环境的话,IDE 是最好的——编辑器还需要安装相应的插件。所以,这也就是为什么面试的时候会用编辑器的原因。 IDE 的全称是集成开发环境,顾名思义即它集成了你需要用到的一些工具。而如果是编辑器的话,你需要自己去找寻合适的工具来做这件事。不过,这也意味着使用编辑器会有更多的自由度。如果你没有足够的时间去打造自己的开发环境就使用 IDE 吧。 一般来说,他们都应该有下面的一些要素: * **shortcut(快捷键)** * **Code HighLight(代码高亮)** * **Auto Complete(自动补全)** * **Syntax Check(语法检查)** 而如果是编辑器的话,就需要自己去找寻这些相应的插件。 IDE 一般是针对特定语言才产生的,并且优化更好。而,编辑器则需要自己去搭配。这也意味着如果你需要在多个语言上工作时,并且喜欢折腾,你可以考虑使用编辑器。 ### DEBUG 工具 不得不提及的是在有些 IDE 自带了 Debug 工具,这点可能使得使用 IDE 更有优势。在简单的项目是,我们可能不需要这样的 Debug 工具。因为我们对我们的代码库比较熟悉,一个简单的问题一眼就知道是哪里的问题。而对于那些复杂的项目来说,可能就没有那么简单了。特别是当你来到一个新的大中型项目,一个简单的逻辑在实现上可能要经过一系列的函数才能处理完。 这时候我们就需要 Debug 工具——对于前端开发来说,我们可能使用 Chrome 的 Dev Tools。但是对于后端来说,我们就需要使用别的工具。如下图所示的是 Intellij Idea 的 Debug 界面: ![](https://box.kancloud.cn/2016-05-16_57398daf21a68.png) Intellij Idea Debug 在 Debug 的过程中,我们可以根据代码的执行流程一步步向下执行。这也意味着,当出现 Bug 的时候我们可以更容易找到 Bug。这就是为什么他叫 Debug 工具的原因了。 ### 终端或命令提示符 在开始写代码的时候,使用 GUI 可能是难以戒掉的一个习惯。但是当你习惯了使用终端之后,或者说使用终端的工具,你会发现这是另外一片天空。对于 GUI 应用上同样的菜单来说,在终端上也会有同样的工具——只是你觉得记住更多的命令。而且不同的工具对于同一实现可能会不同的规范,而 GUI 应用则会有一致的风格。不过,总的来说使用终端是一个很有益的习惯——从速度、便捷性。忘了提到一点,当你使用 Linux 服务器的时候,你不得不使用终端。 ![](https://box.kancloud.cn/2016-05-16_57398daf536a4.jpg) Linux 终端截图 使用终端的优点在于我们可以摆脱鼠标的操作——这可以让我们更容易集中精力于完成任务。而这也是两种不同的选择,便捷还是更快。虽是如此,但是这也意味着学习 Linux 会越来越轻松。 ![](https://box.kancloud.cn/2016-05-16_57398daf7c5db.png) Linux 与 Windows 的学习曲线 虽然这是以 Linux 和 Windows 作了两个不同的对比,但是两个系统在终端工具上的差距是很大的。Linux 自身的哲学鼓励使用命令行来完成任务,这也意味着在 Linux 上会有更多的工具可以在命令行下使用。虽然 Windows 上也可以——如使用 CygWin 来完成,但是这看上去并不是那么让人满意! ### 包管理 虽然包管理不仅仅存在于操作系统中,还存在着语言的包管理工具。在操作系统中安装软件,最方便的东西莫过于包管理了。引自 OpenSUSE 官网的说明及图片: ![](https://box.kancloud.cn/2016-05-16_57398daf9a751.png) 包管理 Linux 发行版无非就是一堆软件包 (package) 形式的应用程序加上整体地管理这些应用程序的工具。通常这些 Linux 发行版,包括 OpenSUSE,都是由成千上万不同的软件包构成的。 * 软件包: 软件包不止是一个文件,内含构成软件的所有文件,包括程序本身、共享库、开发包以及使用说明等。 * 元数据 (metadata) 包含于软件包之中,包含软件正常运行所需要的一些信息。软件包安装之后,其元数据就存储于本地的软件包数据库之中,以用于软件包检索。 * 依赖关系 (dependencies) 是软件包管理的一个重要方面。实际上每个软件包都会涉及到其他的软件包,软件包里程序的运行需要有一个可执行的环境(要求有其他的程序、库等),软件包依赖关系正是用来描述这种关系的。 我们经常会使用各式各样的包管理工具,来加速我们地日常使用。而不是 Google 某个软件,然后下载,接着安装。 ## 环境搭建 由于我近期工具在 Mac OS X 上,所以先以 Mac OS X 为例。 ### OS X **[Homebrew](http://brew.sh/)** > 包管理工具,官方称之为 The missing package manager for OS X。 **[Homebrew Cask](https://caskroom.github.io/)** > brew-cask 允许你使用命令行安装 OS X 应用。 **[iTerm2](https://www.iterm2.com/)** > iTerm2 是最常用的终端应用,是 Terminal 应用的替代品。 **[Zsh](http://www.zsh.org/)** Zsh 是一款功能强大终端(shell)软件,既可以作为一个交互式终端,也可以作为一个脚本解释器。它在兼容 Bash 的同时 (默认不兼容,除非设置成 emulate sh) 还有提供了很多改进,例如: * 更高效 * 更好的自动补全 * 更好的文件名展开(通配符展开) * 更好的数组处理 * 可定制性高 **[Oh My Zsh](http://ohmyz.sh/)** > Oh My Zsh 同时提供一套插件和工具,可以简化命令行操作。 **[Sublime Text 2](https://www.sublimetext.com/)** > 强大的文件编辑器。 **[MacDown](http://macdown.uranusjr.com/)** > MacDown 是 Markdown 编辑器。 **[CheatSheet](https://www.mediaatelier.com/CheatSheet/)** > CheatSheet 能够显示当前程序的快捷键列表,默认的快捷键是长按⌘。 **[SourceTree](https://www.sourcetreeapp.com/)** > SourceTree 是 Atlassian 公司出品的一款优秀的 Git 图形化客户端。 **[Alfred](https://www.alfredapp.com/)** > Mac 用户不用鼠标键盘的必备神器,配合大量 Workflows,习惯之后可以大大减少操作时间。 上手简单,调教成本在后期自定义 Workflows,不过有大量雷锋使用者提供的现成扩展,访问这里挑选喜欢的,并可以极其简单地根据自己的需要修改。 **[Vimium](https://vimium.github.io/)** > Vimium 是一个 Google Chrome 扩展,让你可以纯键盘操作 Chrome。 相关参考: * [Mac web developer apps](https://gist.github.com/erikreagan/3259442) * [强迫症的 Mac 设置指南](https://github.com/macdao/ocds-guide-to-setting-up-mac) ### Windows **[Chocolatey](https://chocolatey.org/)** > Chocolatey 是一个软件包管理工具,类似于 Ubuntu 下面的 apt-get,不过是运行在 Windows 环境下面。 **[Wox](http://www.getwox.com/)** > Wox 是一个高效的快速启动器工具,通过快捷键呼出,然后输入关键字来搜索程序进行快速启动,或者搜索本地硬盘的文件,打开百度、Google 进行搜索,甚至是通过一些插件的功能实现单词翻译、关闭屏幕、查询剪贴板历史、查询编程文档、查询天气等更多功能。它最大的特点是可以支持中文拼音的模糊匹配。 **[PowerShell](https://msdn.microsoft.com/en-us/powershell/mt173057.aspx)** > Windows PowerShell 是微软公司为 Windows 环境所开发的壳程序(shell)及脚本语言技术,采用的是命令行界面。这项全新的技术提供了丰富的控制与自动化的系统管理能力。 **[cmder](http://cmder.net/)** > cmder 把 conemu,msysgit 和 clink 打包在一起,让你无需配置就能使用一个真正干净的 Linux 终端!她甚至还附带了漂亮的 monokai 配色主题。 **[Total Commander](http://www.ghisler.com/)** > Total Commander 是一款应用于 Windows 平台的文件管理器 ,它包含两个并排的窗口,这种设计可以让用户方便地对不同位置的“文件或文件夹”进行操作,例如复制、移动、删除、比较等,相对 Windows 资源管理器而言方便很多,极大地提高了文件操作的效率,被广大软件爱好者亲切地简称为:TC 。 ### GNU/Linux **[Zsh](http://www.zsh.org/)** Zsh 是一款功能强大终端(shell)软件,既可以作为一个交互式终端,也可以作为一个脚本解释器。它在兼容 Bash 的同时 (默认不兼容,除非设置成 emulate sh) 还有提供了很多改进,例如: * 更高效 * 更好的自动补全 * 更好的文件名展开(通配符展开) * 更好的数组处理 * 可定制性高 **[Oh My Zsh](http://ohmyz.sh/)** > Oh My Zsh 同时提供一套插件和工具,可以简化命令行操作。 **[ReText](https://github.com/retext-project/retext)** > ReText 是一个使用 Markdown 语法和 reStructuredText (reST) 结构的文本编辑器,编辑的内容支持导出到 PDF、ODT 和 HTML 以及纯文本,支持即时预览、网页生成以及 HTML 语法高亮、全屏模式,可导出文件到 Google Docs 等。 **[Launchy](http://www.launchy.net/)** > Launchy 是一款免费开源的协助您摒弃 Windows “运行”的 Dock 式替代工具,既方便又实用,自带多款皮肤,作为美化工具也未尝不可。 环境搭建完毕!现在,就让我们来看看如何学好一门语言! ## 学好一门语言的艺术 ### 一次语言学习体验 在我们开始学习一门语言或者技术的时候,我们可能会从一门 “hello,world” 开始。 好了,现在我是 Scala 语言的初学者,接着我用搜索引擎去搜索『Scala』来看看『Scala』是什么鬼: > Scala 是一门类 Java 的编程语言,它结合了面向对象编程和函数式编程。 接着又开始看『Scala ‘hello,world’』,然后找到了这样的一个示例: ~~~ object HelloWorld { def main(args: Array[String]): Unit = { println("Hello, world!") } } ~~~ GET 到了5%的知识。 看上去这门语言相比于 Java 语言来说还行。然后我找到了一本名为『Scala 指南』的电子书,有这样的一本目录: * 表达式和值 * 函数是一等公民 * 借贷模式 * 按名称传递参数 * 定义类 * 鸭子类型 * 柯里化 * 范型 * Traits * … 看上去还行, 又 GET 到了5%的知识点。接着,依照上面的代码和搭建指南在自己的电脑上安装了 Scala 的环境: ~~~ brew install scala ~~~ Windows 用户可以用: ~~~ choco install scala ~~~ 然后开始写一个又一个的 Demo,感觉自己 GET 到了很多特别的知识点。 到了第二天忘了! ![](https://box.kancloud.cn/2016-05-16_57398dafb36a1.jpg) Bro Wrong 接着,你又重新把昨天的知识过了一遍,还是没有多大的作用。突然间,你听到别人在讨论什么是**这个世界上最好的语言**——你开始加入讨论了。 于是,你说出了 Scala 这门语言可以: * 支持高阶函数。lambda,闭包… * 支持偏函数。 match.. * mixin,依赖注入.. * 等等 虽然隔壁的 Python 小哥赢得了这次辩论,然而你发现你又回想起了 Scala 的很多特性。 ![](https://box.kancloud.cn/2016-05-16_57398dafcbbe2.jpg) 最流行的语言 你发现隔壁的 Python 小哥之所以赢得了这场辩论是因为他把 Python 语言用到了各个地方——机器学习、人工智能、硬件、Web开发、移动应用等。而你还没有用 Scala 写过一个真正的应用。 让我想想我能做什么?我有一个博客。对,我有一个博客,可以用 Scala 把我的博客重写一遍: 1. 先找一 Scala 的 Web 框架,Play 看上去很不错,就这个了。这是一个 MVC 框架,原来用的 Express 也是一个 MVC 框架。Router 写这里,Controller 类似这个,就是这样的。 2. 既然已经有 PyJS,也会有 Scala-js,前端就用这个了。 好了,博客重写了一遍了。 感觉还挺不错的,我决定向隔壁的 Java 小弟推销这门语言,以解救他于火海之中。 『让我想想我有什么杀手锏?』 『这里的知识好像还缺了一点,这个是什么?』 好了,你已经 GET 到了90%了。如下图所示: ![](https://box.kancloud.cn/2016-05-16_57398dafeb8c8.jpg) Learn 希望你能从这张图上 GET 到很多点。 ### 输出是最好的输入 上面那张图『学习金字塔』就是在说明——输出是最好的输入。 如果你不试着去写点博客、整理资料、准备分享,那么你可能并没有意识到你缺少了多少东西。虽然你已经有了很多的实践,然并卵。 因为你一直在完成功能、完成工作,你总会有意、无意地漏掉一些知识,而你也没有意识到这些知识的重要性。 ![](https://box.kancloud.cn/2016-05-16_57398db0104c2.png) Output is Input 从我有限的(500+)博客写作经验里,我发现多数时候我需要更多地参考资料才能更好也向人们展示这个过程。为了输出我们需要更多的输入,进而加速这个过程。 而如果是写书的时候则是一个更高水平的学习,你需要发现别人在他们的书中欠缺的一些知识点。并且你还要展示一些在别的书中没有,而这本书会展现这个点的知识,这意味着你需要挖掘得更深。 所以,如果下次有人问你如何学一门新语言、技术,那么答案就是写一本书。 ### 如何应用一门新的技术 对于多数人来说,写书不是一件容易的事,而应用新的技术则是一件迫在眉睫的事。 通常来说,技术出自于对现有的技术的改进。这就意味着,在掌握现有技术的情况下,我们只需要做一些小小的改动就更可以实现技术升级。 而学习一门新的技术的最好实践就是用这门技术对现有的系统行重写。 第一个系统(v1): `Spring MVC` + `Bootstrap` + `jQuery` 那么在那个合适的年代里, 我们需要单页面应用,就使用了Backbone。然后,我们就可以用 Mustache + HTML 来替换掉 JSP。 第二个系统(v2): `Spring MVC` + `Backbone` + `Mustache` 在这时我们已经实现了前后端分离了,这时候系统实现上变成了这样。 第二个系统(v2.2): `RESTful Services` + `Backbone` + `Mustache` 或者 第二个系统(v2.2): `RESTful Services` + `AngularJS 1.x` Spring 只是一个 RESTful 服务,我们还需要一些问题,比如 DOM 的渲染速度太慢了。 第三个系统(v3): `RESTful Services` + `React` 系统就是这样一步步演进过来的。 尽管在最后系统的架构已经不是当初的架构,而系统本身的业务逻辑变化并没有发生太大的变化。 特别是对于如博客这一类的系统来说,他的一些技术实现已经趋于稳定,而且是你经常使用的东西。所以,下次试试用新的技术的时候,可以先从对你的博客的重写开始。 ## Web 编程基础 ### 从浏览器到服务器 如果你的操作系统带有 cURL 这个软件(在 GNU/Linux、Mac OS 都自带这个工具,Windows 用户可以从[http://curl.haxx.se/download.html](http://curl.haxx.se/download.html)下载到),那么我们可以直接用下面的命令来看这看这个过程(-v 参数可以显示一次 http 通信的整个过程): ~~~ curl -v https://www.phodal.com ~~~ 我们就会看到下面的响应过程: ~~~ * Rebuilt URL to: https://www.phodal.com/ * Trying 54.69.23.11... * Connected to www.phodal.com (54.69.23.11) port 443 (#0) * TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 * Server certificate: www.phodal.com * Server certificate: COMODO RSA Domain Validation Secure Server CA * Server certificate: COMODO RSA Certification Authority * Server certificate: AddTrust External CA Root > GET / HTTP/1.1 > Host: www.phodal.com > User-Agent: curl/7.43.0 > Accept: */* > < HTTP/1.1 403 Forbidden < Server: phodal/0.19.4 < Date: Tue, 13 Oct 2015 05:32:13 GMT < Content-Type: text/html; charset=utf-8 < Content-Length: 170 < Connection: keep-alive < <html> <head><title>403 Forbidden</title></head> <body bgcolor="white"> <center><h1>403 Forbidden</h1></center> <hr><center>phodal/0.19.4</center> </body> </html> * Connection #0 to host www.phodal.com left intact ~~~ 我们尝试用 cURL 去访问我的网站,会根据访问的域名找出其 IP,通常这个映射关系是来源于 ISP 缓存 DNS(英语:Domain Name System)服务器[^DNSServer]。 以“*”开始的前8行是一些连接相关的信息,称为**响应首部**。我们向域名[https://www.phodal.com/](https://www.phodal.com/)发出了请求,接着 DNS服务器告诉了我们网站服务器的 IP,即54.69.23.11。出于安全考虑,在这里我们的示例,我们是以 HTTPS 协议为例,所以在这里连接的端口是 443。因为使用的是 HTTPS 协议,所以在这里会试图去获取服务器证书,接着获取到了域名相关的证书信息。 随后以“>”开始的内容,便是向Web服务器发送请求。Host 即是我们要访问的主机的域名,GET / 则代表着我们要访问的是根目录,如果我们要访问 [https://www.phodal.com/about/](https://www.phodal.com/about/)页面在这里,便是 GET 资源文件 /about。紧随其后的是 HTTP 的版本号(HTTP/1.1)。User-Agent 通常指向的是使用者行为的软件,通常会加上硬件平台、系统软件、应用软件和用户个人偏好等等的一些信息。Accept 则指的是告知服务器发送何种媒体类型。 这个过程,大致如下图所示: ![](https://box.kancloud.cn/2016-05-16_57398db0264d2.jpg) DNS 到服务器的过程 在图中,我们会发现解析 DNS 的时候,我们需要先本地 DNS 服务器查询。如果没有的话,再向根域名服务器查询——这个域名由哪个服务器来解析。直至最后拿到真正的服务器IP才能获取页面。 当我们拿到相应的 HTML、JS、CSS 后,我们就开始渲染这个页面了。 #### HTTP 协议 说到这里,我们不得不说说 HTTP 协议——超文本传输协议。它也是一个基于文本的传输协议,这就是为什么你在上面看到的都是文本的传输过程。 ### 从 HTML 到页面显示 而浏览器接收到文本的时候,就要开始着手将 HTML 变成屏幕。下图是 Chrome 渲染页面的一个时间线: ![](https://box.kancloud.cn/2016-05-16_57398db04dbbd.jpg) Chrome 渲染的 Timeline 及其整个渲染过程如下图所示: ![](https://box.kancloud.cn/2016-05-16_57398db06a0f1.png) Render HTML (PS: 需要注意的是这里用的是 WebKit 内核的渲染过程,即 Chrome 和 Safari 等浏览器所使用的内核。) 从上面的两图可以看出来第一步都 Parser HTML,而 Paser HTML 实质上就是将其将解析为 DOM Tree。与此同时,CSS 解析器会解析 CSS 会产生 CSS 规则树。 随后会根据生成的 DOM 树和 CSS 规则树来构建 Render Tree,接着生成 Render Tree的布局,最后就是绘制出 Render Tree。 详细的内容还得参见相关的书籍~~。 相关内容: * 《[How browsers work](http://taligarsiel.com/Projects/howbrowserswork1.htm)》 ## HTML 让我们先从身边的语言下手,也就是现在无处不在的 HTML+Javascript+CSS。 之所以从 HTML 开始,是因为我们不需要配置一个复杂的开发环境,也许你还不知道开发环境是什么东西,不过这也没关系,毕竟这些知识需要慢慢的接触才能有所了解,尤其是对于普通的业余爱好者来说,当然,对于专业选手而言自然不是问题。HTML 是 Web 的核心语言,也算是比较基础的语言。 ### hello,world hello,world 是一个传统,所以在这里也遵循这个有趣的传统,我们所要做的事情其实很简单,虽然也有一点点 hack 的感觉。——让我们先来新建一个文件并命名为“helloworld.html”。 (PS:大部分人应该都是在 Windows 环境下工作的,所以你需要新建一个文本,然后重命名,或者你需要一个编辑器,在这里我们推荐用 **Sublime Text** 。破解不破解,注册不注册都不会对你的使用有太多的影响。) 1. 新建文件 2. 输入 ~~~ hello,world ~~~ 3. 保存为->“helloworld.html”, 4. 双击打开这个文件。 正常情况下都应该是用你的默认浏览器打开。只要是一个正常工作的现代浏览器,都应该可以看到上面显示的是“Hello,world”。 这才是最短的 hello,world 程序,但是呢?在 Ruby 中会是这样子的 ~~~ 2.0.0-p353 :001 > p "hello,world" "hello,world" => "hello,world" 2.0.0-p353 :002 > ~~~ 等等,如果你了解过 HTML 的话,会觉得这一点都不符合语法规则,但是他工作了,没有什么比安装完 Nginx 后看到 It works! 更让人激动了。 遗憾的是,它可能无法在所有的浏览器上工作,所以我们需要去调试其中的 bug。 #### 调试 hello,world 我们会发现我们的代码在浏览器中变成了下面的代码,如果你和我一样用的是 Chrome,那么你可以右键浏览器中的空白区域,点击审查元素,就会看到下面的代码。 ~~~ <html> <head></head> <body>hello,world</body> </html> ~~~ 这个才是真正能在大部分浏览器上工作的代码,所以复制它到编辑器里吧。 #### 说说 hello,world 我很不喜欢其中的,但是我也没有找到别的方法来代替它们,所以这是一个设计得当的语言。甚至大部分人都说这算不上是一门真正的语言,不过 HTML 的原义是 > 超文本标记语言 所以我们可以发现其中的关键词是标记——markup,也就是说 html 是一个 markup,head 是一个 markup,body 也是一个 markup。 然而,我们真正工作的代码是在 body 里面,至于为什么是在这里面,这个问题就太复杂了。打个比方来说: 1. 我们所使用的汉语是人类用智慧创造的,我们所正在学的这门语言同样也是人类创造的。 2. 我们在自己的语言里遵循着 **桌子是桌子,凳子是凳子** 的原则,很少有人会问为什么。 ### 中文? 所以我们也可以把计算机语言与现实世界里用于交流沟通的语言划上一个等号。而我们所要学习的语言,并不是我们最熟悉的汉语语言,所以我们便觉得这些很复杂,但是如果我们试着用汉语替换掉上面的代码的话 ~~~ <语言> <头><结束头> <身体>你好,世界<结束身体> <结束语言> ~~~ 这看上去很奇怪,只是因为是直译过去的原因,也许你会觉得这样会好理解一点,但是输入上可就一点儿也不方便,因为这键盘本身就不适合我们去输入汉字,同时也意味着可能你输入的会有问题。 让我们把上面的代码代替掉原来的代码然后保存,打开浏览器会看到下面的结果 ~~~ <语言> <头><结束头> <身体>你好,世界<结束身体> <结束语言> ~~~ 更不幸的结果可能是 ~~~ <璇█> <澶�><缁撴潫澶�> <韬綋>浣犲ソ锛屼笘鐣�<缁撴潫韬綋> <缁撴潫璇█> ~~~ 这是一个编码问题,对中文支持不友好。 我们把上面的代码改为和标记语言一样的结构 ~~~ <语言> <头></头> <身体>你好,世界</身体> <结束语言> ~~~ 于是我们看到的结果便是 ~~~ <语言> <头> <身体>你好,世界 ~~~ 被 Chrome 浏览器解析成什么样了? ~~~ <html><head></head><body><语言> <头><!--头--> <身体>你好,世界<!--身体--> <!--语言--> </body></html> ~~~ 以`<!--`开头,`-->`结尾的是注释,写给人看的代码,不是给机器看的,所以机器不会去理解这些代码。 但是当我们把代码改成 ~~~ <whatwewanttosay>你好世界</whatwewanttosay> ~~~ 浏览器上面显示的内容就变成了 ~~~ 你好世界 ~~~ 或许你会觉得很神奇,但是这一点儿也不神奇,虽然我们的中文语法也遵循着标记语言的标准,但是我们的浏览器不支持中文标记。 结论: 1. 浏览器对中文支持不友好。 2. 浏览器对英文支持友好。 刚开始的时候不要对中文编程有太多的想法,这是很不现实的: 1. 现有的系统都是基于英语语言环境构建的,对中文支持不是很友好。 2. 中文输入的速度在某种程度上来说没有英语快。 我们离开话题已经很远了,但是这里说的都是针对于那些不满于英语的人来说的,只有当我们可以从头构建一个中文系统的时候才是可行的,而这些就要将 CPU、软件、硬件都包含在内,甚至我们还需要考虑重新设计 CPU 的结构,在某种程度上来说会有些不现实。或许,需要一代又一代人的努力。忘记那些吧,师夷之长技以制夷。 ### 其他 HTML 标记 添加一个标题, ~~~ <html> <head> <title>标题</title> </head> <body>hello,world</body> </html> ~~~ 我们便可以在浏览器的最上方看到“标题”二字,就像我们常用的淘宝网,也包含了上面的东西,只是还包括了更多的东西,所以你也可以看懂那些我们可以看到的淘宝的标题。 ~~~ <html> <head> <title>标题</title> </head> <body> hello,world <h1>大标题</h1> <h2>次标题</h2> <h3>...</h3> <ul> <li>列表1</li> <li>列表2</li> </ul> </body> </html> ~~~ 更多的东西可以在一些书籍上看到,这边所要说的只是一次简单的语言入门,其他的东西都和这些类似。 ### 小结 #### 美妙之处 我们简单地上手了一门不算是语言的语言,浏览器简化了这其中的大部分过程,虽然没有 C 和其他语言来得有专业感,但是我们试着去开始写代码了。我们可能在未来的某一篇中可能会看到类似的语言,诸如 Python,我们所要做的就是 ~~~ $ python file.py =>hello,world ~~~ 然后在终端上返回结果。只是因为在我看来学会 HTML 是有意义的,简单的上手,然后再慢慢地深入,如果一开始我们就去理解指针,开始去理解类。我们甚至还知道程序是怎么编译运行的时候,在这个过程中又发生了什么。虽然现在我们也没能理解这其中发生了什么,但是至少展示了 1. 中文编程语言在当前意义不大,不现实,效率不高兼容性差 2. 语言的语法是固定的。(ps:虽然我们也可以进行扩充,我们将会在后来支持上述的中文标记。) 3. 已经开始写代码,而不是还在配置开发环境。 4. 随身的工具才是最好的,最常用的 code 也才是实在的。 #### 更多 我们还没有试着去解决“某商店里的糖一颗5块钱,小明买了3颗糖,小明一共花了多少钱”的问题。也就是说我们学会的是一个还不能解决实际问题的语言,于是我们还需要学点东西,比如 JavaScript, CSS。我们可以将 JavaScript 理解为解决问题的语言,HTML 则是前端显示,CSS 是配置文件,这样的话,我们会在那之后学会成为一个近乎专业的程序员。我们刚刚学习了一下怎么在前端显示那些代码的行为,于是我们还需要 JavaScript。 ## CSS 如果说 HTML 是建筑的框架,CSS 就是房子的装修。那么 JavaScript 呢,我听到的最有趣的说法是小三——还是先让我们回到代码上来吧。 下面就是我们之前说到的代码,CSS 将 Red 三个字母变成了红色。 ~~~ <!DOCTYPE html> <html> <head> </head> <body> <p id="para" style="color:red">Red</p> </body> <script type="text/javascript" src="app.js"></script> </html> ~~~ 只是, ~~~ var para=document.getElementById("para"); para.style.color="blue"; ~~~ 将字体变成了蓝色,CSS+HTML 让页面有序的工作着,但是 JavaScript 却打乱了这些秩序,有着唯恐世界不乱的精彩,也难怪被冠以小三之名了——或许终于可以理解,为什么以前人们对于 JavaScript 没有好感了——不过这里要讲的是正室,也就是 CSS,这时还没有 JavaScript。 ![](https://box.kancloud.cn/2016-05-16_57398db0805fe.png) Red Fonts ### 简介 这不是一篇专业讲述 CSS 的书籍,所以我不会去说 CSS 是怎么来的,有些东西我们既然可以很容易从其他地方知道,也就不需要花太多时间去重复。诸如重构等这些的目的之一也在于去除重复的代码,不过有些重复是不可少的,也是有必要的,而通常这些东西可能是由其他地方复制过来的。 到目前为止我们没有依赖于任何特殊的硬件或者是软件,对于我们来说我们最基本的需求就是一台电脑,或者可以是你的平板电脑,当然也可以是你的智能手机,因为他们都有个浏览器,而这些都是能用的,对于我们的 CSS 来说也不会有例外的。 CSS(Cascading Style Sheets),到今天我也没有记得他的全称,CSS 还有一个中文名字是层叠式样式表,事实上翻译成什么可能并不是我们关心的内容,我们需要关心的是他能做些什么。作为三剑客之一,它的主要目的在于可以让我们方便灵活地去控制 Web 页面的外观表现。我们可以用它做出像淘宝一样复杂的界面,也可以像我们的书本一样简单,不过如果要和我们书本一样简单的话,可能不需要用到 CSS。HTML 一开始就是依照报纸的格式而设计的,我们还可以继续用上面说到的编辑器,又或者是其他的。如果你喜欢 DreamWeaver 那也不错,不过一开始使用 IDE 可无助于我们写出良好的代码。 忘说了,CSS 也是有版本的,和 Windows,Linux 内核等等一样,但是更新可能没有那么频繁,HTML 也是有版本的,JavaScript 也是有版本的,复杂的东西不是当前考虑的内容。 #### 代码结构 对于我们的上面的 Red 示例来说,如果没有一个好的结构,那么以后可能就是这样子。 ~~~ <!DOCTYPE html> <html> <head> </head> <body> <p style="font-size: 22px;color: #f00;text-align: center;padding-left: 20px;">如果没有一个好的结构</p> <p style="font-size: 44px;color: #3ed;text-indent: 2em;padding-left: 2em;">那么以后可能就是这样子。。。。</p> </body> </html> ~~~ 虽然我们看到的还是一样的: ![](https://box.kancloud.cn/2016-05-16_57398db090c9d.png) No Style 于是我们就按各种书上的建议重新写了上面的代码 ~~~ <!DOCTYPE html> <html> <head> <title>CSS example</title> <style type="text/css"> .para{ font-size: 22px; color: #f00; text-align: center; padding-left: 20px; } .para2{ font-size: 44px; color: #3ed; text-indent: 2em; padding-left: 2em; } </style> </head> <body> <p class="para">如果没有一个好的结构</p> <p class="para2">那么以后可能就是这样子。。。。</p> </body> </html> ~~~ 总算比上面好看也好理解多了,这只是临时的用法,当文件太大的时候,正式一点的写法应该如下所示: ~~~ <!DOCTYPE html> <html> <head> <title>CSS example</title> <style type="text/css" href="style.css"></style> </head> <body> <p class="para">如果没有一个好的结构</p> <p class="para2">那么以后可能就是这样子。。。。</p> </body> </html> ~~~ 我们需要 ~~~ <!DOCTYPE html> <html> <head> <title>CSS example</title> <link href="./style.css" rel="stylesheet" type="text/css" /> </head> <body> <p class="para">如果没有一个好的结构</p> <p class="para2">那么以后可能就是这样子。。。。</p> </body> </html> ~~~ 然后我们有一个像 app.js 一样的 style.css 放在同目录下,而他的内容便是 ~~~ .para{ font-size: 22px; color: #f00; text-align: center; padding-left: 20px; } .para2{ font-size: 44px; color: #3ed; text-indent: 2em; padding-left: 2em; } ~~~ 这代码和 JS 的代码有如此多的相似 ~~~ var para={ font_size: '22px', color: '#f00', text_align: 'center', padding_left: '20px', } ~~~ 而22px、20px以及#f00都是数值,因此: ~~~ var para={ font_size: 22px, color: #f00, text_align: center, padding_left: 20px, } ~~~ 目测差距已经尽可能的小了,至于这些话题会在以后讨论到,如果要让我们的编译器更正确的工作,那么我们就需要非常多这样的符号,除非你乐意去理解: ~~~ (dotimes (i 4) (print i)) ~~~ 总的来说我们减少了符号的使用,但是用 lisp 便带入了更多的括号,不过这是一种简洁的表达方式,也许我们可以在其他语言中看到。 ~~~ \d{2}/[A-Z][a-z][a-z]/\d{4} ~~~ 上面的代码,是为了从一堆数据中找出“某日/某月/某年”。如果一开始不理解那是正则表达式,就会觉得那个很复杂。 这门语言可能是为设计师而设计的,但是设计师大部分还是不懂编程的,不过相对来说这门语言还是比其他语言简单易懂一些。 ### 样式与目标 如下所示,就是我们的样式 ~~~ .para{ font-size: 22px; color: #f00; text-align: center; padding-left: 20px; } ~~~ 我们的目标就是 > 如果没有一个好的结构 所以样式和目标在这里牵手了,问题是他们是如何在一起的呢?下面就是 CSS 与 HTML 沟通的重点所在了: ### 选择器 我们用到的选择器叫做类选择器,也就是 class,或者说应该称之为 class 选择器更合适。与类选择器最常一起出现的是 ID 选择器,不过这个适用于比较高级的场合,诸如用 JS 控制 DOM 的时候就需要用到 ID 选择器。而基本的选择器就是如下面的例子: ~~~ p.para{ color: #f0f; } ~~~ 将代码添加到 style.css 的最下面会发现“如果没有一个好的结构”变成了粉红色,当然我们还会有这样的写法 ~~~ p>.para{ color: #f0f; } ~~~ 为了产生上面的特殊的样式,虽然不好看,但是我们终于理解什么叫层叠样式了,下面的代码的权重比上面高,也因此有更高的优先规则。 而通常我们可以通过一个 ~~~ p{ text-align: left; } ~~~ 这样的元素选择器来给予所有的 p 元素一个左对齐。 还有复杂一点的复合型选择器,下面的是 HTML 文件 ~~~ <!DOCTYPE html> <html> <head> <title>CSS example</title> <link href="./style.css" rel="stylesheet" type="text/css" /> </head> <body> <p class="para">如果没有一个好的结构</p> <div id="content"> <p class="para2">那么以后可能就是这样子。。。。</p> </div> </body> </html> ~~~ 还有 CSS 文件 ~~~ .para{ font-size: 22px; color: #f00; text-align: center; padding-left: 20px; } .para2{ font-size: 44px; color: #3ed; text-indent: 2em; padding-left: 2em; } p.para{ color: #f0f; } div#content p { font-size: 22px; } ~~~ ### 更有趣的 CSS 一个包含了 para2 以及 para_bg 的例子 ~~~ <div id="content"> <p class="para2 para_bg">那么以后可能就是这样子。。。。</p> </div> ~~~ 我们只是添加了一个黑色的背景 ~~~ .para_bg{ background-color: #000; } ~~~ 重新改变后的网页变得比原来有趣了很多,所谓的继承与合并就是上面的例子。 我们还可以用 CSS3 做出更多有趣的效果,而这些并不在我们的讨论范围里面,因为我们讨论的是 be a geek。 或许我们写的代码都是那么的简单,从 HTML 到 JavaScript,还有现在的 CSS,只是总有一些核心的东西,而不是去考虑那些基础语法,基础的东西我们可以在实践的过程中一一发现。但是我们可能发现不了,或者在平时的使用中考虑不到一些有趣的用法或者说特殊的用法,这时候可以通过观察一些精致设计的代码中学习到。复杂的东西可以变得很简单,简单的东西也可以变得很复杂。 ## JavaScript JavaScript 现在已经无处不在了,也许你正打开的某个网站,他便可能是 node.js+json+javascript+mustache.js 完成的,虽然你还没理解上面那些是什么,也正是因为你不理解才需要去学习更多的东西。但是你只要知道 JavaScript 已经无处不在了,它可能就在你手机上的某个 app 里,就在你浏览的网页里,就运行在你 IDE 中的某个进程里。 ### hello,world 这里我们还需要有一个 helloworld.html,JavaScript 是专为网页交互而设计的脚本语言,所以我们一点点来开始这部分的旅途,先写一个符合标准的 helloworld.html ~~~ <!DOCTYPE html> <html> <head></head> <body></body> </html> ~~~ 然后开始融入我们的 JavaScript,向 HTML 中插入JavaScript 的方法,就需要用到 HTML 中的 标签,我们先用页面嵌入的方法来写 helloworld。 ~~~ <!DOCTYPE html> <html> <head> <script> document.write('hello,world'); </script> </head> <body></body> </html> ~~~ 按照标准的写法,我们还需要声明这个脚本的类型 ~~~ <!DOCTYPE html> <html> <head> <script type="text/javascript"> document.write('hello,world'); </script> </head> <body></body> </html> ~~~ 没有显示 hello,world ?试试下面的代码 ~~~ <!DOCTYPE html> <html> <head> <script type="text/javascript"> document.write('hello,world'); </script> </head> <body> <noscript> disable Javascript </noscript> </body> </html> ~~~ ### JavaScriptFul 我们需要让我们的代码看上去更像是 js,同时是以 js 结尾。就像 C 语言的源码是以 C 结尾的,我们也同样需要让我们的代码看上去更正式一点。于是我们需要在 helloworld.html 的同一文件夹下创建一个 app.js 文件,在里面写着 ~~~ document.write('hello,world'); ~~~ 同时我们的 helloworld.html 还需要告诉我们的浏览器 js 代码在哪里 ~~~ <!DOCTYPE html> <html> <head> <script type="text/javascript" src="app.js"></script> </head> <body> <noscript> disable Javascript </noscript> </body> </html> ~~~ #### 从数学出发 让我们回到第一章讲述的小明的问题,**从实际问题下手编程,更容易学会编程**。小学时代的数学题最喜欢这样子了——某商店里的糖一个5块钱,小明买了3个糖,小明一共花了多少钱。在编程方面,也许我们还算是小学生。最直接的方法就是直接计算 3x5=? ~~~ document.write(3*5); ~~~ document.write 实际也我们可以理解为输出,也就是往页面里写入 3*5 的结果,在有双引号的情况下会输出字符串。我们便会在浏览器上看到15,这便是一个好的开始,也是一个糟糕的开始。 #### 设计和编程 对于实际问题,如果我们只是止于所要得到的结果,很多年之后,我们就成为了 code monkey。对这个问题进行再一次设计,所谓的设计有些时候会把简单的问题复杂化,有些时候会使以后的扩展更加简单。这一天因为这家商店的糖价格太高了,于是店长将价格降为了4块钱。 ~~~ document.write(3*4); ~~~ 于是我们又得到了我们的结果,但是下次我们看到这些代码的时候没有分清楚哪个是糖的数量,哪个是价格,于是我们重新设计了程序 ~~~ tang=4; num=3; document.write(tang*num); ~~~ 这才能叫得上是程序设计,或许你注意到了“;”这个符号的存在,我想说的是这是另外一个标准,我们不得不去遵守,也不得不去 fuck。 #### 函数 记得刚开始学三角函数的时候,我们会写 ~~~ sin 30=0.5 ~~~ 而我们的函数也是类似于此,换句话说,因为很多搞计算机的先驱都学好了数学,都把数学世界的规律带到了计算机世界,所以我们的函数也是类似于此,让我们从一个简单的开始。 ~~~ function hello(){ return document.write("hello,world"); } hello(); ~~~ 当我第一次看到函数的时候,有些小激动终于出现了。我们写了一个叫 hello 的函数,它返回了往页面中写入 hello,world 的方法,然后我们调用了 hello 这个函数,于是页面上有了 hello,world。 ~~~ function sin(degree){ return document.write(Math.sin(degree)); } sin(30); ~~~ 在这里 degree 就称之为变量。 于是输出了 -0.9880316240928602,而不是 0.5,因为这里用的是弧度制,而不是角度制。 ~~~ sin(30) ~~~ 的输出结果有点类似于sin 30。写括号的目的在于,括号是为了方便解析,这个在不同的语言中可能是不一样的,比如在 Ruby 中我们可以直接用类似于数学中的表达: ~~~ 2.0.0-p353 :004 > Math.sin 30 => -0.9880316240928618 2.0.0-p353 :005 > ~~~ 我们可以在函数中传入多个变量,于是我们再回到小明的问题,就会这样去编写代码。 ~~~ function calc(tang,num){ result=tang*num; document.write(result); } calc(3,4); ~~~ 但是从某种程度上来说,我们的 calc 做了计算的事又做了输出的事,总的来说设计上有些不好。 #### 重新设计 我们将输出的工作移到函数的外面, ~~~ function calc(tang,num){ return tang*num; } document.write(calc(3,4)); ~~~ 接着我们用一种更有意思的方法来写这个问题的解决方案 ~~~ function calc(tang,num){ return tang*num; } function printResult(tang,num){ document.write(calc(tang,num)); } printResult(3, 4) ~~~ 看上去更专业了一点点,如果我们只需要计算的时候我们只需要调用 calc,如果我们需要输出的时候我们就调用 printResult 的方法。 #### object 和函数 我们还没有说清楚之前我们遇到过的 document.write 以及 Math.sin 的语法为什么看上去很奇怪,所以让我们看看他们到底是什么,修改 app.js 为以下内容 ~~~ document.write(typeof document); document.write(typeof Math); ~~~ typeof document 会返回 document 的数据类型,就会发现输出的结果是 ~~~ object object ~~~ 所以我们需要去弄清楚什么是 object。对象的定义是 > 无序属性的集合,其属性可以包含基本值、对象或者函数。 创建一个 object,然后观察这便是我们接下来要做的 ~~~ store={}; store.tang=4; store.num=3; document.write(store.tang*store.num); ~~~ 我们就有了和 document.write 一样的用法,这也是对象的美妙之处,只是这里的对象只是包含着基本值,因为 ~~~ typeof story.tang="number" ~~~ 一个包含对象的对象应该是这样子的。 ~~~ store={}; store.tang=4; store.num=3; document.writeln(store.tang*store.num); var wall=new Object(); wall.store=store; document.write(typeof wall.store); ~~~ 而我们用到的 document.write 和上面用到的 document.writeln 都是属于这个无序属性集合中的函数。 下面代码说的就是这个无序属性集合中的函数。 ~~~ var IO=new Object(); function print(result){ document.write(result); }; IO.print=print; IO.print("a obejct with function"); IO.print(typeof IO.print); ~~~ 我们定义了一个叫 IO 的对象,声明对象可以用 ~~~ var store={}; ~~~ 又或者是 ~~~ var store=new Object{}; ~~~ 两者是等价的,但是用后者的可读性会更好一点,我们定义了一个叫print的函数,他的作用也就是 document.write,IO 中的print 函数是等价于 print() 函数,这也就是对象和函数之间的一些区别,对象可以包含函数,对象是无序属性的集合,其属性可以包含基本值、对象或者函数。 复杂一点的对象应该是下面这样的一种情况。 ~~~ var Person={name:"phodal",weight:50,height:166}; function dream(){ future; }; Person.future=dream; document.write(typeof Person); document.write(Person.future); ~~~ 而这些会在我们未来的实际编程过程中用得更多。 ### 面向对象 开始之前先让我们简化上面的代码, ~~~ Person.future=function dream(){ future; } ~~~ 看上去比上面的简单多了,不过我们还可以简化为下面的代码。。。 ~~~ var Person=function(){ this.name="phodal"; this.weight=50; this.height=166; this.future=function dream(){ return "future"; }; }; var person=new Person(); document.write(person.name+"<br>"); document.write(typeof person+"<br>"); document.write(typeof person.future+"<br>"); document.write(person.future()+"<br>"); ~~~ 只是在这个时候 Person 是一个函数,但是我们声明的 person 却变成了一个对象 **一个Javascript函数也是一个对象,并且,所有的对象从技术上讲也只不过是函数。** 这里的“”是 HTML 中的元素,称之为 DOM,在这里起的是换行的作用,我们会在稍后介绍它,这里我们先关心下 this。this 关键字表示函数的所有者或作用域,也就是这里的 Person。 上面的方法显得有点不可取,换句话说和一开始的 ~~~ document.write(3*4); ~~~ 一样,不具有灵活性,因此在我们完成功能之后,我们需要对其进行优化,这就是程序设计的真谛——解决完实际问题后,我们需要开始真正的设计,而不是解决问题时的编程。 ~~~ var Person=function(name,weight,height){ this.name=name; this.weight=weight; this.height=height; this.future=function(){ return "future"; }; }; var phodal=new Person("phodal",50,166); document.write(phodal.name+"<br>"); document.write(phodal.weight+"<br>"); document.write(phodal.height+"<br>"); document.write(phodal.future()+"<br>"); ~~~ 于是,产生了这样一个可重用的 JavaScript 对象, this 关键字确立了属性的所有者。 ### 其他 JavaScript 还有一个很强大的特性,也就是原型继承,不过这里我们先不考虑这些部分,用尽量少的代码及关键字来实际我们所要表达的核心功能,这才是这里的核心,其他的东西我们可以从其他书本上学到。 所谓的继承, ~~~ var Chinese=function(){ this.country="China"; } var Person=function(name,weight,height){ this.name=name; this.weight=weight; this.height=height; this.futrue=function(){ return "future"; } } Chinese.prototype=new Person(); var phodal=new Chinese("phodal",50,166); document.write(phodal.country); ~~~ 完整的 JavaScript 应该由下列三个部分组成: * 核心(ECMAScript)——核心语言功能 * 文档对象模型(DOM)——访问和操作网页内容的方法和接口 * 浏览器对象模型(BOM)——与浏览器交互的方法和接口 我们在上面讲的都是 ECMAScript,也就是语法相关的,但是 JS 真正强大的,或者说我们最需要的可能就是对 DOM 的操作,这也就是为什么 jQuery 等库可以流行的原因之一,而核心语言功能才是真正在哪里都适用的,至于 BOM,真正用到的机会很少,因为没有完善的统一的标准。 一个简单的 DOM 示例, ~~~ <!DOCTYPE html> <html> <head> </head> <body> <noscript> disable Javascript </noscript> <p id="para" style="color:red">Red</p> </body> <script type="text/javascript" src="app.js"></script> </html> ~~~ 我们需要修改一下 helloworld.html 添加 ~~~ <p id="para" style="color:red">Red</p> ~~~ 同时还需要将 script 标签移到 body 下面,如果没有意外的话我们会看到页面上用红色的字体显示 Red,修改 app.js。 ~~~ var para=document.getElementById("para"); para.style.color="blue"; ~~~ 接着,字体就变成了蓝色,有了 DOM 我们就可以对页面进行操作,可以说我们看到的绝大部分的页面效果都是通过 DOM 操作实现的。 #### 美妙之处 这里说到的 JavaScript 仅仅只是其中的一小小部分,忽略掉的东西很多,只关心的是如何去设计一个实用的 app,作为一门编程语言,他还有其他强大的内制函数,要学好需要一本有价值的参考书。这里提到的只是其中的不到20%的东西,其他的80%或者更多会在你解决问题的时候出现。 * 我们可以创建一个对象或者函数,它可以包含基本值、对象或者函数。 * 我们可以用 JavaScript 修改页面的属性,虽然只是简单的示例。 * 我们还可以去解决实际的编程问题。