JavaScript语法基础
语句和表达式
JavaScript程序由语句(statements)和表达式(expressions)组成:
// 语句:执行某个动作
let x = 5; // 声明语句
if (x > 0) { } // 条件语句
for (let i = 0; i < 10; i++) { } // 循环语句
// 表达式:产生值
5 + 3; // 算术表达式,结果为8
x > 0; // 比较表达式,结果为true或false
function() { return 42; }(); // 函数表达式,结果为42
分号和自动分号插入(ASI)
// 推荐:显式使用分号
let a = 1;
let b = 2;
console.log(a + b);
// JavaScript会自动插入分号,但可能导致意外结果
let c = 1
let d = 2
console.log(c + d)
// 危险的ASI示例
function getValue() {
return // ASI在这里插入分号
42; // 这行代码永远不会执行
}
console.log(getValue()); // undefined
// 正确写法
function getValue() {
return 42;
}
注释
// 单行注释
let x = 5; // 行末注释
/*
多行注释
可以跨越多行
*/
/**
* JSDoc注释
* 用于文档生成
* @param {number} a - 第一个参数
* @param {number} b - 第二个参数
* @returns {number} 两数之和
*/
function add(a, b) {
return a + b;
}
标识符和关键字
// 有效的标识符
let myVariable;
let _privateVar;
let $element;
let userName2;
let 中文变量; // 支持Unicode
// 无效的标识符
// let 2variable; // 不能以数字开头
// let my-variable; // 不能包含连字符
// let class; // 不能使用关键字
// JavaScript关键字(不能用作标识符)
// break, case, catch, class, const, continue, debugger, default, delete,
// do, else, export, extends, finally, for, function, if, import, in,
// instanceof, let, new, return, super, switch, this, throw, try, typeof,
// var, void, while, with, yield
数据类型详解
原始数据类型
Number类型
// 整数
let integer = 42;
let negative = -17;
let octal = 0o755; // 八进制
let hex = 0xFF; // 十六进制
let binary = 0b1010; // 二进制
// 浮点数
let float = 3.14;
let scientific = 2.5e6; // 2500000
let tiny = 1.23e-4; // 0.000123
// 特殊数值
let infinity = Infinity;
let negInfinity = -Infinity;
let notANumber = NaN;
// 数值检查
console.log(Number.isInteger(42)); // true
console.log(Number.isNaN(NaN)); // true
console.log(Number.isFinite(42)); // true
console.log(Number.isFinite(Infinity)); // false
// 数值转换
console.log(Number('123')); // 123
console.log(Number('123.45')); // 123.45
console.log(Number('abc')); // NaN
console.log(parseInt('123px')); // 123
console.log(parseFloat('123.45px')); // 123.45
// 数值精度问题
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false
// 解决精度问题
function isEqual(a, b, epsilon = Number.EPSILON) {
return Math.abs(a - b) < epsilon;
}
console.log(isEqual(0.1 + 0.2, 0.3)); // true
String类型
// 字符串字面量
let single = 'Hello';
let double = "World";
let template = `Hello, World!`;
// 字符串转义
let escaped = 'It\'s a beautiful day';
let newline = 'First line\nSecond line';
let tab = 'Column1\tColumn2';
let unicode = '\u4F60\u597D'; // "你好"
// 模板字符串
let name = 'Alice';
let age = 30;
let message = `Hello, my name is ${name} and I'm ${age} years old.`;
// 多行字符串
let multiline = `
This is a
multi-line
string.
`;
// 标签模板
function highlight(strings, ...values) {
return strings.reduce((result, string, i) => {
const value = values[i] ? `<mark>${values[i]}</mark>` : '';
return result + string + value;
}, '');
}
let highlighted = highlight`Name: ${name}, Age: ${age}`;
// 字符串方法
let str = 'JavaScript';
console.log(str.length); // 10
console.log(str.charAt(0)); // 'J'
console.log(str.charCodeAt(0)); // 74
console.log(str.indexOf('Script')); // 4
console.log(str.slice(0, 4)); // 'Java'
console.log(str.substring(0, 4)); // 'Java'
console.log(str.substr(0, 4)); // 'Java' (已废弃)
console.log(str.toLowerCase()); // 'javascript'
console.log(str.toUpperCase()); // 'JAVASCRIPT'
// 字符串搜索和替换
let text = 'The quick brown fox jumps over the lazy dog';
console.log(text.includes('fox')); // true
console.log(text.startsWith('The')); // true
console.log(text.endsWith('dog')); // true
console.log(text.replace('fox', 'cat')); // 替换第一个匹配
console.log(text.replaceAll('the', 'a')); // 替换所有匹配
// 字符串分割和连接
let csv = 'apple,banana,orange';
let fruits = csv.split(','); // ['apple', 'banana', 'orange']
let joined = fruits.join(' | '); // 'apple | banana | orange'
// 字符串填充
let num = '5';
console.log(num.padStart(3, '0')); // '005'
console.log(num.padEnd(3, '0')); // '500'
// 字符串修剪
let whitespace = ' hello world ';
console.log(whitespace.trim()); // 'hello world'
console.log(whitespace.trimStart()); // 'hello world '
console.log(whitespace.trimEnd()); // ' hello world'
Boolean类型
// 布尔字面量
let isTrue = true;
let isFalse = false;
// 布尔转换
console.log(Boolean(1)); // true
console.log(Boolean(0)); // false
console.log(Boolean('hello')); // true
console.log(Boolean('')); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
// 假值(Falsy values)
let falsyValues = [
false,
0,
-0,
0n, // BigInt零值
'', // 空字符串
null,
undefined,
NaN
];
falsyValues.forEach(value => {
console.log(`${value} is ${Boolean(value)}`);
});
// 真值(Truthy values)- 除假值外的所有值
let truthyValues = [
true,
1,
'hello',
[], // 空数组
{}, // 空对象
function() {}
];
// 逻辑运算符
let a = true;
let b = false;
console.log(a && b); // false (逻辑与)
console.log(a || b); // true (逻辑或)
console.log(!a); // false (逻辑非)
// 短路求值
let user = null;
let name = user && user.name; // undefined (不会报错)
let defaultName = name || 'Anonymous'; // 'Anonymous'
// 空值合并运算符(ES2020)
let value = null;
let defaultValue = value ?? 'default'; // 'default'
let zeroValue = 0;
let result = zeroValue ?? 'default'; // 0 (不同于 ||)
Undefined和Null
// undefined
let undeclaredVar;
console.log(undeclaredVar); // undefined
function noReturn() {
// 没有return语句
}
console.log(noReturn()); // undefined
let obj = { a: 1 };
console.log(obj.b); // undefined
// null
let intentionallyEmpty = null;
console.log(intentionallyEmpty); // null
// 类型检查
console.log(typeof undefined); // 'undefined'
console.log(typeof null); // 'object' (这是一个历史bug)
// 比较
console.log(undefined == null); // true (类型转换)
console.log(undefined === null); // false (严格比较)
// 检查undefined和null
function isNullOrUndefined(value) {
return value == null; // 同时检查null和undefined
}
function isUndefined(value) {
return value === undefined;
}
function isNull(value) {
return value === null;
}
Symbol类型(ES6)
// 创建Symbol
let sym1 = Symbol();
let sym2 = Symbol('description');
let sym3 = Symbol('description');
console.log(sym2 === sym3); // false (每个Symbol都是唯一的)
// Symbol作为对象属性
let obj = {};
let symKey = Symbol('key');
obj[symKey] = 'value';
console.log(obj[symKey]); // 'value'
console.log(Object.keys(obj)); // [] (Symbol属性不可枚举)
// 全局Symbol注册表
let globalSym1 = Symbol.for('global');
let globalSym2 = Symbol.for('global');
console.log(globalSym1 === globalSym2); // true
// 内置Symbol
let arr = [1, 2, 3];
console.log(arr[Symbol.iterator]); // 数组的迭代器
// 自定义迭代器
let iterableObj = {
data: [1, 2, 3],
[Symbol.iterator]() {
let index = 0;
let data = this.data;
return {
next() {
if (index < data.length) {
return { value: data[index++], done: false };
} else {
return { done: true };
}
}
};
}
};
for (let value of iterableObj) {
console.log(value); // 1, 2, 3
}
BigInt类型(ES2020)
// 创建BigInt
let bigInt1 = 123n;
let bigInt2 = BigInt(123);
let bigInt3 = BigInt('123456789012345678901234567890');
// BigInt运算
let a = 123n;
let b = 456n;
console.log(a + b); // 579n
console.log(a * b); // 56088n
console.log(a ** b); // 非常大的数
// BigInt和Number不能混合运算
// console.log(123n + 456); // TypeError
console.log(123n + BigInt(456)); // 579n
console.log(Number(123n) + 456); // 579
// 比较
console.log(123n === 123); // false
console.log(123n == 123); // true
console.log(123n > 122); // true
// 类型检查
console.log(typeof 123n); // 'bigint'
引用数据类型
Object类型
// 对象字面量
let person = {
name: 'Alice',
age: 30,
city: 'New York',
// 方法
greet() {
return `Hello, I'm ${this.name}`;
},
// 计算属性名
['full' + 'Name']: 'Alice Johnson'
};
// 属性访问
console.log(person.name); // 'Alice'
console.log(person['age']); // 30
console.log(person.greet()); // 'Hello, I'm Alice'
// 动态属性
let prop = 'city';
console.log(person[prop]); // 'New York'
// 属性操作
person.email = 'alice@example.com'; // 添加属性
delete person.city; // 删除属性
// 属性检查
console.log('name' in person); // true
console.log(person.hasOwnProperty('name')); // true
// 对象方法
let keys = Object.keys(person); // 获取所有键
let values = Object.values(person); // 获取所有值
let entries = Object.entries(person); // 获取键值对数组
// 对象合并
let defaults = { theme: 'dark', lang: 'en' };
let userPrefs = { theme: 'light' };
let settings = Object.assign({}, defaults, userPrefs);
// 或使用展开运算符
let settings2 = { ...defaults, ...userPrefs };
// 对象冻结和密封
let frozenObj = Object.freeze({ a: 1 });
// frozenObj.a = 2; // 严格模式下会报错
let sealedObj = Object.seal({ a: 1 });
sealedObj.a = 2; // 可以修改现有属性
// sealedObj.b = 3; // 不能添加新属性
Array类型
// 数组创建
let arr1 = [1, 2, 3, 4, 5];
let arr2 = new Array(5); // 创建长度为5的空数组
let arr3 = new Array(1, 2, 3); // [1, 2, 3]
let arr4 = Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']
let arr5 = Array.of(1, 2, 3); // [1, 2, 3]
// 数组访问和修改
let numbers = [1, 2, 3, 4, 5];
console.log(numbers[0]); // 1
console.log(numbers.length); // 5
numbers[5] = 6; // 添加元素
numbers.length = 3; // 截断数组
// 数组方法 - 修改原数组
let fruits = ['apple', 'banana'];
fruits.push('orange'); // 末尾添加
fruits.unshift('mango'); // 开头添加
let last = fruits.pop(); // 移除末尾元素
let first = fruits.shift(); // 移除开头元素
// splice方法
let colors = ['red', 'green', 'blue', 'yellow'];
colors.splice(1, 2, 'purple', 'pink'); // 从索引1开始删除2个,插入新元素
console.log(colors); // ['red', 'purple', 'pink', 'yellow']
// 数组方法 - 不修改原数组
let nums = [1, 2, 3, 4, 5];
let doubled = nums.map(n => n * 2); // [2, 4, 6, 8, 10]
let evens = nums.filter(n => n % 2 === 0); // [2, 4]
let sum = nums.reduce((acc, n) => acc + n, 0); // 15
let found = nums.find(n => n > 3); // 4
let index = nums.findIndex(n => n > 3); // 3
// 数组搜索
let animals = ['cat', 'dog', 'bird', 'cat'];
console.log(animals.indexOf('cat')); // 0
console.log(animals.lastIndexOf('cat')); // 3
console.log(animals.includes('dog')); // true
// 数组排序
let words = ['banana', 'apple', 'cherry'];
words.sort(); // 字典序排序
console.log(words); // ['apple', 'banana', 'cherry']
let numbers2 = [10, 5, 40, 25, 1000, 1];
numbers2.sort((a, b) => a - b); // 数值排序
console.log(numbers2); // [1, 5, 10, 25, 40, 1000]
// 数组连接和分割
let arr6 = [1, 2];
let arr7 = [3, 4];
let combined = arr6.concat(arr7); // [1, 2, 3, 4]
let spread = [...arr6, ...arr7]; // [1, 2, 3, 4]
let joined = arr6.join('-'); // '1-2'
// 多维数组
let matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
console.log(matrix[1][2]); // 6
// 数组解构
let [a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(a); // 1
console.log(b); // 2
console.log(rest); // [3, 4, 5]
Function类型
// 函数声明
function add(a, b) {
return a + b;
}
// 函数表达式
const multiply = function(a, b) {
return a * b;
};
// 箭头函数
const divide = (a, b) => a / b;
const square = x => x * x;
const greet = () => 'Hello!';
// 函数参数
function greetUser(name = 'Guest', greeting = 'Hello') {
return `${greeting}, ${name}!`;
}
// 剩余参数
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
// 函数作为参数
function operate(a, b, operation) {
return operation(a, b);
}
console.log(operate(5, 3, add)); // 8
console.log(operate(5, 3, multiply)); // 15
// 高阶函数
function createMultiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
// 立即执行函数表达式(IIFE)
(function() {
console.log('IIFE executed!');
})();
// 递归函数
function factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
// 函数属性和方法
function myFunction() {
console.log('Hello');
}
console.log(myFunction.name); // 'myFunction'
console.log(myFunction.length); // 0 (参数个数)
// call, apply, bind
function introduce() {
return `Hi, I'm ${this.name}`;
}
const person1 = { name: 'Alice' };
const person2 = { name: 'Bob' };
console.log(introduce.call(person1)); // 'Hi, I'm Alice'
console.log(introduce.apply(person2)); // 'Hi, I'm Bob'
const boundIntroduce = introduce.bind(person1);
console.log(boundIntroduce()); // 'Hi, I'm Alice'
类型转换
显式类型转换
// 转换为字符串
let num = 123;
let str1 = String(num); // '123'
let str2 = num.toString(); // '123'
let str3 = num + ''; // '123'
// 转换为数字
let str = '123';
let num1 = Number(str); // 123
let num2 = parseInt(str); // 123
let num3 = parseFloat(str); // 123
let num4 = +str; // 123
// parseInt的进制参数
console.log(parseInt('1010', 2)); // 10 (二进制)
console.log(parseInt('FF', 16)); // 255 (十六进制)
// 转换为布尔值
let bool1 = Boolean(1); // true
let bool2 = !!1; // true
隐式类型转换
// 字符串连接
console.log('5' + 3); // '53' (数字转为字符串)
console.log('5' + true); // '5true'
console.log('5' + null); // '5null'
// 数学运算
console.log('5' - 3); // 2 (字符串转为数字)
console.log('5' * 2); // 10
console.log('5' / 2); // 2.5
console.log('5' % 2); // 1
// 比较运算
console.log('5' == 5); // true (类型转换)
console.log('5' === 5); // false (严格比较)
console.log(null == undefined); // true
console.log(null === undefined); // false
// 逻辑运算中的转换
if ('hello') { // 'hello'转为true
console.log('Truthy');
}
if (0) { // 0转为false
console.log('This won\'t run');
}
// 对象转换
let obj = {
valueOf() {
return 42;
},
toString() {
return 'object';
}
};
console.log(obj + 1); // 43 (调用valueOf)
console.log(obj + ''); // '42' (调用valueOf)
console.log(String(obj)); // 'object' (调用toString)
运算符
算术运算符
let a = 10;
let b = 3;
console.log(a + b); // 13 (加法)
console.log(a - b); // 7 (减法)
console.log(a * b); // 30 (乘法)
console.log(a / b); // 3.333... (除法)
console.log(a % b); // 1 (取余)
console.log(a ** b); // 1000 (幂运算,ES2016)
// 一元运算符
console.log(+a); // 10 (一元加)
console.log(-a); // -10 (一元减)
console.log(++a); // 11 (前置递增)
console.log(a++); // 11 (后置递增,返回原值)
console.log(--a); // 11 (前置递减)
console.log(a--); // 11 (后置递减,返回原值)
比较运算符
let x = 5;
let y = '5';
console.log(x == y); // true (相等,允许类型转换)
console.log(x === y); // false (严格相等,不允许类型转换)
console.log(x != y); // false (不等)
console.log(x !== y); // true (严格不等)
console.log(x > 3); // true (大于)
console.log(x < 10); // true (小于)
console.log(x >= 5); // true (大于等于)
console.log(x <= 5); // true (小于等于)
// 特殊比较
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true
console.log(+0 === -0); // true
console.log(Object.is(+0, -0)); // false
逻辑运算符
let a = true;
let b = false;
console.log(a && b); // false (逻辑与)
console.log(a || b); // true (逻辑或)
console.log(!a); // false (逻辑非)
// 短路求值
let user = { name: 'Alice' };
let name = user && user.name; // 'Alice'
let defaultName = name || 'Anonymous'; // 'Alice'
// 空值合并运算符(ES2020)
let value = null;
let result = value ?? 'default'; // 'default'
let zero = 0;
let result2 = zero ?? 'default'; // 0 (不同于||运算符)
// 可选链运算符(ES2020)
let user2 = { profile: { name: 'Bob' } };
console.log(user2?.profile?.name); // 'Bob'
console.log(user2?.profile?.age); // undefined
console.log(user2?.nonexistent?.name); // undefined (不会报错)
赋值运算符
let x = 10;
x += 5; // x = x + 5; 结果: 15
x -= 3; // x = x - 3; 结果: 12
x *= 2; // x = x * 2; 结果: 24
x /= 4; // x = x / 4; 结果: 6
x %= 4; // x = x % 4; 结果: 2
x **= 3; // x = x ** 3; 结果: 8
// 逻辑赋值运算符(ES2021)
let a = null;
a ||= 'default'; // a = a || 'default'; 结果: 'default'
let b = 'existing';
b ||= 'default'; // b保持'existing'
let c = null;
c ??= 'default'; // c = c ?? 'default'; 结果: 'default'
let d = true;
d &&= false; // d = d && false; 结果: false
位运算符
let a = 5; // 二进制: 101
let b = 3; // 二进制: 011
console.log(a & b); // 1 (按位与: 001)
console.log(a | b); // 7 (按位或: 111)
console.log(a ^ b); // 6 (按位异或: 110)
console.log(~a); // -6 (按位非)
console.log(a << 1); // 10 (左移: 1010)
console.log(a >> 1); // 2 (右移: 10)
console.log(a >>> 1); // 2 (无符号右移)
// 位运算的实际应用
// 检查奇偶性
function isEven(n) {
return (n & 1) === 0;
}
// 交换两个数(不使用临时变量)
function swap(a, b) {
a = a ^ b;
b = a ^ b;
a = a ^ b;
return [a, b];
}
本章总结
本章详细介绍了JavaScript的基本语法和数据类型:
- 语法基础:学习了语句、表达式、注释、标识符等基本概念
- 原始类型:掌握了Number、String、Boolean、Undefined、Null、Symbol、BigInt等类型
- 引用类型:深入了解了Object、Array、Function等复杂类型
- 类型转换:理解了显式和隐式类型转换的规则
- 运算符:学习了各种运算符的使用和优先级
这些基础知识是JavaScript编程的核心,为后续学习函数、对象、异步编程等高级特性奠定了坚实的基础。
下一章我们将学习JavaScript的控制结构和流程控制。