第1章:JavaScript简介
1.1 什么是JavaScript?
JavaScript(简称“JS”)是一种高级的、轻量级、解释型的编程语言,主要运行在客户端,用于增强网页的交互性。它最初由Netscape公司的Brendan Eich在1995年开发,目的是为网页添加动态功能。如今,JavaScript已经成为Web开发中不可或缺的一部分,它允许开发者创建交互式网页、处理用户输入、与服务器进行通信等。
1.2 JavaScript的作用
网页交互:通过JavaScript,开发者可以创建响应用户操作的网页,如点击按钮、填写表单、拖放元素等。
客户端脚本:JavaScript通常在用户的浏览器上执行,这意味着它可以快速响应用户的操作,而不需要与服务器进行通信。
服务器端脚本(Node.js):通过Node.js,JavaScript也可以在服务器端运行,处理后端逻辑、数据库交互和生成动态网页。
移动应用开发:JavaScript及其框架(如React Native)可以用来开发跨平台的移动应用。
桌面应用开发:通过Electron等框架,JavaScript也可以用来开发桌面应用程序。
1.3 如何在网页中使用JavaScript
在HTML文档中,可以通过以下三种方式嵌入JavaScript代码:
-
内联JavaScript:
直接在HTML标签的事件属性中编写JavaScript代码。例如:<button onclick="alert('Hello, World!')">Click Me</button>
这种方式不推荐用于复杂的代码,因为它会使得HTML文档变得难以维护。
-
内部JavaScript(内嵌式):
在HTML文档中使用
<script>
标签包裹JavaScript代码。例如:<script> function sayHello() { alert('Hello, World!'); } </script> <button onclick="sayHello()">Click Me</button>
这种方式允许将JavaScript代码组织在HTML文档内部,但仍然与HTML标签紧密耦合。
-
外部JavaScript:
将JavaScript代码保存在一个单独的
.js
文件中,并通过<script>
标签的src
属性引入。例如:<script src="script.js"></script>
这是推荐的方式,因为它将HTML和JavaScript代码分离,使得代码更加模块化和易于维护。
1.4 JavaScript与HTML和CSS的关系
- HTML:负责网页的结构和内容。JavaScript可以用来操作HTML元素,改变网页的结构和内容。
- CSS:负责网页的样式和布局。JavaScript可以用来动态改变CSS样式,实现动画效果等。
1.5 JavaScript的版本
随着时间的推移,JavaScript已经发展出多个版本,包括ES5、ES6(也称为ES2015)、ES7、ES8等。每个版本都引入了新的特性和改进,使得JavaScript更加强大和灵活。
1.6 开发工具和环境
为了开发JavaScript,你通常需要以下工具和环境:
- 文本编辑器:如Visual Studio Code、Sublime Text等。
- 浏览器:如Google Chrome、Mozilla Firefox等,它们内置了JavaScript引擎(如V8、SpiderMonkey)。
- 调试工具:现代浏览器提供了强大的开发者工具,用于调试JavaScript代码。
- 版本控制:如Git,用于代码版本管理和协作。
1.7 学习资源
- 在线教程:如MDN Web Docs、W3Schools等。
- 书籍:如《JavaScript高级程序设计》、《你不知道的JavaScript》等。
- 社区:如Stack Overflow、GitHub等,可以获取帮助和分享代码。
第2章:基础语法
console.log介绍:
console.log
是 JavaScript 中一个非常实用的函数,它允许你在浏览器的控制台(Console)中输出信息。这对于调试代码、查看变量值或跟踪程序执行流程非常有帮助。基本用法
console.log
最基本的用法是输出一个或多个值到控制台。你可以传递任意类型的参数给它,包括字符串、数字、对象、数组等。console.log("Hello, world!"); // 输出字符串 console.log(123); // 输出数字 console.log(true); // 输出布尔值 console.log({name: "John", age: 30}); // 输出对象 console.log([1, 2, 3, 4]); // 输出数组
此时你想要查看结果,你可以在浏览器打开你写的HTML文件,按
F12
键,会弹出一个调试栏(第一次打开时需确认)选择” 控制台(Console)“
2.1 数据类型
JavaScript 是一种解释型、动态的编程语言,广泛用于网页开发中。它支持多种数据类型,这些数据类型分为两大类:原始数据类型(Primitive Types)和对象数据类型(Object Types)。下面我将分别介绍这两大类中的主要数据类型。
原始数据类型(Primitive Types)
原始数据类型在内存中占据固定大小的空间,它们的值被直接保存在变量访问的位置。原始数据类型是不可变的,这意味着一旦创建,它们的值就不能改变(虽然变量本身可以重新赋值为其他原始值)。
- Undefined
- 当一个变量被声明了但没有被赋值时,它的默认值是
undefined
。 - 示例:
let x; console.log(x); // 输出:undefined
- 当一个变量被声明了但没有被赋值时,它的默认值是
- Null
null
是一个表示“无值”的特殊关键字,表示一个空对象引用。- 示例:
let y = null; console.log(y); // 输出:null
- Boolean
- 表示逻辑实体,有两个值:
true
和false
。 - 示例:
let isOpen = true; console.log(isOpen); // 输出:true
- 表示逻辑实体,有两个值:
- Number
- 表示所有的数值,包括整数和浮点数。JavaScript 中所有数字都是双精度 64 位浮点格式存储的(即 IEEE 754 格式)。
- 示例:
let num = 42; console.log(num); // 输出:42
- String
- 表示文本数据,用单引号(')或双引号(")括起来。
- 示例:
let greeting = "Hello, World!"; console.log(greeting); // 输出:Hello, World!
- BigInt
- 一个内置对象,提供了一种方法来表示大于
2^53 - 1
的整数。BigInt 可以表示任意大小的整数。 - 示例:
let bigNum = BigInt("123456789012345678901234567890"); console.log(bigNum); // 输出:123456789012345678901234567890n
- 一个内置对象,提供了一种方法来表示大于
- Symbol
- 表示独一无二的值。主要用于作为对象的唯一属性名。
- 示例:
let uniqueSym = Symbol("unique"); console.log(uniqueSym); // 输出:Symbol(unique)
其中:在JavaScript中,变量未赋值时默认值为undefined
,而不是null
。你必须显式地将变量赋值为null
。
其中:使用typeof null
会返回"object"
,这是一个历史遗留的JavaScript语言特性错误。
对象数据类型(Object Types)
对象数据类型是一个更复杂的数据类型,它们可以存储多个值作为属性。对象是可变的,意味着其属性和值都可以被修改。
- Object
- 对象是一个复合值,可以包含多个属性和对应的值。
- 示例:
let person = { name: "Alice", age: 30 }; console.log(person.name); // 输出:Alice
- Array
- 数组是一种特殊的对象,用于存储一个有序的值集合。
- 示例:
let numbers = [1, 2, 3, 4, 5]; console.log(numbers[2]); // 输出:3
- Function
- 函数在 JavaScript 中也是对象,可以被存储在变量中、作为参数传递给其他函数,或作为其他函数的返回值。
- 示例:
function greet(name) { return "Hello, " + name; } console.log(greet("Bob")); // 输出:Hello, Bob
- Date
- 用于处理日期和时间的对象。
- 示例:
let now = new Date(); console.log(now); // 输出当前日期和时间
- RegExp
- 正则表达式对象,用于匹配字符串中的字符组合。
- 示例:
let regex = new RegExp(/^\d+$/); console.log(regex.test("123")); // 输出:true
2.2 变量
在JavaScript中,变量是用来存储信息的“容器”。变量可以根据需要存储不同类型的数据,比如数字、文本(字符串)、布尔值(true 或 false)、数组、对象等。使用变量之前,你需要先声明它,然后可以给它赋值,并在需要时访问它的值。JavaScript 是一种动态类型语言,这意味着你不需要在声明变量时指定其类型;变量的类型会根据其被赋予的值自动确定。
变量声明
在JavaScript中,你可以使用几种不同的方式来声明变量:
-
使用
var
关键字:这是JavaScript早期版本引入的变量声明方式。使用var
声明的变量会成为其函数作用域(如果在函数内部声明)或全局作用域(如果在函数外部声明)的一部分。var
有一个“变量提升”(hoisting)的特性,即无论你在何处声明变量,它都会被提升到其作用域的顶部。var age = 25;
-
使用
let
关键字:let
是ES6(ECMAScript 2015)中引入的,用于声明块作用域局部变量。与var
不同,let
声明的变量只在其声明的块或子块中可用,并且不会被提升。let message = "Hello, World!";
-
使用
const
关键字:const
也是ES6中引入的,用于声明一个只读的常量。一旦使用const
声明了一个变量并给它赋值后,你就不能再改变它的值了(对于对象或数组,这意味着你不能改变其引用,但你可以修改其内部属性或元素)。const
同样具有块作用域。const PI = 3.14;
变量赋值
变量声明后,你可以给它赋值。变量赋值是将数据存储在变量中的过程。
let score = 85;
console.log(score); // 输出: 85
score = 90; // 更新变量的值
console.log(score); // 输出: 90
访问变量
一旦变量被声明并赋值,你就可以通过变量名来访问它的值了。
let greeting = "Hello, world!";
console.log(greeting); // 输出: Hello, world!
变量命名规则
- 变量名可以包含字母、数字、下划线(_)和美元符号($)。
- 变量名不能以数字开头。
- 变量名是区分大小写的(
name
和Name
会被视为两个不同的变量)。 - 保留字(如
var
、let
、function
等)和未来的保留字(如class
、enum
、implements
等,即使在当前版本的JavaScript中未使用)不能用作变量名。 - 遵循驼峰命名法(camelCase)或下划线命名法(snake_case)等命名约定,以提高代码的可读性。
2.3 操作符
在JavaScript中,操作符(Operators)是用于执行特定数学或逻辑操作的符号。它们可以是对数值的算术运算,对变量的赋值,或是比较两个值的大小等。
1. 算数操作符
- 加法 (
+
): 用于将两个数相加,或者将字符串连接。 - 减法 (
-
): 用于从一个数中减去另一个数。 - 乘法 (
\*
): 用于将两个数相乘。 - 除法 (
/
): 用于将第一个数除以第二个数。 - 取余 (
%
): 返回两数相除的余数。 - 递增 (
++
): 将变量的值增加1。 - 递减 (
--
): 将变量的值减少1。
let sum = 5 + 3; // 8
let difference = 5 - 3; // 2
let product = 5 * 3; // 15
let quotient = 5 / 3; // 1.666...
let remainder = 5 % 3; // 2
let power = 5 ** 3; // 125
2. 赋值操作符
- 简单赋值 (
=
): 将右侧的值赋给左侧的变量。 - 复合赋值: 如
+=
(加后赋值)、-=
(减后赋值)、*=
(乘后赋值)、/=
(除后赋值)、%=
(取余后赋值)。
let count = 1;
count += 1; // count is now 2
3. 比较操作符
- 等于 (
==
): 检查两个值是否相等,但在比较前会尝试进行类型转换。 - 全等 (
===
): 严格检查两个值是否相等,不进行类型转换。 - 不等于 (
!=
): 检查两个值是否不相等,但在比较前会尝试进行类型转换。 - 不全等 (
!==
): 严格检查两个值是否不相等,不进行类型转换。 - 大于 (
>
): 检查左侧的值是否大于右侧的值。 - 小于 (
<
): 检查左侧的值是否小于右侧的值。 - 大于等于 (
>=
): 检查左侧的值是否大于或等于右侧的值。 - 小于等于 (
<=
): 检查左侧的值是否小于或等于右侧的值。
let isEqual = (5 == '5'); // true
let isStrictEqual = (5 === '5'); // false
4. 逻辑操作符
- 逻辑与 (
&&
): 如果两个操作数都为真,则结果为真。 - 逻辑或 (
||
): 如果两个操作数中至少有一个为真,则结果为真。 - 逻辑非 (
!
): 反转操作数的布尔值。
let isTrue = true && false; // false
let isFalse = true || false; // true
let isNotTrue = !true; // false
5. 条件(三元/三目)操作符
- 条件 (
? :
): 这是JavaScript中唯一的三元操作符。它基于条件对两个值进行选择。语法是条件 ? 值1 : 值2
。如果条件为真,则结果为值1;否则为值2。
3 > 5 ? alert("Yes") : alert("No") ;
6. 字符串操作符
- 连接 (
+
): 当使用加号 (+
) 操作符连接两个字符串时,它们会被连接起来形成一个新的字符串。
7. 类型操作符
- typeof: 返回一个表示操作数类型的字符串。
- instanceof: 测试一个对象在其原型链中是否存在一个构造函数的
prototype
属性。
8. 位操作符
位操作符主要用于对整数的二进制表示进行直接操作。它们通常用于处理低级内存操作、图形编程、加密等领域,但在日常Web开发中较为少见,这里暂不展开讲解。
- 位操作符如
&
(按位与)、|
(按位或)、^
(按位异或)、~
(按位非)、<<
(左移)、>>
(有符号右移)、>>>
(无符号右移)等,主要用于对数值的二进制表示进行操作。
let a = 5; // 101 in binary
let b = 3; // 011 in binary
let and = a & b; // 1
let or = a | b; // 7
2.4 控制结构
在JavaScript中,控制结构是编程的基础,它们允许你根据条件执行不同的代码块,或者重复执行某些代码块直到满足特定条件。JavaScript提供了几种基本的控制结构,包括条件语句(如if...else
)、循环语句(如for
、while
、do...while
)以及switch
语句。
1. 分支语句
if…else
if...else
语句是最基本的分支语句,它允许你根据条件表达式的真假来执行不同的代码块。
if (condition) {
// 如果条件为真,执行这里的代码
} else {
// 如果条件为假,执行这里的代码
}
condition
:条件
例:
// 如果分数大于等于60,则打印“及格”,否则打印“不及格”
if (score >= 60) {
// 条件为真时执行
console.log("及格");
} else {
// 条件为假时执行
console.log("不及格");
}
if…else if…else
当你有多个条件需要检查时,可以使用if...else if...else
结构。
if (condition1) {
// 条件1为真时执行
} else if (condition2) {
// 条件1为假且条件2为真时执行
} else {
// 所有条件都为假时执行
}
例:
// 根据成绩区间打印不同的评价
if (score >= 90) {
// 分数大于等于90时执行
console.log("优秀");
} else if (score >= 60) {
// 分数小于90但大于等于60时执行
console.log("及格");
} else {
// 分数小于60时执行
console.log("不及格");
}
switch
switch
语句允许一个表达式的值与多个case标签进行比较,并执行与匹配case相关联的语句块。
switch (expression) {
case value1:
// 如果expression === value1,执行这里的代码
break;
case value2:
// 如果expression === value2,执行这里的代码
break;
// 可以有更多的case...
default:
// 如果没有任何case匹配,执行这里的代码
}
注意:在switch
语句中,每个case
块的末尾通常需要有一个break
语句,以防止代码自动落入下一个case
块中(称为“case穿透”)。
例:
// 使用switch语句根据星期几打印不同的活动
let day = new Date().getDay(); // 获取当前是星期几(0-6,周日到周六)
switch (day) {
case 0:
console.log("周日:休息日");
break;
case 1:
console.log("周一:工作日");
break;
case 2:
console.log("周二:工作日");
break;
case 3:
console.log("周三:工作日");
break;
case 4:
console.log("周四:工作日");
break;
case 5:
console.log("周五:工作日");
break;
case 6:
console.log("周六:休息日");
break;
default:
// 理论上这里不会执行,因为getDay()的返回值范围已经覆盖
console.log("ta答应做你npy");
}
2. 循环语句
for
for
循环是最常用的循环结构之一,它允许你指定循环的初始化、条件和最终表达式。
for (initialization; condition; final-expression) {
// 循环体
}
initialization
:初始化
final-expression
:最终表达式
例:
// 定义一个数组
var arr = ['apple', 'banana', 'cherry', 'date'];
// 使用for循环遍历数组并打印每个元素
for (let i = 0; i < arr.length; i++) {
// 初始化i为0,条件是i小于数组长度,每次循环后i增加1
console.log(arr[i]); // 打印当前元素
}
while
while
循环会在指定的条件为真时重复执行代码块。
while (condition) {
// 循环体
}
例:
// 使用while循环直到条件不再满足
let count = 0;
while (count < 5) {
// 条件为count小于5时执行
console.log(count); // 打印当前计数值
count++; // 每次循环后增加计数值
}
do…while
do...while
循环至少会执行一次代码块,然后在条件为真时继续执行。
do {
// 循环体
} while (condition);
例:
let i = 0;
do {
// 至少执行一次
console.log(i); // 打印当前值
i++; // 增加i的值
} while (i < 5); // 条件为i小于5时继续循环
第3章:函数
3.1 函数定义
函数声明
函数声明是定义函数的一种方式,它使用function
关键字后跟函数名和圆括号内的参数列表,以及一个花括号包裹的函数体。这种方式定义的函数在定义之后即可在声明它的作用域内被调用,包括在声明之前。
function greet(name) {
console.log("Hello, " + name + "!");
}
greet("Alice"); // 输出: Hello, Alice!
函数表达式
函数表达式是将函数赋值给一个变量的方式。这种方式定义的函数可以立即执行(立即执行函数表达式,IIFE),或者像变量一样被传递、赋值。
var greet = function(name) {
console.log("Hello, " + name + "!");
};
greet("Bob"); // 输出: Hello, Bob!
// 立即执行函数表达式(IIFE)
(function() {
console.log("This function runs immediately.");
})();
箭头函数(ES6+)
箭头函数是ES6中引入的一种更简洁的函数写法,它使用=>
语法,类似于Java中的lambda表达式。但箭头函数不绑定自己的this
,arguments
,super
,或new.target
。这些函数表达式更适合用于非方法函数,并且它们不能用作构造函数。
const greet = (name) => {
console.log("Hello, " + name + "!");
};
greet("Charlie"); // 输出: Hello, Charlie!
// 简洁形式(当函数体只有一条语句时,可以省略花括号和大括号内的return)
const greetShort = name => `Hello, ${name}!`;
console.log(greetShort("David")); // 输出: Hello, David!
箭头函数与this
箭头函数不绑定自己的this
值,它会捕获其所在上下文的this
值,作为自己的this
值,这使得箭头函数在处理对象方法时非常有用。
const person = {
name: 'Kimi',
greet: () => console.log(`Hello, my name is ${this.name}`)
};
person.greet(); // 输出: Hello, my name is Kimi
3.2 函数参数
形式参数
形式参数(简称形参)是函数定义时,圆括号内声明的变量,用于接收传递给函数的值。在函数体内部,你可以通过形参来访问传递进来的数据。
function multiply(a, b) {
return a * b;
}
console.log(multiply(3, 4)); // 输出: 12
实际参数
实际参数(简称实参)是调用函数时,传递给函数的值。这些值被存储在函数的形式参数中,供函数内部使用。
function showDetails(name, age) {
console.log(`Name: ${name}, Age: ${age}`);
}
showDetails("Eve", 25); // 调用时,Eve和25是实际参数
参数默认值(ES6+)
如果调用函数时没有提供某个参数,可以使用默认参数值。
function multiply(a, b = 1) {
return a * b;
}
multiply(5); // 5,因为b使用了默认值1
剩余参数(ES6+)
剩余参数允许我们将一个不定数量的参数表示为一个数组。类似于Java中的可变参数。
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4); // 10
3.3 作用域
在JavaScript中,作用域(Scope)是指变量、函数和对象的可访问性。作用域决定了代码块中的变量、函数和对象如何被访问以及它们的生存周期。JavaScript中的作用域主要分为以下几种类型:
全局作用域(Global Scope)
全局作用域是最外层的作用域,它在代码的任何地方都可以被访问。在浏览器环境中,全局作用域是window
对象。在全局作用域中声明的变量或函数会成为全局对象(在浏览器中是window
)的属性。
- 在全局作用域中定义的变量、函数或对象可以在代码的任何其他部分被访问和修改,除非它们被局部作用域中的同名变量覆盖。
- 如果你在函数外部声明一个变量,它就属于全局作用域。
- 全局作用域中的变量会成为全局对象的属性(在浏览器中通常是
window
对象)。
var globalVar = "I'm global!";
function globalFunction() {
console.log("This is a global function.");
}
console.log(window.globalVar); // 输出: I'm global!
window.globalFunction(); // 调用全局函数
局部作用域
也称:函数作用域(Function Scope),是函数内部的作用域。在局部作用域中声明的变量或函数只能在函数内部访问。每次函数被调用时,都会创建一个新的作用域链,其中包含了该函数的局部作用域以及所有父级作用域。
- 在函数作用域中声明的变量、函数或对象只能在该函数内部被访问和修改。
- 函数作用域是JavaScript中的一个非常重要的概念,因为它限制了变量的可见性和生命周期。
- 在ES5及之前版本中,JavaScript没有块级作用域,只有函数作用域。
function localScopeDemo() {
var localVar = "I'm local!";
function innerFunction() {
console.log(localVar); // 可以访问局部变量
}
innerFunction(); // 输出: I'm local!
}
// 尝试访问 localVar 会导致 ReferenceError
// console.log(localVar); // 错误: localVar is not defined
块级作用域(ES6+)
在代码块(如if
语句、循环等)内部声明的变量只在该代码块内部可见。
- 在ES6(ECMAScript 2015)中,引入了
let
和const
关键字,它们允许你创建块级作用域。 - 块级作用域通常由花括号
{}
定义,如if
语句、for
循环或while
循环等。 - 在块级作用域中声明的变量只能在那个块内部被访问和修改。
if (true) {
let blockVar = 'I am block scoped';
}
console.log(blockVar);// 错误:未定义
作用域链(Scope Chain)
- 当访问一个变量时,JavaScript引擎会首先在当前作用域中查找变量,如果找不到,就会向上级作用域查找,直到全局作用域。
- 这种作用域的嵌套结构被称为作用域链。
- 函数在创建时会保存一个[[Scope]]属性,它包含了函数定义时的作用域链。
var globalVar = "global";
function outer() {
var outerVar = "outer";
function inner() {
var innerVar = "inner";
console.log(innerVar); // "inner"
console.log(outerVar); // "outer"
console.log(globalVar); // "global"
}
inner();
}
outer();
在这个例子中,inner
函数的作用域链包含了它自己的变量、outer
函数的变量以及全局变量。
3.4 闭包(Closures)
闭包是JavaScript中一个强大的特性,它允许函数访问其定义时的作用域链,即使在其定义的作用域外执行。
-
创建闭包: 当一个函数从另一个函数中返回,并且返回的函数在其外部作用域中引用了变量时,就创建了一个闭包。
function createClosure() { var secret = 'I am a secret'; return function() { console.log(secret); }; } const myClosure = createClosure(); myClosure(); // 输出: I am a secret
3.5 递归函数
递归函数是调用自身的函数,用于解决可以分解为相似子问题的问题。
-
递归示例: 计算阶乘的函数。
function factorial(n) { if (n === 0) return 1; return n * factorial(n - 1); } factorial(5); // 120
3.6 高阶函数
高阶函数是至少满足下列条件之一的函数:
-
接受一个或多个函数作为参数。
-
返回一个函数。
-
高阶函数示例:
使用
map
方法对数组的每个元素应用一个函数。const numbers = [1, 2, 3, 4, 5]; const squared = numbers.map(function(number) { return number * number; });
3.7 函数柯里化
柯里化是将多参数的函数转换成一系列使用一个或多个参数的函数的技术。
-
柯里化示例:
function curriedSum(a) { return function(b) { return function(c) { return a + b + c; }; }; } const sum3 = curriedSum(1); const sum3With2 = sum3(2); const result = sum3With2(3); // 6
第4章:对象和数组
4.1 对象
JavaScript中的对象是一种复合数据类型,是用于存储数据和相关操作的集合,它允许你将多个值(原始值或其他对象)作为属性(properties)存储在单个实体中。对象可以视为属性的无序集合,每个属性都有一个名称(键)和一个值,其中键是字符串(或符号),值可以是任何数据类型。
-
创建对象:
-
对象字面量
对象字面量:使用花括号
{}
定义对象,并在其中写入属性名和值。let person = { firstName: "John", lastName: "Doe", age: 30, greet: function() { console.log(`Hello, my name is ${this.firstName} ${this.lastName}.`); } };
-
构造函数
使用
new Object()
创建对象,但通常更推荐使用对象字面量。let person = new Object(); person.firstName = "John"; person.lastName = "Doe"; // 以此类推...
-
类(ES6+)
使用
class
关键字定义类,并通过new
关键字实例化对象。class Person { constructor(firstName, lastName, age) { this.firstName = firstName; this.lastName = lastName; this.age = age; } greet() { console.log(`Hello, my name is ${this.firstName} ${this.lastName}.`); } } let person = new Person("John", "Doe", 30);
-
-
访问对象属性:
-
点符号(
.
):如果属性名符合标识符命名规则,则可以使用点符号访问。console.log(person.firstName); // 输出: John
-
方括号(
[]
):如果属性名包含特殊字符或需要动态计算,则可以使用方括号访问。console.log(person["last-name"]); // 假设 //对象 输出有:这样一个 属性3
-
-
修改和添加属性:
可以直接给对象的属性赋新值或添加新属性。
person.age = 31; // 修改属性 person.email = 'john.doe@example.com'; // 添加新属性
-
删除属性:
使用
delete
操作符可以删除对象的属性。delete person.email;
-
对象方法:
对象中可以包含函数,这些函数称为对象的方法。
person.greet(); // 输出: Hello, my name is John
4.2 数组
数组是用于存储多个值的变量,这些值称为数组元素。数组可以包含任意类型的元素。
数组是一种特殊的对象,用于存储有序的元素集合。每个元素可以通过索引(一个正整数)来访问,索引从0开始。
-
创建数组:
-
数组字面量:使用方括号
[]
定义数组,并在其中写入元素。let fruits = ["Apple", "Banana", "Cherry"];
-
构造函数:使用
new Array()
创建数组,但通常更推荐使用数组字面量。let numbers = new Array(1, 2, 3, 4, 5); // 或者,仅指定数组长度 let emptyArray = new Array(5); // 创建一个长度为5的空数组
-
-
访问数组元素:
使用索引(从0开始)来访问数组中的元素。
console.log(fruits[0]); // 输出: Apple
-
修改数组元素:
可以直接给数组的索引赋新值来修改元素。
fruits[1] = 'Blueberry'; // 修改第二个元素
-
添加和删除元素:
可以使用多种方法添加和删除数组元素。
-
添加元素:
fruits.push('Date'); // 添加到数组末尾 fruits.unshift('Apricot'); // 添加到数组开头
-
删除元素:
fruits.pop(); // 删除数组末尾的元素 fruits.shift(); // 删除数组开头的元素
-
-
数组方法:
JavaScript为数组提供了许多有用的方法,如
map()
、filter()
、reduce()
等。-
map()
:创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后的返回值。const numbers = [1, 2, 3, 4]; const squared = numbers.map(x => x * x); console.log(squared); // 输出: [1, 4, 9, 16]
-
filter()
:创建一个新数组,其包含通过所提供函数实现的测试的所有元素。const evenNumbers = numbers.filter(x => x % 2 === 0); console.log(evenNumbers); // 输出: [2, 4]
-
reduce()
:对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0); console.log(sum); // 输出: 10
-
第5章:DOM操作
5.1 什么是DOM
DOM(Document Object Model,文档对象模型)是一个编程接口,它提供了访问和操作HTML和XML文档结构、样式和内容的方法。在Web开发中,DOM是JavaScript与网页内容交互的基础。
5.2 选择元素
在DOM操作中,首先需要选择页面上的元素,然后才能对它们进行操作。
-
document.getElementById()
:通过元素的ID选择元素。ID应该是唯一的。
const header = document.getElementById('header');
-
document.getElementsByTagName()
:通过标签名选择元素。返回一个包含所有匹配元素的HTMLCollection。
const paragraphs = document.getElementsByTagName('p');
-
document.getElementsByClassName()
:通过类名选择元素。返回一个包含所有匹配元素的HTMLCollection。
const items = document.getElementsByClassName('item');
-
document.querySelector()
:使用CSS选择器选择第一个匹配的元素。(推荐使用)
const firstParagraph = document.querySelector('p');
-
document.querySelectorAll()
:使用CSS选择器选择所有匹配的元素。返回一个包含所有匹配元素的NodeList。
const allLinks = document.querySelectorAll('a');
5.3 修改内容
一旦选择了元素,就可以修改它们的文本内容、HTML内容或属性。
-
修改文本内容:
-
使用
element.innerText
或element.textContent
修改元素的文本内容(不包括HTML标签)。 -
使用
element.innerHTML
修改元素的内容,包括HTML标签。elem.innerText = "新文本内容"; elem.innerHTML = "<strong>加粗文本</strong>";
-
-
修改属性::
-
使用
element.setAttribute(name, value)
添加或修改元素的属性。 -
使用
element.removeAttribute(name)
删除元素的属性。 -
也可以使用
element.属性名 = 值
直接修改某些属性(如id
、className
等)。elem.setAttribute("title", "新标题"); elem.removeAttribute("class"); elem.id = "newId"; const link = document.querySelector('a'); link.href = 'https://example.com'; link.target = '_blank';
-
-
修改样式:
-
使用
element.style.样式属性
直接修改元素的CSS样式。 -
使用
element.classList.add(className)
、element.classList.remove(className)
、element.classList.toggle(className)
来添加、删除或切换元素的类名,从而控制样式。elem.style.color = "red"; elem.classList.add("highlight"); elem.classList.remove("highlight"); elem.classList.toggle("highlight");
-
5.4 事件处理
事件是用户或浏览器触发的动作,如点击、滚动、键盘输入等。JavaScript允许你为元素添加事件监听器来响应这些事件。
-
事件监听器:
使用
addEventListener()
方法为元素添加事件监听器。const button = document.getElementById('myButton'); button.addEventListener('click', function() { alert('Button clicked!'); });
-
事件对象:
当事件被触发时,会传递一个事件对象给事件处理函数。这个对象包含了事件的详细信息。
button.addEventListener('click', function(event) { console.log(event.type); // 'click' console.log(event.target); // 被点击的元素 });
-
事件类型:
JavaScript支持多种事件类型,包括但不限于:
- 鼠标事件:
click
,mouseover
,mouseout
,mousedown
,mouseup
- 键盘事件:
keydown
,keyup
- 表单事件:
submit
,change
,focus
,blur
- 窗口事件:
load
,resize
,scroll
- 鼠标事件:
-
移除事件监听器:
使用
removeEventListener()
方法可以移除之前添加的事件监听器。button.removeEventListener('click', handleClick);
5.5 创建和插入元素
JavaScript允许你动态创建新的元素,并将其插入到DOM中。
-
创建元素
使用
document.createElement()
方法创建新的元素。const newDiv = document.createElement('div');
-
插入元素:
使用
appendChild()
或insertBefore()
方法将新创建的元素添加到DOM中。const body = document.body; body.appendChild(newDiv); // 添加到body的子元素列表的末尾
-
设置元素属性:
在添加元素到DOM之前,可以设置其属性。
newDiv.id = 'newElement'; newDiv.className = 'new-class';
-
替换元素:
使用
parent.replaceChild(newChild, oldChild)
替换父元素中的子元素。parentElement.replaceChild(newElement, oldElement);
第6章:事件
在JavaScript中,事件是用户或浏览器触发的动作。例如,当用户点击一个按钮、提交一个表单、或者当浏览器加载完一个网页时,都会触发一个事件。JavaScript允许你监听这些事件,并定义当这些事件发生时应该执行的代码。
6.1 事件类型
JavaScript支持多种类型的事件,包括但不限于:
- 鼠标事件:
click
:当用户点击一个元素时触发。dblclick
:当用户双击一个元素时触发。mousedown
:当用户按下鼠标按钮时触发。mouseup
:当用户释放鼠标按钮时触发。mouseover
:当鼠标指针移动到元素上时触发。mouseout
:当鼠标指针移出元素时触发。mousemove
:当鼠标指针在元素内部移动时触发。
- 键盘事件:
keydown
:当用户按下键盘上的任何键时触发。keyup
:当用户释放键盘上的键时触发。keypress
:当用户按下并释放键盘上的键时触发(在keydown
和keyup
之间)。
- 表单事件:
submit
:当表单被提交时触发。reset
:当表单被重置时触发。change
:当元素的值发生变化时触发(例如,用户在文本框中输入文本)。focus
:当元素获得焦点时触发。blur
:当元素失去焦点时触发。
- 文档/窗口事件:
load
:当整个页面及所有依赖资源(如样式表和图片)完全加载后触发。beforeunload
:在卸载页面前触发,可以用来提示用户确认离开。resize
:当窗口大小发生变化时触发。scroll
:当文档滚动时触发。
6.2 事件监听
在JavaScript中,你可以使用addEventListener()
方法来为元素添加事件监听器。这个方法接受三个参数:
- 事件类型(String):要监听的事件的名称,如
"click"
。 - 事件处理函数(Function):当事件发生时执行的函数。
- 可选参数(Boolean):一个布尔值,指定事件是否在捕获或冒泡阶段执行。默认为
false
(冒泡阶段)。
element.addEventListener('event', function(event) {
// 事件触发时执行的代码
});
例:
element.addEventListener('click', function() {
console.log('元素被点击了!');
});
-
事件对象:当事件被触发时,浏览器会创建一个事件对象(
event
),并将其传递给事件处理函数。这个对象包含了事件的详细信息,如事件类型、触发事件的元素、鼠标的位置等。element.addEventListener('click', function(event) { console.log(event.target); // 触发事件的元素 console.log(event.type); // 事件类型,如"click" });
6.3 事件传播
事件在DOM树中的传播分为三个阶段:捕获阶段、目标阶段和冒泡阶段。
- 捕获阶段:事件从根节点(通常是
document
对象)开始,向目标节点传播。 - 目标阶段:事件到达目标节点(触发事件的元素)。
- 冒泡阶段:事件从目标节点开始,向根节点传播。
当一个事件发生时,它首先在触发事件的元素上触发,然后逐级向上传播到DOM树的根部,这个过程称为事件冒泡。你可以通过调用事件对象的stopPropagation
方法来阻止事件进一步传播。
button.addEventListener('click', function(event) {
event.stopPropagation();
console.log('This will not propagate');
});
addEventListener()
的第三个参数可以用来指定监听器是在捕获阶段还是冒泡阶段触发。
6.4 事件捕获
与事件冒泡相反,事件捕获是指事件从DOM树的根部开始,然后向下传播到触发事件的元素的过程。可以通过在addEventListener
方法中设置第三个参数为true
来启用事件捕获。
6.5 阻止默认行为
在某些情况下,你可能想要阻止元素的默认行为(例如,当点击链接时不跳转)。可以通过调用事件对象的preventDefault
方法来实现。
const link = document.getElementById('myLink');
link.addEventListener('click', function(event) {
event.preventDefault();
console.log('Link will not navigate');
});
第7章:异步编程
7.1 回调函数
定义和使用
7.2 Promises
创建Promise
使用Promise
7.3 async/await
使用async函数
使用await关键字
第8章:模块和包管理
8.1 使用模块
导入和导出
8.2 使用包管理器
npm
yarn
第9章:实战项目
9.1 创建一个简单的计数器
HTML结构
CSS样式
JavaScript逻辑
9.2 创建一个待办事项应用
功能需求
代码实现
第10章:最佳实践和调试
10.1 代码风格
一致性
可读性
10.2 调试工具
使用浏览器开发者工具
使用console.log()
10.3 性能优化
代码优化
资源优化
未完待续。。。
文章不定时更新。。。