1、变量声明和作用域
var
- 作用域:函数作用域(function scope)。
- 在函数内部声明的变量,只能在函数内部访问。
- 在函数外部声明的变量,会成为全局变量。
- 提升(Hoisting) :变量声明会被提升到函数或全局作用域的顶部,但赋值不会被提升。
- 重复声明:允许重复声明同一个变量。
- 全局属性:在全局作用域中声明的
var变量会成为全局对象(如window)的属性。 示例:
function example() {
if (true) {
var x = 10; // 函数作用域
}
console.log(x); // 10,x 在函数内可访问
}
example();
console.log(x); // 报错,x 在函数外不可访问
let
- 作用域:块级作用域(block scope)。
- 在
{}块内声明的变量,只能在块内访问。
- 在
- 提升:变量声明会被提升到块级作用域的顶部,但在声明之前访问会触发“暂时性死区”(Temporal Dead Zone, TDZ)。
- 重复声明:不允许重复声明同一个变量。
- 全局属性:在全局作用域中声明的
let变量不会成为全局对象的属性。 示例:
function example() {
if (true) {
let y = 20; // 块级作用域
console.log(y); // 20
}
console.log(y); // 报错,y 在块外不可访问
}
example();
const
- 作用域:块级作用域(block scope)。
- 与
let相同,const声明的变量只能在块内访问。
- 与
- 提升:与
let相同,存在暂时性死区。 - 重复声明:不允许重复声明同一个变量。
- 不可变性:
- 声明的变量必须初始化,且不能重新赋值。
- 如果变量是对象或数组,其属性或元素可以修改。
- 全局属性:在全局作用域中声明的
const变量不会成为全局对象的属性。 示例:
const z = 30; // 必须初始化
z = 40; // 报错,不能重新赋值
const person = { name: "Alice" };
person.name = "Bob"; // 允许修改属性
console.log(person.name); // Bob
三者区别
| 特性 | var | let | const |
|---|---|---|---|
| 作用域 | 函数作用域 | 块级作用域 | 块级作用域 |
| 提升 | 声明提升,赋值不提升 | 声明提升,存在 TDZ | 声明提升,存在 TDZ |
| 重复声明 | 允许 | 不允许 | 不允许 |
| 可变性 | 可重新赋值 | 可重新赋值 | 不可重新赋值 |
| 全局属性 | 是全局对象的属性 | 不是全局对象的属性 | 不是全局对象的属性 |
| 初始化 | 可不初始化 | 可不初始化 | 必须初始化 |
| 注意:避免使用var,优先使用const,必要时使用let |
示例对比
- var的问题
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // 输出 3 次 3
}, 100);
}
由于 var 是函数作用域,i 在循环结束后仍然是 3。
- let解决方案
for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // 输出 0, 1, 2
}, 100);
}
由于let是块级作用域,每次循环都会创建一个新的i。
注意:变量未赋值时默认值为 undefined,const 声明常量需初始化且不可重新赋值。
2、数据类型
-
基本类型:
string:字符串,如"Hello"。number:数字,如42、3.14。boolean:布尔值,如true、false。null:表示空值。undefined:表示未定义的值。symbol:唯一且不可变的值(ES6 新增)。
-
引用类型:
object:对象,如{ name: "Alice", age: 25 }。array:数组,如[1, 2, 3]。function:函数。- 注意点:
typeof null返回"object"(历史遗留问题)。
判断数据类型:判断数据类型的方法1、typeof 特点: 返回一个字符串,表示操作数的数据类型。 可以识别基本类型(如 number、 - 掘金
3、运算符与表达式
- 算术运算符:
+、-、*、/、%(取余)。 - 比较运算符:
==、===、!=、!==、>、<、>=、<=。 - 逻辑运算符:
&&(与)、||(或)、!(非)。 - 赋值运算符:
=、+=、-=、*=、/=。
注意:==和===的区别:
==会在比较两个值时进行类型转换,如果类型不同,会尝试将它们转换为相同的类型,然后再进行比较。
示例:
console.log(5 == "5"); // true,因为 "5" 被转换为 5
console.log(0 == ""); // true,因为空字符串被转换为 0
console.log(0 == "0"); // true,因为 "0" 被转换为 0
console.log(null == undefined); // true,特殊规则
console.log("true" == true); // false,因为 "true" 转换为 NaN,而 NaN 不等于 true
===会在比较两个值时,不仅比较它们的值,还会比较它们的类型。如果类型不同,直接返回false,不会进行类型转换。
示例:
console.log(5 === "5"); // false,因为类型不同(number vs string)
console.log(0 === ""); // false,因为类型不同(number vs string)
console.log(0 === "0"); // false,因为类型不同(number vs string)
console.log(null === undefined); // false,因为类型不同(null vs undefined)
console.log("true" === true); // false,因为类型不同(string vs boolean)
console.log(5 === 5); // true,因为类型和值都相同
console.log("hello" === "hello"); // true,因为类型和值都相同
特殊情况:
null和undefined之间使用==时会返回true,但使用===时会返回false。NaN不等于任何值,包括它自己。
4、流程控制语句
- 条件语句:
if-else条件判断switch多分支选择
- 循环语句:
for:固定次数的循环。while:条件为真时循环。do...while:至少执行一次循环。for...of:遍历可迭代对象(如数组)。for...in:遍历对象的属性。for-in和for-of的区别:for-in和for-offor-in和for-of的区别for-in:用于遍历对象的键,适合操作普通对象 - 掘金
5、函数
函数是 JavaScript 中的基本构建块,用于封装可重用的代码:
- 函数声明:
function关键字。 - 函数表达式:将函数赋值给变量。
- 箭头函数:ES6 新增的简洁语法。 示例:
// 函数声明
function greet(name) {
return "Hello, " + name;
}
// 函数表达式
const greet = function(name) {
return "Hello, " + name;
};
// 箭头函数
const greet = (name) => "Hello, " + name;
console.log(greet("Alice")); // Hello, Alice
参数的类型:
- 基本参数
function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // 5
- 默认参数(为参数设置默认值)
function greet(name = "Guest") {
return "Hello, " + name;
}
console.log(greet()); // Hello, Guest
- 剩余参数(使用...语法将多个参数合并为数组)
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3)); // 6
立即执行函数:立即执行函数是指在定义后立即执行的函数,通常用于创建独立的作用域。
(function() {
let x = 10;
console.log(x); // 10
})();
箭头函数的特点:
- 没有自己的
this,继承外层作用域的this。 - 不能用作构造函数(不能使用
new)。 - 没有
arguments对象。
6、对象
对象是键值对的集合,用于存储复杂数据:
- 属性:对象的键值对。
- 方法:对象的函数属性。
示例:
let person = {
name: "Alice",
age: 25,
greet: function() {
return "Hello, " + this.name;
}
};
console.log(person.name); // Alice
console.log(person.greet()); // Hello, Alice
详细:对象对象是 JavaScript 的核心数据结构,用于存储键值对。 可以通过对象字面量、构造函数或类创建对象。 - 掘金
7、数组
数组是用于存储多个值的有序集合:
- 索引:从 0 开始。
- 方法:
push()、pop()、shift()、unshift()、slice()、splice()等。 详细:数组1、声明数组 使用数组字面量 1.2 使用 Array 构造函数 2、数组的基本操作 获取数组长度 访问数组元素 - 掘金