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