# 语言基础

# 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 引擎

引擎是如何工作的?

引擎很复杂,但是其基本原理却很简单。

  1. 引擎(如果是浏览器,则引擎被嵌入在其中)读取(“解析”)脚本。
  2. 然后,引擎将脚本转化(“编译”)为机器语言。
  3. 然后,机器代码快速地执行。

# 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 是一门还在发展中的语言,定期会添加一些新的功能。

要查看它们在基于浏览器的引擎及其他引擎中的支持情况,请看:

# 代码结构

# 语句

语句是执行行为(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 语句用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环。