简介
JavaScript 诞生于 1995 年,由网景公司开发,最初是为了解决一个痛点:在拨号上网的年代,网页验证输入(比如检查字段是否为空)得跟服务器来回通信。文件一大,半分钟才能返回结果,用户体验惨不忍睹。于是,JavaScript 横空出世,接管了客户端的输入验证,从此网页交互告别了“龟速时代”。
完整的 JavaScript 由三部分组成:
- 核心(ECMAScript):由 ECMA-262 标准定义,提供语言的基本规则和功能,比如变量、循环啥的。
- 文档对象模型(DOM):让 JS 能操作网页内容,比如改标题、加图片。
- 浏览器对象模型(BOM):提供与浏览器交互的接口,比如控制窗口、读 URL。
书写方式
JavaScript 的写法跟 CSS 类似,分三种:行内、内联和外部。
<!-- 行内:直接写在HTML属性里 -->
<input type="button" value="点击" οnclick="javascript:alert('天天开心!')" />
<!-- 内联:写在<script>标签里 -->
<script>
document.write('Hello,World!')
</script>
<!-- 外部:引入单独的JS文件 -->
<script src="script.js">
// !注意:这里面不要写代码!写了也白写
</script>
有个坑:外部引入<script src="...">时,标签里再写代码是无效的,浏览器直接忽略。还有个<noscript>标签,专门对付不支持 JS 的浏览器:
<noscript>
<h1>你的浏览器不支持脚本!</h1>
<!-- 不支持JS或关闭JS时,显示这里的内容 -->
</noscript>
早期浏览器不认 JS 时,<noscript>能优雅降级显示替代内容。现在基本没人用老古董浏览器了,但有些用户会禁用 JS(比如安全控),这标签还能派上用场。它可以嵌在<body>里任何地方,但不能跟<script>混着用。
区分大小写
JavaScript 里一切都区分大小写。变量名、函数名、操作符,全都得注意大小写。比如:
let Test = '大写'
let test = '小写'
console.log(Test) // "大写"
console.log(test) // "小写",两个完全不同的变量
写错大小写,JS 可不会手下留情,直接报错或给你意外结果。
标识符
标识符就是给变量、函数、属性或参数起的名字。规则如下:
- 第一个字符:必须是字母(A-Z 或 a-z)、下划线(_)或美元符($)。
- 其他字符:字母、下划线、美元符或数字(0-9)都可以。
推荐用驼峰命名法,首单词小写,后续单词首字母大写:
let firstSecond
let myCar
这不是硬性要求,但跟 JS 内置函数(比如 getElementById)风格一致,可读性也好,是最佳实践。注意:关键字、保留字不能当标识符用。
注释
JS 用 C 语言风格的注释,有单行和多行两种:
// 单行注释:简单记录一下
let x = 10 // 设置初始值
/* 多行注释:
可以写长点,
比如解释复杂逻辑 */
写代码时加注释是个好习惯,尤其是团队合作时,能救命。
严格模式
ECMAScript 5 引入了严格模式(Strict Mode),让 JS 更规范。开了严格模式,一些稀里糊涂的写法(比如没声明变量就用)会直接报错。要启用很简单,在脚本开头加一句:
'use strict'
这行是个“魔法指令”,告诉 JS 引擎按严格规则跑代码。也可以只给某个函数加:
function helloWorld() {
'use strict'
// 这里是严格模式
}
所有现代浏览器都支持。开了严格模式,代码更安全,但也得小心别踩新坑。
语句
JS 语句一般用分号(;)结尾,省略也可以,但不推荐:
let sum = a + b // 有效但别这么干
let diff = a - b // 加上分号,清晰又保险
解析器能猜语句在哪结束,可一旦猜错(比如代码压缩后),就炸了。所以老老实实加分号吧。控制语句(像 if)最好用代码块,哪怕只有一行:
// 不推荐:容易改错
if (test) console.log(test)
// 推荐:清晰又安全
if (test) {
console.log(test)
}
用大括号,改代码时不容易出错,看着也舒服。
注意:分号使用要有原则,全加或全省都行,别中途变卦。
变量
JS 变量是个“万能箱”,啥类型的数据都能装,就是个占位符。
var
用 var 声明变量:
var message // 未初始化,默认是undefined
不赋值时,变量默认是 undefined。可以直接初始化:
var message = 'hi'
像这样叫做初始化,这样初始化变量不会把它标识为字符串类型,只是一个简单的赋值而已。随后,不仅可以改变保存的值,也可以改变值的类型:
var message = 'hi' // 赋值字符串
这只是赋值,不是固定类型。JS 很灵活,值和类型都能改:
var message = 'hi'
message = 100 // 改成数字,合法但不建议
上面先存字符串,再改成数字,没问题,但容易让人懵,最好别乱改类型。
var 作用域
var 声明的变量有作用域特性:在函数里定义的,出了函数就销毁:
function test() {
var message = 'hi'
}
test()
console.log(message) // 报错:message is not defined
但如果省略 var,就成了全局变量:
function test() {
message = 'hi' // 没var,变成全局的
}
test()
console.log(message) // "hi"
不加 var 的全局变量不好维护,严格模式下还会报 ReferenceError,所以尽量别这么干。
声明多个变量可以用逗号隔开:
var message = 'hi',
found = false,
age = 18
这种写法合法且紧凑,但建议分开写:
var message = 'hi'
var found = false
var age = 18
分开写结构更清晰,特别在代码量大时,不容易漏看变量声明,还能方便加注释或调试。比如:
var message = 'hi' // 用户消息
var found = false // 是否找到
var age = 18 // 用户年龄
let 和 const
ES6 引入了 let 和 const,比 var 更现代。let 跟 var 类似,但有块级作用域:
if (true) {
let name = 'Alice'
}
console.log(name) // 报错:name is not defined
const 声明常量,不能改值,但对象内部属性可以变:
const age = 18
age = 20 // 报错:Assignment to constant
const user = { name: 'Bob' }
user.name = 'Alice' // 可以改,对象本身没变
用 let 和 const 能避免 var 的一些坑,比如作用域混乱,推荐优先使用。
数据类型
JS 有几种基本数据类型:
- String(字符串):用引号包裹,比如”hello”或’world’。
- Number(数字):整数或小数,比如 42、3.14。
- Boolean(布尔):只有 true 和 false。
- Undefined:未定义,默认值是 undefined。
- Null:空值,表示“啥也没有”。
可以用 typeof 检查类型:
console.log(typeof 'hi') // "string"
console.log(typeof 42) // "number"
console.log(typeof true) // "boolean"
console.log(typeof undefined) // "undefined"
console.log(typeof null) // "object"(历史遗留问题)
注意:null 返回”object”是个老 Bug,别被骗了。
运算符
JS 有常见的运算符:
- 算术:+(加)、-(减)、*(乘)、/(除)、%(取模):
let sum = 5 + 3 // 8
let mod = 10 % 3 // 1
- 比较:>(大于)、<(小于)、>=、<=、
==(等于)、===(严格等于):
console.log(5 == '5') // true,类型转换后相等
console.log(5 === '5') // false,类型不同
==会转换类型,===要求值和类型都一样,推荐用===。
逻辑:&&(与)、||(或)、!(非):
let a = true
let b = false
console.log(a && b) // false
console.log(a || b) // true
console.log(!a) // false
函数基础
函数是 JS 的核心,能封装代码复用。定义函数用 function:
function greet(name) {
return 'Hello, ' + name
}
调用时传参数:
console.log(greet('Alice')) // "Hello, Alice"
函数可以没返回值,默认返回 undefined:
function sayHi() {
console.log('Hi!')
}
sayHi() // "Hi!",返回undefined
简单又强大,适合处理重复逻辑。