JavaScript 基础语法

这篇讲 JavaScript 的基础语法:输出、输入、变量、数据类型、运算符和控制流。内容不多,但都是后面写代码的基础,建议你边看边动手运行示例代码。

在开始之前先说一个你会经常看到的词:ES6。JavaScript 的正式名称叫 ECMAScript,ES6 就是它在 2015 年发布的第 6 个大版本。这个版本加了很多好用的新语法,比如 let/const、箭头函数、class、模板字符串等等。现在这些语法已经是标准写法了,所有主流浏览器和 Node.js 都支持。后面教程中提到「ES6 引入的」,你知道它就是指这次更新就行。

输出

JavaScript 最常用的输出方式是 console.log(),它会在控制台打印内容,并且自动换行:

console.log() 每次调用都会自动换行。如果你不想换行,可以用 process.stdout.write()

日常用 console.log() 就够了,process.stdout.write() 在需要精确控制输出格式时才用。

输入处理

在算法题中,经常需要从标准输入读取数据。JavaScript 用 readline 模块来逐行读取输入,这是最常用的方式:

这段代码看起来有点长,我来拆解一下核心逻辑:

  1. readline.createInterface() 创建一个读取器,绑定到标准输入 process.stdin
  2. rl.on("line", ...) 每读到一行就把它存进 lines 数组
  3. rl.on("close", ...) 输入全部读完后,在这个回调函数里处理数据

这个模板你先记住就行,后面做算法题时会反复用到。核心思路就是先把所有输入收集起来,等输入结束后再统一处理

下面是一个更实用的模板,读取两个数并求和:

这里用 line.trim() 去掉行首行尾的空白,split(" ") 按空格拆分成数组,parseInt() 把字符串转成整数。这些都是处理输入时的常用操作。

变量

JavaScript 有三种声明变量的方式:letconstvar

简单记:能用 const 就用 const,需要修改的值才用 let

你可能还会在一些代码里看到 var。它是 JavaScript 早期声明变量的方式,功能和 let 类似,但有一些容易踩坑的行为(比如变量提升、没有块级作用域),所以现在不推荐使用了,了解一下就行:

// var 的写法(不推荐,了解即可)
var oldWay = "旧写法";

后面写代码时,统一用 letconst 就好。

数据类型

JavaScript 有几种基本数据类型:

类型说明示例
number数字(整数和小数统一)423.14-10
string字符串"hello"'world'
boolean布尔值truefalse
null空值(主动赋的)null
undefined未定义(变量声明了但没赋值)undefined

有一个值得注意的点:JavaScript 的 number 类型不区分整数和浮点数,4242.0 是完全一样的。这让数字处理变得简单,但也有个小坑:0.1 + 0.2 的结果不是 0.3(浮点精度问题),这在所有编程语言里都存在。

typeof 运算符可以检查一个值的类型:

typeof null 返回 "object" 是一个历史遗留问题,知道就行,不用深究。

类型转换

不同类型的值之间经常需要互相转换,JavaScript 提供了几个常用的转换函数:

Number() 会严格转换整个字符串,如果字符串里有非数字字符就返回 NaN(Not a Number)。而 parseInt()parseFloat() 更宽松,它们从字符串开头开始解析,遇到非数字字符就停止。

还有一种你会经常碰到的情况:字符串拼接时的隐式转换。

这里的关键:+ 号遇到字符串就变成拼接,其他算术运算符会自动把字符串转成数字。这是一个常见的坑,写代码时要注意。

运算符

算术运算符

注意一个重要的点:JavaScript 的除法 / 默认就是数学除法,17 / 5 得到 3.4,不会自动截断成整数。想要整数除法的效果,就用 Math.floor() 向下取整。

比较运算符

JavaScript 有两套相等运算符:===(严格相等)和 ==(宽松相等)。永远用 ===!==,忘掉 ==!=。宽松相等会做各种你意想不到的类型转换,是 bug 的温床。

逻辑运算符

位运算

位运算直接操作数字的二进制位,在处理二进制相关问题时非常高效。详细的位运算原理可以参考 常用的位操作,这里了解一下基本用法就行:

控制流

if / else if / else

三元运算符 条件 ? 值1 : 值2 适合简单的条件赋值,逻辑复杂时还是老老实实用 if-else 更清晰。

for 循环

经典的 for (let i = 0; i < n; i++) 你会用得最多,后面写算法题基本离不开它。for...of 在遍历数组和字符串时写起来更简洁,也很常用。

while 循环

while 循环在条件满足时重复执行,适合不确定循环次数的场景。do...while 保证循环体至少执行一次,用得比较少。

break 和 continue

break 是"我不玩了,直接出去",continue 是"这一轮跳过,下一轮继续"。

switch

switch 适合一个变量需要和多个固定值比较的场景:

注意每个 case 后面都要写 break,否则会"穿透"到下一个 case 继续执行。default 是所有 case 都不匹配时的兜底。实际写代码时,大多数情况用 if-else 就够了,switch 用得不算多。

异常处理

JavaScript 用 throw 抛出错误,用 try-catch-finally 接住。

throw 后面可以跟任何值(数字、字符串都行),但推荐抛 Error 或其子类,这样 stackmessage 属性都在,调试时能看到堆栈。

常见的内置错误类型有 TypeError(对 null/undefined 取属性、调用不是函数的值,都会抛这个)、RangeError(值越界)、SyntaxError(语法错)、ReferenceError(引用了未定义的变量)。业务代码里如果要抛自定义错误,继承 Error 即可。

catch 后面的 (e) 不关心错误时可以省略,直接写 catch {} 即可,这是较新的语法,现代 Node 和浏览器都支持。finallytrycatch 之后都会执行,常用来关闭连接、释放锁、恢复状态。

写服务端代码时,建议在边界层(HTTP 请求入口、事件监听、定时任务)加一层 try-catch,这样某个小错误不会把整个 Node 进程直接干崩。

小结

这篇涵盖了 JavaScript 的基础语法:console.log() 输出、readline 读取输入、let/const 声明变量、基本数据类型和类型转换、运算符、以及 if/for/while 等控制流。

有几个关键点再强调一下:

  • 比较用 ===,不要用 ==
  • 除法 / 默认产生小数,想要整数用 Math.floor()
  • + 号遇到字符串就变成拼接,注意类型转换

下一篇我们来讲讲 JavaScript 的 模块与导入 机制,看看 require 是怎么回事,哪些功能需要导入、哪些直接就能用。