(01)① JS 速览——进入 JS 的世界 | JavaScript 初识

432 阅读18分钟
转载请注明出处,未经同意,不可修改文章内容。

🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。

    🔗最终效果链接

涉及面试题:
1. 简单介绍 JavaScript 的发展历史,ES3、ES5、ES6 分别指什么?
2. 说几条写 JavaScript 的基本规范?
3. JavaScript 代码中的 “use strict” 是什么意思?
4. 说说严格模式的限制?

编号:[js_01]

前言: 记得我初次接触 JS 时,真的是完全一片空白,学习的方式方法和之前的 HTML、CSS 一点也不一样。本篇文章行文前也是再三斟酌,也许会过于简单,但怕的就是一来就各种术语,还没进入正轨就打了退堂鼓。

JS 是一款纯正的 Web 编程语言,让我们能够给网页添加行为。有了 JS,我们就能够与用户互动,响应有趣的事件,从网上搜集数据并用于网页中,在网页中绘制图形等。网页不再是枯燥、乏味、静态的,不再只是一动不动地展示在我们面前。掌握 JS 之后,我们还能够赋予网页全新的行为。

1 JS 是从何而来

“竞争”有个最大的好处就是可以促使“新技术”的产生。

20 世纪 90 年代,浏览器领域的竞争异常惨烈。以网景(Netscape——现在的 Mozilla)和微软为首的两大公司迫切需要在其浏览器上添加激动人心的功能来取得优势地位。

为此,1995 年 Netscape 推出了一款脚本语言,让任何人都能够在网页中添加脚本——LiveScript 由此产生,也就是后边更名的 JavaScript。之所以更名,其实是为了搭上当时 Java 名声在外的顺风车。

而微软的反应则是于 1996 年模仿 JavaScript 开发了一种近似的语言,取名 JScript。

面对微软带来的压力,Netscape 提交了对 JavaScript 进行标准化的申请,希望以此来对抗微软。ECMAScript 由此诞生,它是所有 JavaScript 实现(无论是浏览器还是其他环境中)的标准语言定义。

随着时间的推移,1999 年 12 月,ECMAScript3 发布,成为 JavaScript 的通行标准,得到了广泛支持。JavaScript 慢慢站稳了脚跟,也努力地摆脱“业余语言”的名声。

2005 年,Google 发布了 Google Maps,向全世界展示了 JavaScript 在创建动态网页方面的强大威力。成熟了的 JavaScript 获得了专业开发人员的尊敬,很多杰出的编程语言人员也年复一年地致力于改善 JavaScript 解释器的运行性能。

20 多年的发展,当前所有现代浏览器都至少遵循了 ECMAScript5(🏆2009 年发布)。

2015 年 6 月 17 日,ECMAScript6 发布正式版本。2016、2017、2018、2019 年相继发布了《ECMAScript 2016 标准》、《ECMAScript 2017 标准》、《ECMAScript 2018 标准》、《ECMAScript 2019 标准》也昭告着它的与时俱进。

JavaScript 急匆匆地来到这个世界,却是一款功能和表现力强大的语言。

(当我们提到这门语言本身时,通常所指的语言版本是 ECMAScript3、ECMAScript5 和 ECMAScript6。ECMAScript4 已经开发了数年,由于太过庞大,从未发布过正式版本。有时会看到 JavaScript 的版本号——比如 JavaScript1.5 或 JavaScript1.8,这些是 Mozilla 的版本号,版本 1.5 基本上就是 ECMAScript3。)

2 JS 作为网页重要的组成部分

一个“完整的网页”是由 HTML、CSS、JS 组成的:

  • HTML 负责“结构”和“内容”;
  • CSS 负责网页“外观”:字体、边框、颜色、布局、边距等;
  • JS 让网页能够实现“动态行为”:计算、响应、绘画、通信、提醒、变更、更新、修改等。

3 JS 怎么工作

🚀先熟读这篇文章:《前后端交互——发出请求的“客户端”:① 认识 HTTP 客户端》

  • 浏览器加载:与往常一样,在浏览器中输入网页的地址。浏览器遇到 JS 代码后,将立即对其进行分析,为执行做好准备。与 HTML 和 CSS 一样,发现 JS 代码存在错误的时候,浏览器会尽力继续读取后面的 JS,尽可能避免无法向用户显示网页的情况。
  • 浏览器执行:浏览器在网页中遇到 JS 代码后,浏览器会立即执行它,并在网页的整个生命周期不断地执行。

4 如何将 JS 代码加入网页

  1. 通过 <script> 标签放在 <body> 内的最下方;

  2. 可在网页的 <body> 元素中链接到外部文件。

<body>
  <p>
  </p>

  <!-- 一般来说这里引入 JS 代码 -->
  <!-- 方式1: -->
  <script src="index.js"></script>

  <!-- 方式2: -->
  <script>
    alert(1);
  </script>
</body>

5 如何编写 JS 代码

  • 创建 HTML 时,我们通常对文本进行 “标记”,以指定其结构;
  • 使用 CSS 时,我们编写一些 “规则”,其中每一条规则都指定了网页中的元素及其样式;
  • 使用 JS 时,我们是编写一条条 “语句”,每一条“语句”都指定了计算的一小部分,而所有“语句”一起给网页添加行为。

5.1 什么是“语句”

JS 中添加注释的方式:

// 这是单行注释

/*
这是
多行
注释
 */

❗️此外,由于历史上 JavaScript 兼容 HTML 代码的注释,所以 <!----> 也被视为单行注释。

x = 1; <!-- x = 2;
--> x = 3;

上面代码中,只有 x = 1 会执行,其他的部分都被注释掉了。

需要注意的是,--> 只有在行首,才会被当成单行注释,否则就是一个运算符。

/*
下面是一系列语句!
每条语句都做一点点工作,如声明用于存储值的变量。
 */

var age = 29;
var name = "Oli"; // 这里创建了两个变量,它们分别包含“年龄 29”和“值 Oli”;

if(age > 14) { // 有些语句用来做决策,比如用户的年龄是否大于 14;
  
  alert("Sorry this page is for kids only!"); /*
  																						如果是,就提醒用户,指出他太大了,
  																						该网页对他来说不合适;
                                               */
}else {
  alert("Welcome" + name + "!"); // 否则,就欢迎用户,显示后边的字符。
}

5.2 怎样编写一条语句

注释 1:

声明变量时,总是以 var 打头。

注释 2:

变量名称。

“变量名称”的命名方法要遵循:

  • 以字母、下划线或美元符号打头(即,不能用数字打头);
  • 然后使用任意数量的字母、数字、下划线或美元符号。

“变量名称”的命名,我们采用“语义化命名的方式”——即把你想取的中文名字翻译成英文,

然后用驼峰式拼写法拼写。

❗️在命名时,要注意 JS 自身有一些保留字,这些保留字是 JS 用于特殊目的的。我们在给自己需要的变量命名时,要避开这些保留字:

arguments、break、case、catch、
class、const、continue、debugger、
default、delete、do、else、
enum、eval、export、extends、
false、finally、for、function、
if、implements、import、in、
instanceof、interface、let、new、
null、package、private、protected、
public、return、static、super、
switch、this、throw、true、
try、typeof、var、void、
while、with、yield

❗️另外,还有三个词虽然不是保留字,但是因为具有特别含义,也不应该用作标识符 InfinityNaNundefined

注释 3:

运算符 = 用于“赋值”。即,把后面的值赋给前面声明的变量。

注释 4:

值。

值可以是以下类型:

① 数字;

var age = 29;

② 字符串;

var name = "Oli"; // 字符串用双引号引起。

③ 布尔值;

var isBoy = true// 布尔值 true 和 false 不要用引号引起。

④ 表达式;

  • 常量是最简单的一类表达式。变量名也是一种简单的表达式,它的值就是赋值给变量的值。复杂表达式是由简单表达式组成的。

  • 将简单表达式组合成复杂表达式最常用的方法就是使用运算符

  • 表达式的结果为“值”。这些值可以是数字、字符串、布尔值及其他。

    • 数字:

例如下边的表达式:

(9 / 5) * tem + 32  

// 如果 tem 为 10,那么这个表达式的结果就为 50。
  • 字符串:

如下表达式:

name + "," + " you are so cool!"

// 如果 name 的值是 Oli,这个表达式的结果为:Oli, you are so cool!
  • 布尔值:

如下表达式:

color == "orange"

/*
如果 color 的值为“pink”,那么该表达式的值为 false;
如果 color 的值为“orange”,则该表达式的值为 true。
 */

如下表达式:

yourLevel > 5

/*
如果 yourLevel 的值是 4,该表达式的值为 false;
如果 yourLevel 的值为 7,该表达式的结果为 true。
 */
  • 其他:

如数组(一系列值)、对象和函数。

注释 5:

赋值语句总是以 ; 结尾!

5.3 什么是可以重复操作的“循环语句——while”

循环语句可以让一部分代码重复执行。

(当然除了这里介绍的 while ,还有其他多种反复执行循环代码的方式: forfor inforEach ,后边我们再慢慢介绍。 )

while(scoops > 0) {
  document.write("Another scoop!");
  scoops = scoops - 1;
}

注释 1:

while 打头。

注释 2:

这种语句包含一个布尔表达式,我们称之为条件测试(简称“条件”)。

  • 如果“条件”为 true ,则执行下边用“花括号 {} ”括起的“代码块”,并回头来再次检查条件
  • 如果“条件”为 false ,就结束循环。

注释 3:

代码块中包含需要执行的代码。

  • 🏆while 循环工作原理:
var chapters = 3// 1️⃣首先,我们将 chapters 设置为 3;

while(chapters > 0) { /*
											2️⃣其次,我们执行 while 语句,检查其中的条件,看其是 true 还
  										是 false。这里 3>0,条件为 true,则执行以下代码块中语句;
                       */

  document.write("Another chapter!<br>"); /*
  																				3️⃣接着,代码块中第一条语句是在浏览器中写
  																				入 "Another chapter!<br>";
                                           */

  chapters = chapters - 1; // 4️⃣继而,执行下一条语句是“章节”减 1,并把结果 2 赋值给 chapters;

} // 5️⃣直到这里,代码块中的最后一条语句执行完,我们返回 while 语句开头继续重复上边的操作;


document.write("Oli, I finished the book."/*
																					 6️⃣最后,当上边的循环操作执行到球数减至 0 时,
																					 条件为 false,则停止执行代循环中的代码块。
                                           我们将跳过代码块,执行本行语句——在浏览器上
                                           写入:"Oli, I finished the book."。
                                            */

5.4 如何用 JS 做决策、做判断——if 条件判断语句

在 while 语句中,我们使用“条件”来决定是否继续执行循环中的代码块。

在 JS 中,还可在 if 语句中使用布尔值来进行决策、判断。

仅当 if 语句的条件测试为 true 时,才会执行其代码块。

if(chapters >= 5) {
  alert("Come on, keep fighting!");
}else if(chapters < 2) {
  alert("Wow! Oli, you will get it! ");
}
// ❗️注意格式。

6 JS 怎样与用户交流

6.1 创建提醒框——alert

仅当你要停止一切并提醒用户时,才应使用它。这个功能是浏览器自带的,实际工作中我们都是自己重新编写更有特色的 UI 弹框来提醒。

6.2 直接写入文档—— document.write

将网页视为一个文档(浏览器就是这么认为的)。你随时都可使用函数 document.write 将任何 HTML 和内容写入网页——实际工作中,本方法不可取!

6.3 使用控制台——console.log

在开发网页期间调试代码时,我们可以很直观地了解和学习代码的功能(用户一般不会去看控制台消息)。方式: 网页 --> 右键 --> 检查 --> console

6.4 直接操作文档——DOM 文档对象模型

这是最佳的方式。

使用 DOM 可以访问网页、读取和修改其内容,甚至修改其结构和样式。但,要使用 DOM,你必须:

  • 知道网页的结构;
  • 熟悉用来读写网页的编程接口。

7 使用上面的知识写一些可以用的代码

🔗最终效果链接

🔗源码链接

7.1 需求

  1. 有一个 1*7 的网格,网格中有一艘战舰,且战舰占据三个单元格;
  2. 目标:通过尽可能少的猜测次数将浏览器的战舰全部击沉。将根据你的表现给你打分;
  3. 准备工作:这个游戏启动时,计算机将战舰放在一个虚拟网格中。然后,游戏将让你进行第一次猜测;
  4. 玩法:浏览器将提示你猜测位置,然后你输入网格位置。你猜测后,将显示结果 HitMissYou sank my battleship! 。所有战舰被击沉后,游戏结束并显示你的得分。

7.2 分析游戏流程

7.2.1 用户启动游戏

游戏将一艘战舰随机地放在网格中,注意这些网格是虚拟的。

  • 创建一艘战舰,并指定它在排列成一行的 7 个单元格中占据哪三个单元格;
  • 这些单元格是使用整数表示的,是虚拟的,在代码中我们并不需要把网格本身表示出来,例如整数 1、2、3 就可以表示为战舰占据了 3 个单元格。

7.2.2 开始游戏

重复下面的步骤,直到战舰被击沉:

  • 提示用户猜测一个位置(2、0 等)——使用浏览器自带函数 prompt 来显示一条消息,并从用户那里获取输入(一个 0-6 的数字);
  • 获取用户的输入,将用户猜测的位置与战舰的位置比较,确定结果是击中、未击中还是击沉。

7.2.3 游戏结束

根据猜测次数给用户打分并显示结果(使用浏览器自带函数 alert 显示结果)。

7.3 编写伪代码

伪代码介于 JS 代码和程序的自然语言之间,是一种规划和编写代码的方法。

7.3.1 所需变量

  • 声明 3 个变量,用于存储战舰占据的各个单元格。
location1
location2
location3
  • 声明 1 个存储用户猜测的变量,将其命名为 guess
  • 声明 1 个存储击中次数的变量,将其命名为 hits 并初始化为 0
  • 声明 1 个存储猜测次数的变量,将其命名为 guesses 并初始化为 0
  • 声明 1 个记录战舰是否被击沉的变量,将其命名为 isSunk 并初始化为 false

7.3.2 程序逻辑

7.4 编写 HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Battleship</title>
  <meta charset="utf-8">
</head>
<body>
  <h1>Hey Oli, let's play battleship!</h1>
  <script src="./battleship.js"></script>
</body>
</html>

7.5 编写游戏代码

7.5.1 声明变量

var location1 = 3;
var location2 = 4;
var location3 = 5;
// 这是三个位置变量。我们暂时将战舰放置在 3、4、5 单元格内。后边我们再考虑“随机放置位置”;

var guess; // 用户猜测前,变量 guess 没有值,因此是未定义的;
var hits = 0;  
var guesses = 0// 我们将变量 hits 和 guesses 的初始值都设为 0;

var isSunk = false/*
										最后,设置变量 isSunk 的初始值为 false。用户击沉战舰后我们将把
										这个变量设置为 true。
                     */

/*
❗️注意,如果你没有给变量指定初始值,JS 将给它指定默认值 undefined。
JS 使用 undefined 来指出还没有给变量赋值。
 */

7.5.2 创建循环并获取输入

while(isSunk === false) { /*
													前面说过,while 语句使用条件测试来决定是否继续循环。在这里,
													我们通过检查确认 isSunk 仍为 false。一旦战舰被击沉,将会
                          将 isSunk 设置为 true。
                           */

  guess = prompt("Ready, aim, fire!(enter a number 0-6):"); /* 
  																								每次循环时都让用户进行猜测。
                                                  ❗️❗️❗️prompt() 方法用于显示可提示
                                                  用户进行输入的对话框,这个方法返回用户
                                                  输入的字符串。
                                                             */
}

7.5.3 检查用户的猜测

while(isSunk === false) {
  guess = prompt("Ready,aim,fire!(enter a number from 0-6):");

  if(guess<0 || guess>6) { /*
  												 首先要确认用户的输入是否有效,里边的 || 表示布尔“或”运算
  												 符:只要至少有一个表达式为 true,则结果为 true;
                            */

    alert("Please enter a valid call number!"); /*
    																						如果输入无效,就使用 alert 向用户
    																						指出这一点;
                                                ❗️alert() 方法显示带有一条指定消息
                                                和一个 OK(确认) 按钮的警告框。
                                                 */
  }else {
    guesses = guesses + 1// 如果输入有效,就将 guesses 加 1,以记录用户猜测的次数。
  }
}

💡布尔运算符,本篇混个眼熟,下篇文章会详讲!)

布尔运算符用于结果为 true 或 false 的布尔表达式中。有两种布尔运算符:

  • 比较运算符

  • 逻辑运算符

    • 比较运算符:
      比较运算符对两个值进行比较。下面是一些常见的比较运算符:
运算符描述
<表示小于
>表示大于
==表示等于
===表示严格相等
<=表示小于或等于
>=表示大于或等于
!=表示不等于
  • 逻辑运算符:

逻辑运算符将两个布尔表达式合二为一,得到一个布尔结果(true 或 false)。

运算符描述
||表示“或”,只要至少有一个表达式为 true,结果就为 true。
&&表示“与”,仅当两个表达式都为 true 时,结果才为 true。
!表示“非”,仅当表达式为 false 时,结果才为 true。

7.5.4 添加击中检测代码

while(isSunk === false) {
  guess = prompt("Ready,aim,fire!(enter a number from 0-6):");
  if(guess<0 || guess>6) {  
    alert("Please enter a valid call number!"); 
  }else {
    guesses = guesses + 1;  

    if(guess == location1 || guess == location2 || guess == location3) {  
    // 我们使用 || “或”运算符将三个条件合而为一,并将其用于一条 if 语句中;
      
      alert("HIT!"); // 击中了,我们要让用户知道结果;
        
      hits = hits + 1/*
      				   如果 guess 等于 location1、location2 或 location3,
      				   就将 hits 加 1;
                        */

      if(hits === 3) { // 检查是否击中了 3 次;
          
        isSunk = true; /*
        			   如果击中了 3 次就将 isSunk 设置为 true。如果 isSunk 为 true,
        			   则整个游戏循环结束,执行下一条语句;
                        */
          
        alert("Oli, you sank my battleship!"); // 同时让用户知道这一点;
      }
    }else {
      alert("MISS"); // 如果一个位置都没击中,则提示用户“MISS”。
    }
  }
}

7.5.5 游戏结束,进行游戏后分析

while(isSunk === false) {
  guess = prompt("Ready,aim,fire!(enter a number from 0-6):");
  if(guess<0 || guess>6) {  
    alert("Please enter a valid call number!"); 
  }else {
    guesses = guesses + 1;  
    if(guess == location1 || guess == location2 || guess == location3) {  
      alert("HIT!");  
      hits = hits + 1; 
      if(hits === 3) { 
        isSunk = true;
        alert("Oli,you sank my battleship!"); 
      }
    }else {
      alert("MISS"); 
    }
  }
}

var stats = "Oli, you took" + guesses + "guesses to sink the battleship," + " which means your shooting accuracy was " + (3/guesses);  
/*
我们创建一个用运算符 “+” 来连接的字符串,其中包含要向用户显示的消息(包括用户猜测的次数和射击精度),
并将这个字符串赋值给声明的变量 stats;
 */

alert(stats); // 最后通过 alert 显示给用户。

7.5.6 ❗️以上的游戏代码有个 bug

上边的代码,我们是指定死了战舰的位置是在 3、4、5,实际玩起来没有乐趣可言。

那如果想随机地放置战舰的位置,我们又需要考虑什么呢?

  • 在包含 7 个单元格的一维网格中,战舰自身要占据相连的 3 个单元格;
  • 把 3 个连续的单元格放在 7 个单元格里,有多少种方法?——我们需要考虑一个起始位置;
  • 单元格以 0 开始,那么起始位置必须是 0-4,不然战舰放不下。

7.5.7 如何随机地指定战舰位置呢

在确定了起始位置是 0-4 后,就可以使用它和接下来的两个单元格来放置战舰。

var location1 = randomLoc;
// 使用随机位置和接下来的两个单元格。

var location2 = location1 + 1;
var location3 = location2 + 1;

❓如何生成“随机位置”——声明一个变量 randomLoc ,将一个 0-4 的随机整数赋给这个变量。

  • 首先,得到一个“随机小数”: Math.random() ——如:0.128、0.845、0.9 等;
  • 其次,得到一个 0-5 的(不包含 5)“包含小数的随机数字”: Math.random() * 5 ——如:0.64、4.225、4.5 等;
  • 最后,将上一步“包含小数的随机数字”的小数去掉,得到 0-4 的整数: Math.floor(Math.random() * 5)

🏆改良后的战舰游戏代码如下:

var randomLoc = Math.floor(Math.random() * 5);
var location1 = randomLoc;
var location2 = location1 + 1;
var location3 = location2 + 1;

var guess;
var hits = 0;  
var guesses = 0;
var isSunk = false;

while(isSunk === false) {
  guess = prompt("Ready, aim, fire!(enter a number from 0-6):");
  if(guess<0 || guess>6) {  
    alert("Please enter a valid call number!"); 
  }else {
    guesses = guesses + 1;  
    if(guess == location1 || guess == location2 || guess == location3) {  
      alert("HIT!");  
      hits = hits + 1; 
      if(hits === 3) { 
        isSunk = true;
        alert("Oli, you sank my battleship!"); 
      }
    }else {
      alert("MISS!"); 
    }
  }
}

var stats = "Oli, you took " + guesses + " guesses to sink the battleship," + " which means your shooting accuracy was " + (3/guesses); 

alert(stats);

8 说说代码重用——函数

通过写这个简易战舰游戏,你可能注意到了:我们使用了几个内置函数:如 alertpromptconsole.logMath.random

这些函数让你能够弹出对话框、将输出写入控制台以及生成随机数,而你需要做的工作很少。这些内置函数是为你编写好的现成代码,你可根据需要反复使用,而使用时只需调用即可。

(注:实际工作中,我们需要的弹框等,一般不再用上边的浏览器自带的 promptalert 来实现,为了用户体验,我们都会自己写出更好看的弹框。)


后记: 本篇文章,先来了一个小白式的大杂烩,由于行文过于宽泛,因此也就挖了不少的“坑”,留下了不少疑问。

  • 文中的代码多次用到了诸如 + 这样的“运算符”,可我们也未曾详细学习 JS 中都有哪些“运算符”、“运算符”之间有优先级吗?
  • 文中提到“值可以有多种类型”,但我们并没有详细阐述和分类这些“类型”,也没有谈到这些“类型”之间如何转换?
  • 文中代码多次用到如 if 这种“流程控制判断语句”,可我们依然未曾系统地学习何为“流程控制判断”?
  • 文末提到了“函数”,可“函数”到底是什么呢?

带着这些“坑”和疑问,让我们用接下来的几篇文章一个个地说明白。

祝好,qdywxs ♥ you!