# 语言基础
# JavaScript 简介
# Javascript 是什么?
Javascript 是一种运行在客户端的脚本语言,不需要编译,经 JS 解释器逐行来解释并执行,现在也可以基于 node.js
技术进行服务器端编程
JavaScript 最初被创建的目的是“使网页更生动”。这种编程语言写出来的程序被称为 脚本。它们可以被直接写在网页的 HTML 中,在页面加载的时候自动执行。
JavaScript 于 1961 年 由 Brendan Eich
发明,诞生于网景公司,名字蹭了 Java 的热度
为什么叫 JavaScript
JavaScript 在刚诞生的时候,它的名字叫 “LiveScript”。但是因为当时 Java 很流行,所以决定将一种新语言定位为 Java 的“弟弟”会有助于它的流行。 随着 JavaScript 的发展,它已经成为了一门完全独立的语言,并且也拥有了自己的语言规范 ECMAScript。现在,它和 Java 之间没有任何关系。
浏览器核心分为两部分,渲染引擎和 JS 引擎,JavaScript 引擎有时也称作“JavaScript 虚拟机”
浏览器引擎 | |
---|---|
渲染引擎 | 用来解析 HTML 和 CSS,生成 Layout Tree ,进而生成 Render Tree ,并渲染出画面 |
脚本引擎 | JS 解释器,读取网页中的 JavaScript 代码,并执行 |
渲染引擎:
- Chrome Webkit ==> Blink
- Firefox Gecko ==> Goanna
- IE Trident
- Edge EdgeHTML ==> Blink
JS 引擎:
- Firefox 使用代号为 SpiderMonkey 的 JS 引擎
- Chrome 和 Opera 以及新版 Edge 使用代号为 V8 的 JS 引擎
- IE 使用代号为 Chakra 的 JS 引擎
引擎是如何工作的?
引擎很复杂,但是其基本原理却很简单。
- 引擎(如果是浏览器,则引擎被嵌入在其中)读取(“解析”)脚本。
- 然后,引擎将脚本转化(“编译”)为机器语言。
- 然后,机器代码快速地执行。
# JavaScript 能做什么
邮件表单、网页特效、服务端开发、桌面程序、APP、物联网、游戏开发
- 浏览器中的 JavaScript 能做什么
现代的 JavaScript 是一种“安全的”编程语言。它不提供对内存或 CPU 的底层访问,因为它最初是为浏览器创建的,不需要这些功能。
JavaScript 的能力很大程度上取决于它运行的环境。例如,Node.js
支持允许 JavaScript
读取/写入任意文件,执行网络请求等的函数。
浏览器中的 JavaScript 可以做与网页操作、用户交互和 Web 服务器相关的所有事情。
- 浏览器中的 JavaScript 不能做什么
为了用户的(信息)安全,在浏览器中的 JavaScript 的能力是受限的。目的是防止恶意网页获取用户私人信息或损害用户数据。
此类限制的例子包括:
- 网页中的 JavaScript 不能读、写、复制和执行硬盘上的任意文件。它没有直接访问操作系统的功能。
- 不同的标签页/窗口之间通常互不了解。尤其是不同源的标签页
- JavaScript 可以轻松地通过互联网与当前页面所在的服务器进行通信。但是从其他网站/域的服务器中接收数据的能力被削弱了。尽管可以,但是需要来自远程服务器的明确协议(在 HTTP header 中)。这也是为了用户的信息安全。
时值 2022 年,第一点似乎不那么成立了。File System Access API (opens new window)
# 为什么 JavaScript 胜出了
至少有 3 件事值得一提:
- 与 HTML/CSS 完全集成。
- 简单的事,简单地完成。
- 被所有的主流浏览器支持,并且默认开启。
# 总结
- JavaScript 最开始是专门为浏览器设计的一门语言,但是现在也被用于很多其他的环境。
- 如今,JavaScript 已经成为了与 HTML/CSS 完全集成的,使用最广泛的浏览器语言。
- 有很多其他的语言可以被“编译”成 JavaScript,这些语言还提供了更多的功能。建议最好了解一下这些语言,至少在掌握了 JavaScript 之后大致的了解一下。
# 手册与规范
# 手册
MDN(Mozilla)JavaScript 索引 是一个带有用例和其他信息的手册。它是一个获取关于个别语言函数、方法等深入信息的很好的来源。
你可以在https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference (opens new window) 阅读它。
# 规范
ECMA-262 规范 包含了大部分深入的、详细的、规范化的关于 JavaScript 的信息。这份规范明确地定义了这门语言。
但正因其规范化,对于新手来说难以理解。所以,如果你需要关于这门语言细节最权威的信息来源,这份规范就很适合你(去阅读)。但它并不适合日常使用。
每年都会发布一个新版本的规范。最新的规范草案请见 https://tc39.es/ecma262/ (opens new window)。
# 兼容性表
vaScript 是一门还在发展中的语言,定期会添加一些新的功能。
要查看它们在基于浏览器的引擎及其他引擎中的支持情况,请看:
- http://caniuse.com (opens new window) —— 每个功能的支持表,例如,查看哪个引擎支持现代加密(cryptography)函数:http://caniuse.com/cryptography (opens new window)。
- https://kangax.github.io/compat-table/es6/ (opens new window) —— 一份列有语言功能以及引擎是否支持这些功能的表格。
# 代码结构
# 语句
语句是执行行为(action)的语法结构和命令。 通常,每条语句独占一行,以提高代码的可读性:
// bad
alert("Hello");
alert("World");
// good
alert("Hello");
alert("World");
# 分号
即使语句被换行符分隔了,我们依然建议在它们之间加分号。
这个规则被社区广泛采用。我们再次强调一下 —— 大部分时候可以省略分号,但是最好不要省略分号,尤其对新手来说。
# 注释
单行注释以两个正斜杠字符 // 开始。
多行注释以一个正斜杠和星号开始 “/” 并以一个星号和正斜杠结束 “/”。
// 这行注释独占一行
alert("Hello");
alert("World"); // 这行注释跟随在语句后面
/* 两个消息的例子。
这是一个多行注释。
*/
alert("Hello");
alert("World");
# “use strict”
这个指令看上去像一个字符串 "use strict" 或者 'use strict'。当它处于脚本文件的顶部时,则整个脚本文件都将以“现代”模式进行工作。
# 变量
变量是对“值”的具名引用。变量就是为“值”起名,然后引用这个名字,就等同于引用这个值。
JavaScript 的变量名区分大小写
- 如果只是声明变量而没有赋值,则该变量为 undefined
- 如果不进行声明直接赋值,则自动为全局变量,所以建议总是使用 var/let/const 命令声明变量
# 标识符
标识符identifier
指的是用来识别各种值的合法名称,关键字、保留字不可用于命名变量,JavaScript 语言的标识符对大小写敏感
- 第一个字符,可以是字母以及美元符号($)和下划线(_)。
- 后面的字符,除了 Unicode 字母、美元符号和下划线,还可以用数字 0-9。
- 驼峰命名法:首字母小写,后面单词首字母大写
# 区块
JavaScript 使用大括号,将多个相关的语句组合在一起,称为“区块”(block)。 注意区块对于 var 命令不构成单独的作用域
# 声明
- var 用 var 声明的变量,不是函数作用域就是全局作用域。var 允许重新声明。
- let 用 let 声明的变量具有块级作用域,颗粒度更细。let 不允许重新声明
- const 声明一个常数(不变)变量,可以使用 const 而非 let
let a = "a";
if (a === "a") {
var b = "b";
let c = "c";
}
console.log(b); // b
console.log(c); // c is not defined
# 大写命名
大写命名的常量仅用作“硬编码(hard-coded)”值的别名
# 赋值和比较
赋值表达式
=
给变量赋予数值
相等运算符
==
比较时,发生类型转换,数值相同即为 true
全等运算符
===
比较时,不发生类型转换,必须严格相等
# 变量提升
JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting),由于在 JS 中函数是一等公民,因此函数会最先被提升
# 流程控制
# 分支
JavaScript 提供 if 结构和 switch 结构,完成条件判断,即只有满足预设的条件,才会执行相应的语句。
if 结构 先判断一个表达式的布尔值,然后根据布尔值的真伪,执行不同的语句
if (条件) {
语句;
}
- if…else 结构
if 代码块后面,还可以跟一个 else 代码块,表示不满足条件时,所要执行的代码
if (条件) {
// 满足条件时,执行的语句
} else {
// 不满足条件时,执行的语句
}
- switch case 结构
注意 switch 用的运算符是全等运算符,这意味着比较时不会发生类型转换。
switch (条件) {
case "情况1":
// 执行1;
break;
case "情况2":
// 执行2;
break;
default:
//默认;
}
- 三元运算符
条件 ? (空格) 表达式1 : 表达式2;
这个三元运算符可以被视为 if...else...的简写形式,因此可以用于多种场合
# 循环
循环语句用于重复执行某个操作,它有多种形式。
for 循环
for (初始化表达式; 条件; 递增表达式) {
语句;
}
- while 循环 只要条件为真,就不断循环执行代码块
while (条件) {
语句;
}
- do...while 循环 不管条件是否为真,do...while 循环至少运行一次
do {
语句;
} while (条件);
# 短路
break
语句用于跳出代码块或循环。return
常用于函数返回值。continue
语句用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环。