目录
一、声明变量
(1)let
(2)const
(3)var
var、let 和 const 的作用域差异
二、数据类型
(1)基本类型
undefined和null
String
模板字符串拼接:
number和bigint
字符串转换为整数 :
boolean
symbol
二、对象类型
(1)Function函数
1.函数声明
2.函数表达式
3.箭头函数
4.匿名函数
函数作用域
闭包
(2)Array数组
常用数组方法
1.添加/删除元素
2.合并/拼接数组
3.查找元素
4.遍历数组
5.排序和反转
6.其他实用方法
7. ES6+ 新增数组特性
1.扩展运算符
2. 解构赋值
3.Array.from()
(3)Object对象
创建对象
访问属性
添加/修改属性
删除属性
常用静态方法
对象实例方法
原型与继承
原型基础
更规范的继承方式
构造函数与原型
ES6+ 对象新特性
属性简写
计算属性名
对象解构
扩展运算符
对象与JSON
一、声明变量
(1)let
- let声明的变量可以多次赋值。
(2)const
- const修饰的值叫常量,只能赋值一次。
(3)var
- var声明的变量可以多次赋值。
var、let 和 const 的作用域差异
-
var:函数作用域
- 在函数内部声明的变量只能在函数内部访问
- 没有块级作用域
-
let/const:块级作用域
- 在 {} 块中声明的变量只能在该块中访问
- 解决了 var 的变量提升和重复声明问题
function varExample() {if (true) {var x = 10;let y = 20;}console.log(x); // 10 (var 没有块级作用域)console.log(y); // 报错:y is not defined (let 有块级作用域)
}varExample();
二、数据类型
(1)基本类型
undefined和null
undefined表示变量已被声明,但尚未被赋值。也就是说,变量存在,但没有具体的值。
-
变量声明后未赋值时,默认值为
undefined
。 -
如果函数没有返回值,那么它的返回值默认也是
undefined
。 -
如果访问对象中不存在的属性,其值也是
undefined
。let a; // 声明变量 a,未赋值 console.log(a); // 输出:undefinedfunction test() {// 没有返回值 } console.log(test()); // 输出:undefinedconst obj = {}; console.log(obj.property); // 输出:undefined
null表示“空值”或“无对象”。
-
明确表示变量的值为空,而不是未赋值。
-
在类型检查中,
null
是一个独立的类型,即null
的类型是object
总结:
-
undefined
表示变量未被赋值,是一个“未定义”的状态。 -
null
表示变量被明确赋值为空,是一个“空值”或“无对象”的状态。
String
字符串是由字符组成的序列,用于表示文本数据。在 JavaScript 中,字符串可以用单引号('
)、双引号("
)或反引号(`
)来定义。
let singleQuoted = 'Hello, world!';
let doubleQuoted = "Hello, world!";
let backtickQuoted = `Hello, world!`;console.log(singleQuoted); // 输出:Hello, world!
console.log(doubleQuoted); // 输出:Hello, world!
console.log(backtickQuoted); // 输出:Hello, world!
传统字符串拼接:
let name = "Alice";
let age = 30;
let greeting = "Hello, " + name + "! You are " + age + " years old.";
console.log(greeting); // 输出:Hello, Alice! You are 30 years old.
模板字符串拼接:
(模板字符串是 ES6 的新特性)
模板字符串(Template Literals)是 ES6 引入的一种新的字符串表示方式,使用反引号(`
)定义,并支持嵌入表达式和多行字符串。
let name = "Alice";
let age = 30;
let greeting = `Hello, ${name}! You are ${age} years old.`;
console.log(greeting); // 输出:Hello, Alice! You are 30 years old.
number和bigint
Number
类型基于 IEEE 754 标准的双精度浮点数表示,因此可以表示小数。可以表示的数值范围是 -2^53 + 1
到 2^53 - 1。
由于 Number
是基于浮点数表示的,因此在处理大整数或高精度计算时可能会出现精度问题。
console.log(0.1 + 0.2); // 输出:0.30000000000000004
console.log(9007199254740991 + 1); // 输出:9007199254740992
console.log(9007199254740992 + 1); // 输出:9007199254740992(精度丢失)
字符串转换为整数 :
1.parseInt
console.log(parseInt("12345")); // 输出:12345
console.log(parseInt("123.45")); // 输出:123(忽略小数部分)
console.log(parseInt("123abc")); // 输出:123(忽略非数字部分)
console.log(parseInt("abc123")); // 输出:NaN(开头不是数字)
2.Number
构造函数
console.log(Number("123.45")); // 输出:123.45
console.log(Number("123abc")); // 输出:NaN
3.一元加号运算符
console.log(+ "123.45"); // 输出:123.45
console.log(+ "123abc"); // 输出:NaN
BigInt
是 ES2020 引入的一种新的数值类型,用于表示任意大小的整数。BigInt
可以表示任意大小的整数,没有上限。BigInt
保证整数的精确表示,不会出现精度问题。BigInt
字面量以 n
结尾,例如 123n。BigInt
支持基本的算术运算,但不能与 Number
类型直接进行运算,需要显式转换。
// Number
let num1 = 12345678901234567890;
let num2 = 12345678901234567890;
console.log(num1 + num2); // 输出:24691357802469135780,但可能会有精度问题// BigInt
let bigInt1 = 12345678901234567890n;
let bigInt2 = 12345678901234567890n;
console.log(bigInt1 + bigInt2); // 输出:24691357802469135780n,精确无误
boolean
在 JavaScript 中,truthy 和 falsy 是两个非常重要的概念,用于描述值在布尔上下文中的表现。这些概念在条件语句(如 if
、while
等)和逻辑运算中非常重要。
falsy:false、0、-0、""(空字符串)、null、undefined、NaN
truthy:true、1、{}(空对象)、[](空数组)等。
symbol
在 JavaScript 中,Symbol
是一种原始数据类型,用于表示唯一的、不可变的值。Symbol
是 ES6(ECMAScript 2015)引入的,旨在解决对象属性名称冲突的问题,并提供一种更安全的方式来定义对象的属性。
二、对象类型
(1)Function函数
函数本质上是对象。这使得函数具有对象的特性,例如可以拥有属性和方法,可以作为变量赋值,可以作为参数传递,也可以作为返回值。这种特性使得 JavaScript 的函数非常强大和灵活。
1.函数声明
function greet(name) {return `Hello, ${name}!`;
}console.log(greet("Alice")); // 输出:Hello, Alice!
2.函数表达式
const greet = function(name) {return `Hello, ${name}!`;
};console.log(greet("Bob")); // 输出:Hello, Bob!
3.箭头函数
ES6 引入了箭头函数(Arrow Function),它是一种更简洁的匿名函数语法。箭头函数省略了 function
关键字,并且可以省略花括号和 return
关键字(如果函数体只有一条语句)。
const greet = (name) => `Hello, ${name}!`;console.log(greet("Charlie")); // 输出:Hello, Charlie!
4.匿名函数
匿名函数也经常被用作高阶函数的参数,例如 map
、filter
和 reduce
。
const numbers = [1, 2, 3, 4, 5];
const squared = numbers.map(function(num) {return num * num;
});console.log(squared); // 输出:[1, 4, 9, 16, 25]
函数作用域
- 函数作用域:在函数内部声明的变量只能在函数内部访问
- 局部变量:函数内部声明的变量
- 全局变量:函数外部声明的变量
JavaScript 使用作用域链来解析变量:
- 首先在当前函数作用域查找
- 如果找不到,向上一级作用域查找
- 直到全局作用域
- 如果全局作用域也没有,则报错
var a = 1;function outer() {var b = 2;function inner() {var c = 3;console.log(a + b + c); // 6 (可以访问所有外层变量)}inner();
}outer();
闭包
闭包是指一个函数能够记住并访问其词法作用域,即使该函数在其词法作用域之外执行。
简单来说,闭包让函数可以"记住"它被创建时的环境,即使这个函数在创建它的环境之外被调用。
function outer() {let count = 0; // 外部函数的局部变量function inner() {count++; // 内部函数访问外部函数的变量console.log(count);}return inner; // 返回内部函数
}const counter = outer();
counter(); // 1
counter(); // 2
counter(); // 3
在这个例子中,inner
函数就是一个闭包,它可以访问 outer
函数的 count
变量,即使 outer
函数已经执行完毕
闭包的特点
1.记忆环境:闭包会记住创建时的词法环境
2.持久性:闭包中的变量会一直存在,不会被垃圾回收
3.私有性:可以创建私有变量和方法
(2)Array数组
常用数组方法
1.添加/删除元素
方法 | 描述 | 返回值 | 是否修改原数组 |
---|---|---|---|
push() | 末尾添加一个或多个元素 | 新长度 | 是 |
pop() | 删除最后一个元素 | 被删除元素 | 是 |
unshift() | 开头添加一个或多个元素 | 新长度 | 是 |
shift() | 删除第一个元素 | 被删除元素 | 是 |
let arr = [1, 2, 3];arr.push(4); // [1, 2, 3, 4]
arr.pop(); // [1, 2, 3]
arr.unshift(0); // [0, 1, 2, 3]
arr.shift(); // [1, 2, 3]
2.合并/拼接数组
// concat() - 合并数组(不修改原数组)
let arr1 = [1, 2];
let arr2 = [3, 4];
let combined = arr1.concat(arr2); // [1, 2, 3, 4]// splice() - 强大的数组修改方法(修改原数组)
let fruits = ['Apple', 'Banana', 'Orange'];
fruits.splice(1, 1, 'Mango', 'Peach');
// 从索引1开始,删除1个元素,插入'Mango'和'Peach'
// 结果: ['Apple', 'Mango', 'Peach', 'Orange']
3.查找元素
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];// indexOf() - 查找元素首次出现的位置
console.log(numbers.indexOf(3)); // 2// lastIndexOf() - 查找元素最后一次出现的位置
console.log(numbers.lastIndexOf(3)); // 6// includes() - 检查是否包含某元素
console.log(numbers.includes(5)); // true// find() - 查找第一个符合条件的元素
let found = numbers.find(item => item > 3); // 4// findIndex() - 查找第一个符合条件的元素索引
let foundIndex = numbers.findIndex(item => item > 3); // 3
4.遍历数组
let fruits = ['Apple', 'Banana', 'Orange'];// forEach() - 遍历数组
fruits.forEach(function(item, index) {console.log(index, item);
});// map() - 映射新数组
let lengths = fruits.map(fruit => fruit.length); // [5, 6, 6]// filter() - 过滤数组
let longFruits = fruits.filter(fruit => fruit.length > 5); // ['Banana', 'Orange']// reduce() - 累积计算
let numbers = [1, 2, 3, 4];
let sum = numbers.reduce((total, num) => total + num, 0); // 10
5.排序和反转
let numbers = [3, 1, 4, 2, 5];// sort() - 排序(修改原数组)
numbers.sort(); // [1, 2, 3, 4, 5]// 自定义排序
let scores = [88, 95, 70, 92];
scores.sort((a, b) => b - a); // 降序排序 [95, 92, 88, 70]// reverse() - 反转数组(修改原数组)
numbers.reverse(); // [5, 4, 3, 2, 1]
6.其他实用方法
// slice() - 截取数组(不修改原数组)
let arr = [1, 2, 3, 4, 5];
let part = arr.slice(1, 3); // [2, 3]// join() - 数组转字符串
let str = arr.join('-'); // "1-2-3-4-5"// Array.isArray() - 检查是否为数组
console.log(Array.isArray(arr)); // true// fill() - 填充数组
let newArr = new Array(3).fill(0); // [0, 0, 0]// flat() - 扁平化数组
let nested = [1, [2, [3]]];
let flatArr = nested.flat(2); // [1, 2, 3]
7. ES6+ 新增数组特性
1.扩展运算符
// 复制数组
let arr = [1, 2, 3];
let arrCopy = [...arr]; // [1, 2, 3]// 合并数组
let combined = [...arr, 4, 5, ...[6, 7]]; // [1, 2, 3, 4, 5, 6, 7]
2. 解构赋值
let [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
3.Array.from()
// 从类数组对象创建数组
let arrayLike = {0: 'a', 1: 'b', length: 2};
let realArray = Array.from(arrayLike); // ['a', 'b']// 从可迭代对象创建数组
let set = new Set([1, 2, 3]);
let arrayFromSet = Array.from(set); // [1, 2, 3]
(3)Object对象
对象是 JavaScript 中最重要的数据类型之一,用于存储键值对集合。几乎所有 JavaScript 的值都可以视为对象,除了原始类型(string、number、boolean、null、undefined、symbol、bigint)。
创建对象
// 1. 对象字面量语法(最常用)
let person = {name: '张三',age: 30,isStudent: false
};// 2. 使用 Object 构造函数
let car = new Object();
car.make = 'Toyota';
car.model = 'Camry';// 3. 使用 Object.create()
let animal = Object.create(null);
animal.type = 'dog';
访问属性
// 点表示法
console.log(person.name); // '张三'// 方括号表示法(适用于动态属性名或包含特殊字符的属性名)
console.log(person['age']); // 30let key = 'isStudent';
console.log(person[key]); // false
添加/修改属性
// 添加新属性
person.job = '工程师';// 修改现有属性
person.age = 31;// 使用方括号表示法
person['favorite color'] = '蓝色'; // 属性名包含空格时
删除属性
delete person.isStudent; // 删除属性
console.log(person.isStudent); // undefined
常用静态方法
// Object.keys() - 获取对象所有可枚举属性的键
let keys = Object.keys(person); // ['name', 'age', 'job', 'favorite color']// Object.values() - 获取对象所有可枚举属性的值
let values = Object.values(person); // ['张三', 31, '工程师', '蓝色']// Object.entries() - 获取键值对数组
let entries = Object.entries(person);
// [ ['name', '张三'], ['age', 31], ['job', '工程师'], ['favorite color', '蓝色'] ]// Object.assign() - 合并对象(浅拷贝)
let target = { a: 1 };
let source = { b: 2, c: 3 };
Object.assign(target, source); // { a: 1, b: 2, c: 3 }// Object.freeze() - 冻结对象,防止修改
let frozenObj = Object.freeze({ x: 1 });
frozenObj.x = 2; // 静默失败(严格模式下会报错)
对象实例方法
let obj = {name: '示例对象',// 定义方法greet: function() {return `你好,我是${this.name}`;},// ES6简写方法语法sayHello() {return 'Hello!';}
};console.log(obj.greet()); // "你好,我是示例对象"
console.log(obj.sayHello()); // "Hello!"
原型与继承
原型基础
// 每个对象都有一个原型(__proto__属性,不推荐直接使用)
let animal = {eats: true
};let rabbit = {jumps: true,__proto__: animal // 设置原型(现代写法应使用Object.create)
};console.log(rabbit.eats); // true (通过原型继承)
更规范的继承方式
// 使用Object.create()创建带有指定原型的对象
let animal = {eats: true
};let rabbit = Object.create(animal);
rabbit.jumps = true;console.log(rabbit.eats); // true
构造函数与原型
// 构造函数
function Person(name, age) {this.name = name;this.age = age;
}// 通过原型添加方法
Person.prototype.greet = function() {return `你好,我是${this.name},今年${this.age}岁`;
};let john = new Person('John', 30);
console.log(john.greet()); // "你好,我是John,今年30岁"
ES6+ 对象新特性
属性简写
let name = '李四';
let age = 25;let person = {name, // 等同于 name: nameage, // 等同于 age: agegreet() {return `我是${this.name}`;}
};
计算属性名
let propKey = 'foo';let obj = {[propKey]: true,['b' + 'ar']: 123,[Symbol('id')]: 'symbolId'
};console.log(obj.foo); // true
console.log(obj.bar); // 123
对象解构
let options = {title: '菜单',width: 100,height: 200
};// 解构赋值
let { title, width, height } = options;console.log(title); // '菜单'
console.log(width); // 100
console.log(height); // 200
扩展运算符
let obj1 = { a: 1, b: 2 };
let obj2 = { c: 3, d: 4 };let merged = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }
对象与JSON
// 对象转JSON字符串
let user = {name: "张三",age: 30
};let json = JSON.stringify(user);
console.log(json); // '{"name":"张三","age":30}'// JSON字符串转对象
let parsed = JSON.parse(json);
console.log(parsed.name); // "张三"