JavaScript极简入门
本文面向具有一定编程基础(如 Java、Python 等)的中高级开发工程师,快速介绍 JavaScript 的核心语法和特性。如果你已经熟悉其他编程语言,这篇文章将帮助你快速上手 JavaScript。
# 一、JavaScript 简介
JavaScript(通常简称 JS)是一门高级的、解释型的、动态类型的编程语言。最初设计用于网页交互,现在已经成为全栈开发的主流语言之一(Node.js)。
# 关键特性
- 动态类型:变量类型在运行时确定
- 弱类型:类型之间可以隐式转换
- 原型继承:基于原型链而非传统的类继承(ES6 引入
class语法糖) - 函数是一等公民:函数可以作为值传递、赋值、返回
- 事件驱动:异步编程模型,适合 I/O 密集型任务
# 运行环境
- 浏览器:通过
<script>标签引入,操作 DOM、处理用户交互 - Node.js:服务端运行环境,用于构建后端服务、工具链等
# 二、变量声明
JavaScript 有三种变量声明方式:
# var(不推荐)
var x = 10;
var x = 20; // 可以重复声明
var 存在函数作用域和变量提升问题,容易引发 bug,现代开发中应避免使用。
# let(块级作用域)
let count = 1;
if (true) {
let count = 2; // 块级作用域,不影响外层
console.log(count); // 2
}
console.log(count); // 1
let 是块级作用域,不能重复声明。
# const(常量)
const PI = 3.14159;
// PI = 3.14; // 错误:不能重新赋值
const user = { name: 'Alice' };
user.name = 'Bob'; // 正确:对象属性可以修改
// user = {}; // 错误:不能重新赋值引用
const 声明常量,但对象和数组的内容可以修改,只是引用不能改变。
# 最佳实践
- 优先使用
const,除非需要重新赋值 - 需要重新赋值时使用
let - 避免使用
var
# 三、数据类型
# 基本类型(Primitive Types)
// 1. Number(数字)
let num = 42;
let float = 3.14;
let negative = -10;
let infinity = Infinity;
let notANumber = NaN; // Not a Number
// 2. String(字符串)
let str1 = 'single quotes';
let str2 = "double quotes";
let str3 = `template string with ${num}`; // 模板字符串
// 3. Boolean(布尔)
let isTrue = true;
let isFalse = false;
// 4. Undefined(未定义)
let x;
console.log(x); // undefined
// 5. Null(空值)
let y = null;
// 6. Symbol(ES6,唯一标识符)
let sym = Symbol('description');
// 7. BigInt(ES2020,大整数)
let bigNum = 9007199254740991n;
# 引用类型(Reference Types)
// 1. Object(对象)
let person = {
name: 'Alice',
age: 30,
greet: function() {
console.log(`Hello, I'm ${this.name}`);
}
};
// 2. Array(数组)
let numbers = [1, 2, 3, 4, 5];
let mixed = [1, 'two', { three: 3 }, [4]];
// 3. Function(函数)
function add(a, b) {
return a + b;
}
// 4. Date(日期)
let now = new Date();
// 5. RegExp(正则表达式)
let pattern = /\d+/g;
# 类型检测
typeof 42; // "number"
typeof 'hello'; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object"(历史遗留问题)
typeof {}; // "object"
typeof []; // "object"
typeof function(){}; // "function"
// 更准确的类型检测
Array.isArray([]); // true
null === null; // true(使用严格相等)
Object.prototype.toString.call([]); // "[object Array]"
# 四、运算符
# 算术运算符
let a = 10, b = 3;
console.log(a + b); // 13
console.log(a - b); // 7
console.log(a * b); // 30
console.log(a / b); // 3.3333...
console.log(a % b); // 1(取余)
console.log(a ** b); // 1000(幂运算,ES2016)
# 比较运算符
// == vs ===
console.log(5 == '5'); // true(类型转换后比较)
console.log(5 === '5'); // false(严格相等,不转换类型)
console.log(null == undefined); // true
console.log(null === undefined); // false
// 最佳实践:始终使用 === 和 !==
console.log(10 !== '10'); // true
# 逻辑运算符
let x = true, y = false;
console.log(x && y); // false(与)
console.log(x || y); // true(或)
console.log(!x); // false(非)
// 短路求值
let result = someValue || 'default'; // 如果 someValue 为假值,使用默认值
// 空值合并运算符(ES2020)
let value = null ?? 'default'; // 'default'(仅 null/undefined 使用默认值)
# 自增/自减
let count = 0;
count++; // 后增,count = 1
++count; // 先增,count = 2
count--; // 后减,count = 1
--count; // 先减,count = 0
# 五、控制流
# 条件语句
// if-else
let score = 85;
if (score >= 90) {
console.log('A');
} else if (score >= 80) {
console.log('B');
} else {
console.log('C');
}
// 三元运算符
let grade = score >= 60 ? 'Pass' : 'Fail';
// switch
let day = 3;
switch (day) {
case 1:
console.log('Monday');
break;
case 2:
console.log('Tuesday');
break;
default:
console.log('Other day');
}
# 循环语句
// for 循环
for (let i = 0; i < 5; i++) {
console.log(i);
}
// while 循环
let count = 0;
while (count < 5) {
console.log(count);
count++;
}
// do-while 循环
let num = 0;
do {
console.log(num);
num++;
} while (num < 5);
// for...of(遍历可迭代对象,如数组)
let arr = [1, 2, 3];
for (let value of arr) {
console.log(value); // 1, 2, 3
}
// for...in(遍历对象属性)
let obj = { a: 1, b: 2 };
for (let key in obj) {
console.log(key, obj[key]); // a 1, b 2
}
# 六、函数
# 函数声明
function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // 5
# 函数表达式
const multiply = function(a, b) {
return a * b;
};
console.log(multiply(2, 3)); // 6
# 箭头函数(ES6)
// 基本语法
const subtract = (a, b) => a - b;
// 多行函数体
const divide = (a, b) => {
if (b === 0) throw new Error('Division by zero');
return a / b;
};
// 单参数可以省略括号
const square = x => x * x;
// 无参数
const greet = () => console.log('Hello');
注意:箭头函数没有自己的 this,继承外层作用域的 this。详见关于this关键字的魔幻现实。
# 默认参数
function greet(name = 'Guest') {
console.log(`Hello, ${name}`);
}
greet(); // Hello, Guest
greet('Alice'); // Hello, Alice
# 剩余参数
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
# 高阶函数
// 函数作为参数
function operate(a, b, operation) {
return operation(a, b);
}
console.log(operate(5, 3, (x, y) => x + y)); // 8
// 函数作为返回值
function multiplier(factor) {
return x => x * factor;
}
const double = multiplier(2);
console.log(double(5)); // 10
# 七、对象
# 对象字面量
const person = {
name: 'Alice',
age: 30,
greet() { // 方法简写
console.log(`Hello, I'm ${this.name}`);
}
};
// 访问属性
console.log(person.name); // 点符号
console.log(person['age']); // 方括号
// 动态属性名
const key = 'email';
const user = {
[key]: 'alice@example.com'
};
# 对象解构
const person = { name: 'Bob', age: 25, city: 'NYC' };
// 解构赋值
const { name, age } = person;
console.log(name, age); // Bob 25
// 重命名
const { name: userName, age: userAge } = person;
// 默认值
const { country = 'USA' } = person;
# 扩展运算符
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
// 对象合并
const merged = { ...obj1, ...obj2 };
console.log(merged); // { a: 1, b: 2, c: 3, d: 4 }
// 浅拷贝
const clone = { ...obj1 };
# 对象方法
const obj = { a: 1, b: 2, c: 3 };
Object.keys(obj); // ['a', 'b', 'c']
Object.values(obj); // [1, 2, 3]
Object.entries(obj); // [['a', 1], ['b', 2], ['c', 3]]
// 属性检查
obj.hasOwnProperty('a'); // true
'a' in obj; // true
# 八、数组
# 数组创建
const arr1 = [1, 2, 3];
const arr2 = new Array(5); // 长度为 5 的空数组
const arr3 = Array.of(1, 2, 3); // [1, 2, 3]
# 常用数组方法
let numbers = [1, 2, 3, 4, 5];
// 添加/删除元素
numbers.push(6); // 末尾添加
numbers.pop(); // 末尾删除
numbers.unshift(0); // 开头添加
numbers.shift(); // 开头删除
// 查找元素
numbers.indexOf(3); // 2(索引)
numbers.includes(4); // true
numbers.find(n => n > 3); // 4(第一个匹配)
numbers.findIndex(n => n > 3); // 3
// 数组切片
numbers.slice(1, 3); // [2, 3](不修改原数组)
numbers.splice(1, 2); // 删除索引 1 开始的 2 个元素(修改原数组)
// 数组拼接
[1, 2].concat([3, 4]); // [1, 2, 3, 4]
# 高阶数组方法
const numbers = [1, 2, 3, 4, 5];
// map(映射)
const doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// filter(过滤)
const evens = numbers.filter(n => n % 2 === 0);
console.log(evens); // [2, 4]
// reduce(归约)
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(sum); // 15
// forEach(遍历)
numbers.forEach((n, index) => {
console.log(`${index}: ${n}`);
});
// some(任意满足)
const hasEven = numbers.some(n => n % 2 === 0);
console.log(hasEven); // true
// every(全部满足)
const allPositive = numbers.every(n => n > 0);
console.log(allPositive); // true
# 数组解构
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
// 交换变量
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b); // 2 1
# 扩展运算符
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
// 数组合并
const merged = [...arr1, ...arr2];
// 数组拷贝
const copy = [...arr1];
// 将类数组转为数组
const args = [...arguments];
# 九、字符串
# 字符串方法
const str = 'Hello World';
str.length; // 11
str.toUpperCase(); // 'HELLO WORLD'
str.toLowerCase(); // 'hello world'
str.indexOf('World'); // 6
str.includes('Hello'); // true
str.startsWith('Hello'); // true
str.endsWith('World'); // true
str.slice(0, 5); // 'Hello'
str.substring(6, 11); // 'World'
str.split(' '); // ['Hello', 'World']
str.trim(); // 去除首尾空格
str.repeat(2); // 'Hello WorldHello World'
# 模板字符串
const name = 'Alice';
const age = 30;
// 字符串插值
const message = `My name is ${name} and I'm ${age} years old.`;
// 多行字符串
const multiline = `
Line 1
Line 2
Line 3
`;
// 标签模板
function highlight(strings, ...values) {
return strings.reduce((result, str, i) => {
return result + str + (values[i] ? `<b>${values[i]}</b>` : '');
}, '');
}
const html = highlight`Name: ${name}, Age: ${age}`;
# 十、类与继承
# ES6 类
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, I'm ${this.name}`);
}
// 静态方法
static species() {
return 'Homo Sapiens';
}
// Getter
get info() {
return `${this.name}, ${this.age}`;
}
// Setter
set age(value) {
if (value < 0) throw new Error('Age cannot be negative');
this._age = value;
}
}
const alice = new Person('Alice', 30);
alice.greet(); // Hello, I'm Alice
console.log(Person.species()); // Homo Sapiens
# 继承
class Student extends Person {
constructor(name, age, studentId) {
super(name, age); // 调用父类构造函数
this.studentId = studentId;
}
// 重写方法
greet() {
super.greet(); // 调用父类方法
console.log(`My student ID is ${this.studentId}`);
}
}
const bob = new Student('Bob', 20, 'S12345');
bob.greet();
// Hello, I'm Bob
// My student ID is S12345
# 原型链(传统方式)
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a sound`);
};
function Dog(name, breed) {
Animal.call(this, name); // 继承属性
this.breed = breed;
}
// 继承方法
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
console.log('Woof!');
};
const dog = new Dog('Rex', 'Labrador');
dog.speak(); // Rex makes a sound
dog.bark(); // Woof!
# 十一、异步编程
# 回调函数
function fetchData(callback) {
setTimeout(() => {
callback('Data received');
}, 1000);
}
fetchData((data) => {
console.log(data); // Data received
});
回调函数容易导致回调地狱(callback hell),代码可读性差。
# Promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve('Success!');
} else {
reject('Error!');
}
}, 1000);
});
promise
.then(result => console.log(result))
.catch(error => console.error(error))
.finally(() => console.log('Done'));
# Promise 链式调用
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
console.log(data);
return fetch('https://api.example.com/other');
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
# async/await(ES2017)
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
return data;
} catch (error) {
console.error('Error:', error);
}
}
fetchData();
# Promise 静态方法
// Promise.all(所有成功才成功)
Promise.all([promise1, promise2, promise3])
.then(results => console.log(results));
// Promise.race(第一个完成即返回)
Promise.race([promise1, promise2])
.then(result => console.log(result));
// Promise.allSettled(等待所有完成,不管成功失败)
Promise.allSettled([promise1, promise2])
.then(results => console.log(results));
// Promise.any(任意一个成功即成功)
Promise.any([promise1, promise2])
.then(result => console.log(result));
# 十二、模块化
# ES6 模块(推荐)
// math.js
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export default class Calculator {
multiply(a, b) {
return a * b;
}
}
// main.js
import Calculator, { PI, add } from './math.js';
console.log(PI); // 3.14159
console.log(add(2, 3)); // 5
const calc = new Calculator();
console.log(calc.multiply(2, 3)); // 6
// 重命名导入
import { add as sum } from './math.js';
// 导入所有
import * as math from './math.js';
console.log(math.PI);
# CommonJS(Node.js)
// math.js
const PI = 3.14159;
function add(a, b) {
return a + b;
}
module.exports = { PI, add };
// main.js
const { PI, add } = require('./math.js');
console.log(PI);
console.log(add(2, 3));
# 十三、错误处理
# try-catch
try {
const result = riskyOperation();
console.log(result);
} catch (error) {
console.error('Error:', error.message);
} finally {
console.log('Cleanup');
}
# 抛出错误
function divide(a, b) {
if (b === 0) {
throw new Error('Division by zero');
}
return a / b;
}
try {
divide(10, 0);
} catch (error) {
console.error(error.message); // Division by zero
}
# 自定义错误
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
function validateAge(age) {
if (age < 0) {
throw new ValidationError('Age cannot be negative');
}
}
try {
validateAge(-5);
} catch (error) {
if (error instanceof ValidationError) {
console.error('Validation failed:', error.message);
}
}
# 十四、常用内置对象
# Math
Math.PI; // 3.141592653589793
Math.abs(-5); // 5
Math.ceil(4.2); // 5(向上取整)
Math.floor(4.8); // 4(向下取整)
Math.round(4.5); // 5(四舍五入)
Math.max(1, 2, 3); // 3
Math.min(1, 2, 3); // 1
Math.random(); // [0, 1) 随机数
Math.sqrt(16); // 4(平方根)
Math.pow(2, 3); // 8(2^3)
# Date
const now = new Date();
now.getFullYear(); // 2025
now.getMonth(); // 0-11(0 表示 1 月)
now.getDate(); // 1-31
now.getDay(); // 0-6(0 表示周日)
now.getHours(); // 0-23
now.getMinutes(); // 0-59
now.getSeconds(); // 0-59
now.getTime(); // 时间戳(毫秒)
// 日期格式化
now.toISOString(); // '2025-11-03T07:00:00.000Z'
now.toLocaleDateString(); // '2025/11/3'
# JSON
const obj = { name: 'Alice', age: 30 };
// 序列化
const json = JSON.stringify(obj);
console.log(json); // '{"name":"Alice","age":30}'
// 反序列化
const parsed = JSON.parse(json);
console.log(parsed.name); // Alice
# Set(集合)
const set = new Set([1, 2, 3, 3, 4]);
console.log(set); // Set { 1, 2, 3, 4 }
set.add(5);
set.has(3); // true
set.delete(2);
set.size; // 4
set.clear();
// 数组去重
const unique = [...new Set([1, 2, 2, 3])];
# Map(映射)
const map = new Map();
map.set('name', 'Alice');
map.set('age', 30);
map.get('name'); // 'Alice'
map.has('age'); // true
map.delete('age');
map.size; // 1
map.clear();
// 遍历
for (let [key, value] of map) {
console.log(key, value);
}
# 十五、正则表达式
# 基本语法
const pattern1 = /hello/i; // 字面量,i 表示忽略大小写
const pattern2 = new RegExp('hello', 'i'); // 构造函数
// 测试匹配
pattern1.test('Hello World'); // true
// 查找匹配
const str = 'The price is $100';
const match = str.match(/\d+/);
console.log(match[0]); // '100'
// 全局匹配
const matches = str.match(/\d/g);
console.log(matches); // ['1', '0', '0']
// 替换
const newStr = str.replace(/\d+/, '200');
console.log(newStr); // 'The price is $200'
# 常用模式
/\d+/ // 一个或多个数字
/\w+/ // 一个或多个单词字符(字母、数字、下划线)
/\s+/ // 一个或多个空白字符
/^hello/ // 以 hello 开头
/world$/ // 以 world 结尾
/[a-z]/ // 任意小写字母
/[0-9]/ // 任意数字
/(abc|def)/ // abc 或 def
/a{2,4}/ // 2 到 4 个 a
# 十六、严格模式
在文件或函数开头添加 'use strict'; 启用严格模式:
'use strict';
// 1. 禁止未声明变量
x = 10; // 错误:x is not defined
// 2. 禁止删除不可删除的属性
delete Object.prototype; // 错误
// 3. 函数参数名不能重复
function sum(a, a, c) { // 错误
return a + a + c;
}
// 4. 禁止八进制字面量
const num = 010; // 错误
// 5. this 在函数中为 undefined
function test() {
console.log(this); // undefined(非严格模式为全局对象)
}
test();
# 十七、常见陷阱与最佳实践
# 类型转换陷阱
'5' + 3; // '53'(字符串拼接)
'5' - 3; // 2(数字减法)
true + 1; // 2
false + 1; // 1
[] + []; // ''(空字符串)
[] + {}; // '[object Object]'
{} + []; // 0(取决于上下文)
# 相等性比较
// 使用 === 而非 ==
[] == false; // true(类型转换)
[] === false; // false(推荐)
// NaN 比较
NaN === NaN; // false
Number.isNaN(NaN); // true(推荐)
# 浮点数精度
0.1 + 0.2; // 0.30000000000000004(精度问题)
// 解决方案:使用整数运算或库(如 decimal.js)
(0.1 * 10 + 0.2 * 10) / 10; // 0.3
# 对象/数组比较
[] === []; // false(不同引用)
{} === {}; // false
// 深度比较需要自定义函数或库(如 Lodash)
# 变量提升
console.log(x); // undefined(var 声明提升)
var x = 10;
// 等价于
var x;
console.log(x);
x = 10;
# 最佳实践
- 使用
const和let,避免var - 始终使用
===和!== - 启用严格模式
'use strict'; - 使用箭头函数避免
this问题 - 使用模板字符串而非字符串拼接
- 使用解构赋值简化代码
- 使用
async/await处理异步操作 - 避免全局变量污染
- 使用 ESLint 等工具检查代码质量
# 十八、总结
JavaScript 是一门灵活且强大的语言,掌握以下核心概念即可快速上手:
- 变量声明:优先使用
const,需要重新赋值时使用let - 数据类型:7 种基本类型 + 引用类型
- 函数:箭头函数、高阶函数、
this绑定 - 对象与数组:解构、扩展运算符、高阶方法
- 类与继承:ES6 类语法、原型链
- 异步编程:Promise、
async/await - 模块化:ES6 模块、CommonJS
对于有其他语言基础的开发者,重点关注 JavaScript 的动态类型、原型继承、异步编程、this 绑定等特性,避免常见陷阱。
更多高级主题(如闭包、事件循环、内存管理等),可参考本博客的其他文章。DOM 和浏览器 API 部分,将在"浏览器与 Web API"专题中详细介绍。
祝你变得更强!
编辑 (opens new window)
上次更新: 2025/11/07