国庆节10月1日
--


JS 用 let 声明变量、const 声明常量,是弱类型语言;这篇把基本数据类型、typeof、模板字符串、运算符与流程控制一次讲清,并逐条对照 Java 找异同

上一篇解决了”JS 代码写在哪里”,从这篇开始写代码本身。JS 的基础语法和 Java 很像(所以学过 Java 会觉得眼熟),但它是弱类型语言——变量不挑类型、条件不要求布尔值、除法不做整除……这些差异正是最容易写错的地方,这篇把每一条都和 Java 对照着写。
JS 中用 let 关键字来声明变量——最大的特点是:
JS 是弱类型语言,变量可以存放不同类型的值。
课程代码 02. JS-基础语法.html 里就是这么演示的:
1//1. 声明变量2let a = 10;3a = "Hello"; // 同一个变量,换成字符串也行4a = true; // 换成布尔值也行5
6alert(a); //弹出框 —— 最后弹出的是 truePPT 版本更简短:
1<script>2 //变量3 let a = 20;4 a = "Hello";5 alert(a);6</script>这就是”弱类型”的含义:Java 里 int a = 10; 之后 a = "Hello" 直接编译不过,而 JS 里没有类型检查,变量装什么就是什么。好处是写法灵活,代价是类型错了编译器不会提醒你——只能靠输出语句自己检查(后面马上讲)。
JS 中用 const 关键字来声明常量。一旦声明,常量的值就不能改变(不可以重新赋值)。
1//2. 声明常量2const PI = 3.14;3//PI = 5.0; // 取消注释再刷新,看控制台报错4
5console.log(PI); //输出到控制台6// document.write(PI); //输出到body区域(不常用)PPT 上把这个错误演示了一遍:去掉 PI = 3.5; 的注释,浏览器控制台会报:
1Uncaught TypeError: Assignment to constant variable.常量名习惯全大写(PI、MAX_COUNT),和 Java 的 final 常量一个约定。改常量的错误是运行时报错——页面会停在这一行报错(控制台里一条红色信息),后面的代码不再执行,这一点比 Java 的编译期报错更”晚”。
PPT 给了三条硬规则:
| 规则 | 说明 |
|---|---|
只能用字母、数字、下划线(_)、美元符号($)组成,且数字不能开头 | user_name、userName、$price 都可以;1name 不行 |
| 变量名严格区分大小写 | name 和 Name 是两个不同的变量 |
| 不能用关键字 | 如 let、var、if、for 等 |
早期的 JS 里声明变量还可以用 var,但并不严谨、不推荐:var 声明的变量没有块级作用域(在 if、for 的 {} 里声明会”漏”到外面)、还能重复声明同名变量,很容易写出隐蔽的 bug。现在统一用 let 声明变量、const 声明常量。
写 Java 时用 System.out.println() 看结果;JS 里有三种输出方式(课程代码里都出现了):
| 输出语句 | 效果 | 说明 |
|---|---|---|
window.alert() | 弹出警告框 | 使用频次较高;window. 可以省略,直接写 alert() |
console.log() | 写入浏览器控制台 | 使用频次较高;浏览器按 F12(或右键”检查”)打开开发者工具,切到 Console 面板看 |
document.write() | 向 HTML 的 body 内输出内容 | 不常用(课程代码里就注释掉了) |
调试时首选 console.log():它不像 alert() 那样会拦住页面(每弹一次都要点”确定”),而且能连续打印多条、看到顺序。浏览器控制台应该成为你写 JS 时最常开着的面板。
JavaScript 的数据类型分为:基本数据类型和引用数据类型(对象)。
基本数据类型一共五种,PPT 逐个给了说明:
| 类型 | 说明 | 例子 |
|---|---|---|
number | 数字(整数、小数、NaN(Not a Number)) | let a = 20;、let b = 1.5; |
boolean | 布尔。true、false | let flag = true; |
null | 对象为空。JavaScript 是大小写敏感的,因此 null、Null、NULL 是完全不同的 | let obj = null; |
undefined | 当声明的变量未初始化时,该变量的默认值是 undefined | let x; |
string | 字符串,单引号、双引号、反引号皆可,推荐使用单引号 | 'JS'、"JS"、`JS` |
使用 typeof 运算符可以获取数据类型(课程代码 03. JS-数据类型.html 前半部分,注释里直接写了结果):
1//1. 数据类型2alert(typeof 10); // number3alert(typeof 1.5); // number4
5alert(typeof true); // boolean6alert(typeof false); // boolean7
8alert(typeof "Hello"); // string9alert(typeof 'JS'); // string10alert(typeof `JavaScript`); // string —— 三种引号都是字符串11
12alert(typeof null); // object ← 课程注释里标了问号:null 的类型是 object ?13
14let a;15alert(typeof a); // undefined课程代码在 typeof null 后面专门标了个问号,这个结果确实是”反直觉”的:typeof null 返回 'object'。这是 JS 最早实现时的历史遗留问题,后来被标准固化了(改了会影响老代码,所以一直留着)。判断一个值是不是 null,别用 typeof,直接用相等判断:a === null。
“引用数据类型(对象)“就是后面要学的自定义对象、数组这些——它们的 typeof 结果都是 object;而函数比较特殊,typeof 会返回 function(函数、自定义对象都在 15 篇讲)。
字符串拼接是写页面时最频繁的操作。先看”笨办法”——用 + 把字符串和变量连起来;再看 JS 提供的模板字符串:
模板字符串语法:
` `(反引号,英文输入模式下按键盘的 Tab 键上方波浪线~那个键) 内容拼接变量时,使用${}包住变量。
1//2. 模板字符串 - 简化字符串拼接2let name = 'Tom';3let age = 18;4
5// 传统写法:+ 号拼接(引号会被切断、加号容易漏)6console.log('我是' + name + ', 我今年' + age + '岁');7
8// 模板字符串:整句话用反引号包住,变量用 ${} 嵌进去9console.log(`我是${name}, 我今年${age}岁`);PPT 上还有一版更长的对比,效果一样:
1console.log('大家好, 我是新入职的' + name + ', 今年' + age + '岁了, 请多多关照');2console.log(`大家好, 我是新入职的${name}, 今年${age}岁了, 请多多关照`);两种写法输出完全相同:我是Tom, 我今年18岁。
这条经验往后会一直用:字符串 + 变量 + 字符串这种拼接,一律改成模板字符串——少写一堆引号和加号,也不容易把空格、逗号漏掉。
PPT 把”流程控制”列在 ECMAScript 的范围里但没展开,这里补上写页面必须会用的部分(写法大多和 Java 一样,标 ★ 的是差异点):
| 类别 | 运算符 | 说明 |
|---|---|---|
| 算术 | + - * / % | ★ + 只要两边有字符串就是拼接,不是加法;★ / 是普通除法,5 / 2 得 2.5(不像 Java 的整数除法得 2) |
| 赋值 | = += -= *= /= | 同 Java |
| 比较 | == != > < >= <= | ★ == 会先做类型转换再比较:'10' == 10 结果是 true |
| 全等 | === !== | ★ 类型和值都相同才为 true:'10' === 10 是 false。判断相等推荐用 === |
| 逻辑 | && || ! | 短路特性同 Java |
| 自增自减 | ++ -- | 同 Java |
| 三元 | 条件 ? 值1 : 值2 | 同 Java |
1// + 的两副面孔2console.log(10 + 20); // 30 —— 两边都是数字,做加法3console.log('10' + 20); // 1020 —— 有字符串,做拼接4
5// == 和 === 的区别6console.log('10' == 10); // true —— 先把字符串转成数字再比较7console.log('10' === 10); // false —— 类型不同,直接不等8
9// 除法没有"整除"10console.log(5 / 2); // 2.5== 的隐式类型转换是 JS 里最经典的”坑”(0 == '' 也是 true)。判断相等一律用 ===——和 Java 里”引用类型比地址”的坑不同,JS 的坑是”类型被偷偷换掉”。
if、for、while、switch 的写法与 Java 几乎一样,逐个过一遍:
1// if / else if / else:和 Java 一样2let score = 85;3if (score >= 90) {4 console.log('优秀');5} else if (score >= 60) {6 console.log('及格');7} else {8 console.log('不及格');9}1// for:和 Java 一样,计数变量用 let 声明2for (let i = 1; i <= 5; i++) {3 console.log(i); // 依次输出 1 2 3 4 54}5
6// while:先判断,再执行7let i = 1;8while (i <= 3) {9 console.log(i);10 i++;11}12
13// do…while:先执行一次,再判断(至少执行一次)14let j = 1;15do {16 console.log(j);17 j++;18} while (j <= 3);1// switch:和 Java 一样,每个 case 后面要 break,否则会"穿透"往下执行2let day = 3;3switch (day) {4 case 1:5 console.log('周一');6 break;7 case 3:8 console.log('周三'); // 命中这一条9 break;10 default:11 console.log('其它');12}遍历数组时,JS 最常用的还是 for + 索引(课程案例里就是这么写的):
1let arr = [10, 20, 30];2
3// 索引遍历:课程案例的标准写法4for (let i = 0; i < arr.length; i++) {5 console.log(arr[i]);6}7
8// for…of:直接拿元素(了解,类似 Java 的增强 for)9for (let item of arr) {10 console.log(item);11}和 Java 最大的差异在这里——JS 的条件不要求是布尔值:
1let n = 0;2if (n) {3 console.log('能进来'); // 不会执行4} else {5 console.log('0 被当成 false'); // 会执行6}JS 会做隐式类型转换:0、''(空字符串)、null、undefined、NaN、false 都会被当成 false(这叫”假值”),其余的值都当成 true。Java 里 if (0) 直接编译报错,JS 里却能跑——所以判断”有没有值”时可以直接 if (name),但要清楚它把空字符串也当成了”没有”。
| 对比项 | Java | JavaScript |
|---|---|---|
| 变量声明 | int a = 10; 必须写类型(Java 10+ 的 var 只是类型推断,仍是强类型) | let a = 10; 不写类型,可以随时换类型(弱类型) |
| 常量 | final double PI = 3.14; | const PI = 3.14; |
| 数据类型 | 基本类型 int/double/boolean/char… 分得很细,有固定大小 | 基本类型只有 number、boolean、null、undefined、string 五种;数字不区分整数小数,另有引用类型(对象) |
| 字符串引号 | 只能双引号 "abc" | 单引号、双引号、反引号都可以(推荐单引号) |
| 字符串拼接 | +,复杂拼接用 String.format / StringBuilder | +,更好用的是模板字符串 `${变量}` |
| 相等判断 | == 比基本类型的值 / 引用类型的地址 | == 会先转换类型再比较;===(全等)类型和值都相同才为 true,推荐 === |
| 除法 | 5 / 2 = 2(整数除法) | 5 / 2 = 2.5(都是浮点数) |
| 打印输出 | System.out.println() | console.log()(控制台)、alert()(弹窗)、document.write()(写 body) |
| if 的条件 | 必须是 boolean | 不要求,0、''、null、undefined、NaN 等假值当 false |
| 流程控制 | if / for / while / do-while / switch | 写法基本一致(for、switch、break、continue 都能直接照搬) |
| 数组 | int[] arr = new int[5]; 长度固定 | let arr = [10, 20, 30]; 长度可变,能随意增删(15 篇) |
let、声明常量用 const(一旦声明,常量的值不能改变、不可以重新赋值);早期还能用 var,但不严谨、不推荐(没有块级作用域、可以重复声明)_)、美元符号($)组成且数字不能开头;严格区分大小写(name 和 Name 是两个变量);不能使用关键字(let、var、if、for 等)window.alert() 弹出警告框(window. 可省略,频次高)、console.log() 写入浏览器控制台(频次高,F12 → Console)、document.write() 向 HTML 的 body 内输出内容(不常用)NaN)、boolean、null(对象为空)、undefined(声明未初始化时的默认值)、stringtypeof 运算符获取数据类型;typeof null 的结果是 object(历史遗留问题,判断 null 要用 a === null,别用 typeof)${} 嵌进去,可以完全替代 + 拼接== 会先做隐式类型转换再比较('10' == 10 为 true);===(全等)要求类型和值都相同才为 true,判断相等推荐用 ===+ 两边只要有字符串就是拼接;/ 是普通除法,5 / 2 得 2.5(不像 Java 得 2)if / else if / else、for、while、do…while、switch 的写法和 Java 几乎一样(switch 的 case 照样要写 break);计数变量用 let 声明0、''、null、undefined、NaN、false 会被当成 false(假值),其余都当成 true——所以 if (n) 这种写法在 JS 里是合法的2-1 变量与常量:看看弱类型和”改不动的常量” 按三步做,每步都用输出语句看结果:
10,然后把它依次改成字符串 "Hello"、布尔值 true,弹窗看看最后是什么3.14,用控制台输出它5.0(故意写错),保存后刷新页面,看控制台报了什么错;看完把这行改回注释
(练习文件 test_14_变量与常量.html 里已经给了骨架和写作区。)一级 · 思路:变量用声明变量的关键字、常量用声明常量的关键字;“看结果”有两种办法——弹窗和控制台
二级 · 方法:let 声明变量、const 声明常量;alert(...) 弹窗、console.log(...) 输出到控制台
三级 · 骨架:let a = ____; a = "____"; a = ____; alert(a); / const PI = 3.14; console.log(____); / //PI = 5.0;
1//1. 声明变量(弱类型:同一个变量可以换成别的类型)2let a = 10;3a = "Hello";4a = true;5alert(a); // 最后弹出 true6
7//2. 声明常量8const PI = 3.14;9console.log(PI); // 输出到控制台10//PI = 5.0; // 取消注释会报错:Uncaught TypeError: Assignment to constant variable.对照课程 02. JS-基础语法.html:变量那三行、常量那两行在课程代码里都是分开注释演示的(拆注释逐个看)。第 3 步的报错说明常量不可以重新赋值,而且页面会停在报错那一行。
2-2 用类型检测给五个变量”验明正身”
声明五个变量,分别装:整数 10、小数 1.5、布尔值 true、字符串 'JS'、以及一个只声明不给初始值的变量;再用类型检测运算符把它们的类型逐个打印到控制台。另外顺手检测一下 null 的类型,看结果和你想的是否一样。
(练习文件 test_14_数据类型与typeof.html 里已经给了写作区。)
一级 · 思路:每种值用一个变量装;“类型检测”是一个运算符,直接放在值前面用
二级 · 方法:typeof 值 得到类型字符串(结果有 number、boolean、string、undefined、object);打印用 console.log()
三级 · 骨架:let a = 10; console.log(____ a); / let b; console.log(typeof ____); / console.log(typeof ____); // null 的类型
1let a = 10;2console.log(typeof a); // number —— 整数也是 number3
4let b = 1.5;5console.log(typeof b); // number —— 小数同样是 number(JS 不区分)6
7let c = true;8console.log(typeof c); // boolean9
10let d = 'JS';11console.log(typeof d); // string12
13let e;14console.log(typeof e); // undefined —— 声明了没初始化,默认 undefined15
16console.log(typeof null); // object —— 反直觉,是历史遗留问题对照课程 03. JS-数据类型.html:课程代码把 typeof 的结果直接写在注释里了(//number、//boolean 等),最后一条 alert(typeof null); //null ? -> object 就是那个”问号”。null 的类型判断要用 a === null。
2-3 把拼接写法改成模板字符串
已知两个变量:名字 'Tom'、年龄 18。先用加号拼接输出一句话:我是Tom, 我今年18岁;再用一种”不用加号”的写法输出完全相同的一句话。
(练习文件 test_14_模板字符串.html 里已经给了变量定义和写作区。)
一级 · 思路:JS 有一种字符串专门用来拼接:整句话被一对特殊引号包住,变量可以直接”嵌”在里面
二级 · 方法:模板字符串用反引号(键盘左上角 ~ 那个键)包住整句,变量写成 ${变量名}
三级 · 骨架:console.log('我是' + ____ + ', 我今年' + ____ + '岁'); / console.log(`我是${____}, 我今年${____}岁`);
1let name = 'Tom';2let age = 18;3
4// 传统写法:+ 号拼接5console.log('我是' + name + ', 我今年' + age + '岁');6
7// 模板字符串:整句用反引号包住,变量用 ${} 嵌进去8console.log(`我是${name}, 我今年${age}岁`);对照课程 03. JS-数据类型.html 后半部分(课程输出的句子是”我是Tom, 我今年18岁”)。注意:反引号是成对的,写成单引号 ' 就变成普通字符串、${} 会原样显示出来。
2-4 用循环和判断打印 1~10(偶数做标记)
用循环把 1 到 10 依次打印出来;如果当前数字是偶数,就在数字后面跟上 (偶数),其余数字原样打印。输出示例:1、2(偶数)、3、4(偶数)……
做完再想一句:如果改成打印 1~100,你的代码需要改几个字?
(练习文件 test_14_循环与判断.html 里已经给了写作区。)
一级 · 思路:“重复 10 次”用循环;“是不是偶数”用取余运算符判断,再用 if 选择打印哪种内容
二级 · 方法:for (let i = 1; i <= 10; i++);偶数判断 i % 2 === 0;打印 console.log(...)
三级 · 骨架:for (let i = 1; i <= 10; i++) { if (i % 2 === 0) { console.log(i + '____'); } else { console.log(____); } }
1// 打印 1~10,偶数后面加标记2for (let i = 1; i <= 10; i++) {3 if (i % 2 === 0) {4 console.log(i + '(偶数)');5 } else {6 console.log(i);7 }8}想改成 1~100 只需要把 i <= 10 改成 i <= 100——这就是循环的价值(对应课程 06. JS-案例-员工列表.html 里”遍历所有数据行”的写法:for (let i = 0; i < trList.length; i++))。
3-1 做一份”成绩单统计” 用变量和流程控制统计一个学生的成绩单(不用数组、不用函数,就用手上的语法):
92、数学 85、英语 78(变量名自己起,见名知意)团子团子的总分是255,平均分是85优秀;≥ 80 输出 良好;≥ 60 输出 及格;否则输出 不及格55(模拟补考),刷新页面检查等级有没有跟着变
(练习文件 test_14_综合_成绩单统计.html 里已经给了写作区。)一级 · 思路:第 1~2 步是”存数据”,第 3 步是算术运算,第 4 步是字符串输出,第 5 步是多重条件判断;第 6 步只改一个变量的值,其它代码都不用动
二级 · 方法:let 存成绩、const 存名字;求和用 +、平均分用 /;输出用模板字符串 `…${值}…`;等级用 if / else if / else;打印用 console.log()
三级 · 骨架:let chinese = 92; … / const name = '团子'; / let total = chinese + math + english; / let avg = total / ____; / \name的总分是{},平均分是${}`/if (avg >= 90) { … } else if (avg >= ____) { … }`
1//1. 三科成绩2let chinese = 92;3let math = 85;4let english = 78;5
6//2. 学生姓名(常量)7const name = '团子';8
9//3. 总分、平均分10let total = chinese + math + english;11let avg = total / 3;12
13//4. 模板字符串输出14console.log(`${name}的总分是${total},平均分是${avg}`);15
16//5. 等级判断17if (avg >= 90) {18 console.log('优秀');19} else if (avg >= 80) {20 console.log('良好');21} else if (avg >= 60) {22 console.log('及格');23} else {24 console.log('不及格');25}输出结果:团子的总分是255,平均分是85 和 良好;把 math 改成 55 后平均分变成 75,等级变成 及格——只改变量的值,逻辑一行不用改。
三个检查点:① avg 用的是 total / 3,不是整数除法(JS 除出来是小数,255 / 3 刚好是整数 85);② 等级判断的顺序必须是从高到低,否则 avg >= 60 写在前面会把 92 分也判成”及格”;③ 第 4 步的引号是反引号,写成单引号 ${} 会原样显示。
如果你喜欢,那么欢迎来到我的世界!
了解更多暂未播放



"所有的相遇都是久别重逢。"—— 未知


