零基础学前端-传统前端开发(第四期-JS基础)

经过前面学过的HTML,CSS的学习,相信大家已经可以使用进行常用的页面开发,接下来我们就要学习JavaScript,鉴于内容过多,需要长期练习

流程为:数据类型>>运算>>语法,语句>>对象>>数组>>函数>>类

软件使用:谷歌浏览器(当然如果你了解的话可以用nodejs试一下,但是为了方便,本系列都是用的浏览器)

JavaScript相比起HTML,CSS是有一定难度的,可以作为一门编程语言而学的,但是学会

JavaScript对于后期我们学习nodejs(包括python爬虫的学习)的时候帮助很大,所以仍然要细心学习

JavaScript在前端开发有什么用呢:

在开发房子中HTML相当于房子水泥钢筋铸的结构骨架,CSS相当于房子的装修风格,而JavaScript相当于智能家居一样,可以让网站变得动态(也就是我们看到的动画效果)

学习JavaScript之前,我们先学数据类型,这个东西有过学习其他开发语言的朋友应该了解

数据类型

一、基本数据类型(Primitive Data Types)

基本数据类型是构成 JavaScript 最基础的单位,存储在栈内存中,直接存储实际的数据值。JavaScript 的基本数据类型包括以下几种:

String(字符串):用来表示文本数据,可以是一个字符或一串字符序列,例如"Hello"、'JavaScript'、"42"等。字符串是不可变的,每次对字符串的操作都会产生新的字符串实例。

Number(数字):表示数字,包括整数和浮点数。例如42、3.14、-7等。JavaScript 中的数字没有区分整型和浮点型,统一用 Number 表示。

Boolean(布尔值) :表示逻辑实体,只有两个值:true 和 false。通常用于条件判断中。(在之前的皮卡丘靶场中的布尔类型的内容中我们短暂的了解过)

Undefined(未定义):表示变量未被赋值,或者尚未声明的变量的默认值。例如:let x;,此时 x 的值就是 undefined。

Null(空值):表示没有值,或者对象为空。null 是一个空对象引用。它和 undefined 常常容易混淆,但它们表示的意义不同。

二、引用数据类型(Reference Data Types)

引用数据类型是复合数据类型,通常存储在堆内存中,变量存储的是对象在内存中的地址(引用)。以下是常见的引用数据类型:

Object(对象):是 JavaScript 中最通用的引用数据类型,以键值对的形式存储数据。例如:let person = { name: 'John', age: 30 }。

Array(数组):是一种特殊的对象,用于存储多个值,这些值可以通过索引来访问。例如:let arr = [1, 2, 3, 'JavaScript']。

Function(函数):在 JavaScript 中,函数其实也是一种特殊的对象,可以被赋值、传递和返回。例如:function add(a, b) { return a + b; } 或者箭头函数:const add = (a, b) => a + b;。

以上是数据类型的知识,虽然看起来很简单,但是在开发语言中,这是非常重要的地基,如果没有记牢的话会影响后面的学习

运算

接下来我们学习运算(类似于你学习数学,你得先知道各类数字比如:整数,有小数点的,有分号的,今天的运算相当于了解加减乘除的符号用法)

直接用谷歌浏览器来运行即可:我们按压F12打开console(如果你汉化过叫"控制台")在里面输入即可

一,算数运算符

作用:执行基本的数学运算

  • 加法
  • 减法

* 乘法

/ 除法

% 求余

示例

javascript 复制代码
let a = 5;

let b = 3;

console.log(a + b); // 8

console.log(a - b); // 2

console.log(a * b); // 15

console.log(a / b); // 1.666...

console.log(a % b); // 2

类似以上内容,直接把内容放到控制台运行即可

二,比较运算符

作用:比较运算符用于比较两个值,返回布尔值(truefalse

== 等于

!= 不等于

> 大于

< 小于

>= 大于等于

<= 小于等于

示例

javascript 复制代码
let a = 5;

let b = 3;

console.log(a == b); // false

console.log(a != b); // ture

console.log(a > b); // true

console.log(a <= b); // false

三,逻辑运算符

作用:逻辑运算符用于组合布尔值,返回布尔结果。

&& 逻辑与(AND)

|| 逻辑或(OR)

! 逻辑非(NOT)

示例

javascript 复制代码
let a = 5;

let b = 3;

console.log(a > 2 && b < 4); // true

console.log(a < 2 || b > 4); // false

console.log(!(a == b)); // true

四,赋值运算符

作用:赋值运算符用于给变量赋值

= 简单赋值

+= 加法赋值

-= 减法赋值

*= 乘法赋值

/= 除法赋值

%= 取模赋值

示例

javascript 复制代码
let c = 10;

c += 5; // c = 15

c -= 3; // c = 12

c *= 2; // c = 24

c /= 4; // c = 6

c %= 5; // c = 1

console.log(c); // 1

由此我们还可以知道JavaScript读取时显示的的是最后一个结果,是因为每次运算的结果会覆盖之前的值,或者你只在最后调用了输出函数

语法语句

接下来是语法,语句

传统的语法定义:音义结合的各结构单位之间的组织规则的汇集。但是在JavaScript学习中,语法意为描述合法代码书写规则的集合(就是拼拼图,必须按照固定搭配才能拼好)

语句:是程序中执行一个操作的基本单元,它是构成程序的基本结构元素之一(就好像写作文,是一句话一句话拼起来的)

语法:

代码块:

代码块是用花括号 {}括起来的代码片段,通常用于表示代码的逻辑结构。

比如在if语句、for循环、while循环和函数中,代码块用来定义执行的具体操作。(在 JavaScript 中,语句通常以分号(;)结尾,表示一个完整的操作结束。)

javascript 复制代码
if (age >= 18) {

  console.log("成年了");

  console.log("可以参加选举了");

}

这里的 {} 中的内容就是代码块,表示当条件满足时,要执行的多个操作。

注释:

注释是用来解释代码片段的,它不会被浏览器执行,但可以帮助我们理解代码的逻辑。(类似于你背英语单词,考试的时候不会看你了不了解,只看你写出来的回答这就是浏览器执行的内容,你背在脑子里的翻译语法就是注释)

单行注释

使用 //,它只能注释这一行的内容

javascript 复制代码
// 这是单行注释,解释变量的作用

let x = 10; // 初始化变量 x
多行注释

使用 /**/ 包裹内容,可以注释多行代码。

javascript 复制代码
/*

这是一个多行注释,可以用来解释

一个复杂的功能模块或者代码逻辑

*/

语句:

变量声明

var语句:是 JavaScript 中最初用于声明变量的关键字。它具有函数作用域,也就是说在函数内部用 var 声明的变量,只在该函数内部有效。

javascript 复制代码
function test() {

  var x = 10;

}

console.log(x); // 会报错,因为 x 只在 test 函数内部有效

let语句:用于声明变量的关键字,它具有块级作用域。块级作用域是指在一对大括号({})内声明的变量,只在该大括号内有效。

javascript 复制代码
{

  let y = 20;

}

console.log(y); // 会报错,因为 y 只在大括号内有效

const:const 用于声明常量,也具有块级作用域。一旦声明后,常量的值不能被改变。

javascript 复制代码
const PI = 3.14;

console.log(PI); // 输出 3.14

PI = 3; // 会报错,不能修改常量的值

条件语句

(类似于如果...我就..这种说法内容)

if 语句:if 语句用于根据条件执行不同的代码。

语法格式

javascript 复制代码
if (条件) {

  代码块

}
javascript 复制代码
var age = 18;

if(age >= 18){

  console.log("你好");

}

if...else 语句: 当需要在条件为真和为假时分别执行不同的代码时,可以使用 if...else 语句。

语法格式

javascript 复制代码
if (条件) {

  代码块 1

} else {

  代码块 2

}
javascript 复制代码
var score = 60;

if(score >= 60){

  console.log("及格");

}else{

  console.log("不及格");

}

 

  如果 `score >= 60` 为真,就执行代码块 1 ,输出 "及格";否则执行代码块 2 ,输出 "不及格"。

if...else if...else 语句:当有多个条件需要判断时,可以使用 if...else if...else 语句。

语法格式

javascript 复制代码
if (条件 1) {

  代码块 1

} else if (条件 2) {

  代码块 2

} else {

  代码块 3

}
javascript 复制代码
var num = 5;

if(num > 10){

  console.log("大于 10");

}else if(num > 5){

  console.log("大于 5");

}else{

  console.log("小于等于 5");

}

循环语句

for 循环:for 循环用于重复执行一段代码,直到满足特定条件为止。

语法格式

javascript 复制代码
for (初始化表达式; 条件表达式; 更新表达式) {

  代码块

}

 * 解释:

   * 初始化表达式:通常用于初始化循环变量。

   * 条件表达式:在每次循环开始前进行判断,如果为真,则执行循环体;如果为假,则退出循环。

   * 更新表达式:在每次循环体执行完毕后更新循环变量。

 * 例如:

 for(let i = 0; i < 3; i++){

  console.log(i); // 输出 0、1、2

}

这里初始化变量 `i` 为 0 ,条件是 `i < 3` ,每次循环后 `i` 增加 1 。循环会执行 3 次,依次输出 0、1、2。

while 循环: while 循环也是用于重复执行一段代码,

javascript 复制代码
while (条件) {

  代码块

}

 * 先判断条件是否为真,如果为真,就执行代码块,然后再次判断条件,直到条件为假。

 * 例如:

 let count = 0;

while(count < 3){

  console.log(count); // 输出 0、1、2

  count++;

}

如果不注意在循环体中更新变量(如这里的 `count++` ),可能会导致死循环,因为条件一直为真。

do...while 循环do...while 循环和 while 循环类似,但它的区别在于不管条件是否为真,都会先执行一次代码块,然后再判断条件

语法格式

javascript 复制代码
do {

  代码块

} while (条件);
javascript 复制代码
{

  let num = 1; // 这个 num 只在这个花括号的作用域内有效

  do {

    console.log(num); // 输出 num 的值

    num++; // num 值加 1

  } while (num <= 5); // 只要 num 小于等于 5,就继续循环

}

循环语句区别

条件判断时机

for 循环:在每次循环开始前都会先执行条件表达式的判断。

while 循环:同样在每次循环开始前判断条件,但没有内置的初始化和更新表达式。

初始化和更新

for 循环:将初始化、条件判断和更新操作集中在一个语句中,结构更紧凑,适合有明确的初始化和更新逻辑的场景。

while 循环:没有内置的初始化和更新操作,需要在循环体内部手动处理。

执行条件

do...while 循环do...while 循环会先执行一次循环体,然后才判断条件。因此,它至少会执行一次循环体,即使条件一开始就不满足。

forwhile 循环:如果条件一开始就不满足,循环体可能一次都不执行。

适用点

for 循环

适用场景 :当你需要在循环中初始化一个变量,并且每次循环后需要更新这个变量时,for 循环是一个很好的选择。它将初始化、条件判断和更新操作集中在一个地方,代码更清晰。

示例

遍历数组或集合。

执行固定次数的循环。

javascript 复制代码
for (let i = 0; i < 5; i++) {

  console.log(i); // 输出 0, 1, 2, 3, 4

}

while 循环

适用场景 :当你需要在循环中动态地控制条件,或者循环的次数不确定时,while 循环更适合。它更灵活,因为你可以根据需要在循环体中动态地改变条件变量。

示例

读取用户输入,直到用户输入特定的值。

执行一个任务,直到某个条件满足。

javascript 复制代码
let num = 0;

while (num < 5) {

  console.log(num); // 输出 0, 1, 2, 3, 4

  num++;

}

**for 循环:**适合有明确的初始化和更新逻辑,循环次数相对确定的场景。

while 循环:适合循环次数不确定,或者需要在循环体中动态控制条件的场景。

break 语句

break 语句用于完全终止当前的循环,跳出循环体,继续执行循环之后的代码。

当你需要在满足某个条件时立即退出循环时,可以使用 break

常用于避免无限循环或在找到目标后提前退出循环。

javascript 复制代码
const numbers = [1, 3, 5, 12, 8, 15];

for (let i = 0; i < numbers.length; i++) {

  if (numbers[i] > 10) {

    console.log("找到第一个大于 10 的数字:", numbers[i]);

    break; // 找到后立即退出循环

  }

}

console.log("循环结束");

continue 语句

continue 语句用于跳过当前循环的剩余部分,直接开始下一次循环迭代。

当你需要跳过某些特定条件的迭代,但仍然继续执行后续的迭代时,可以使用 continue

常用于过滤掉不符合条件的元素,只处理符合条件的元素。

javascript 复制代码
const numbers = [1, 2, 3, 4, 5, 6];

for (let i = 0; i < numbers.length; i++) {

  if (numbers[i] % 2 !== 0) {

    continue; // 如果是奇数,跳过当前迭代

  }

  console.log("偶数:", numbers[i]);

}

breakcontinue 的区别

break

完全终止循环,跳出循环体,继续执行循环之后的代码。

用于提前退出循环。

continue

跳过当前迭代的剩余部分,直接开始下一次迭代。

用于跳过某些特定条件的迭代,但仍然继续执行后续的迭代。

至此,语法语句内容完成

对象

接下来,来接触一下对象

首先:此对象非彼对象,学校里面学好了说不定有对象

什么是编程中的对象呢:在 JavaScript 中,对象是一个独立的、可以存储多个值的实体,它由一系列的键值对(key-value pairs)组成。键(key)是对象的属性名称,值(value)可以是任何数据类型,包括数字、字符串、布尔值、函数(方法)等。你可以把对象想象成一个装满各种信息的"盒子"。

例如,一个描述人的对象:

javascript 复制代码
let person = {

  name: "张三",

  age: 25,

  isStudent: true,

  hobbies: ["阅读", "运动"],

  greet: function() {

    console.log("你好,我叫" + this.name);

  }

};

// 调用 greet 方法

person.greet();

在这个对象中:

nameageisStudent 是属性,它们的值分别是 "张三"25true

hobbies 是一个数组类型的属性,它的值是包含两个字符串的数组。

greet 是一个方法(即对象中的函数,在下一篇会详细介绍函数的),它可以输出 "你好,我叫张三"

创建对象

方法:对象字面量

最常见的方式是使用对象字面量来创建对象,就像上面示例中的 person 对象。这种方式简单直观,适合直接定义对象的属性和方法。

语法:

javascript 复制代码
let 对象名 = {

  属性1: 值1,

  属性2: 值2,

  // ...

};

访问对象的属性和方法

方法1:点语法

javascript 复制代码
console.log(person.name); // 访问属性

person.greet(); // 调用方法

方法2:方括号语法

javascript 复制代码
console.log(person["name"]);

person["greet"]();

添加、修改和删除属性

添加属性
复制代码
person.gender = "男"; // 添加属性
修改属性
复制代码
person.age = 26; // 修改属性
删除属性
复制代码
delete person.age; // 删除属性

对象的遍历

(遍历在之前的文章中讲过,就是一个盒子里有很多小球然后一个一个拿出来)

可以使用 for...in 循环来遍历对象的属性:

javascript 复制代码
for (let key in person) {

  console.log(key + ": " + person[key]);

}

可能听的云里雾里的,之后会有一篇关于传统前端实战的分析文章

数组

接下来我们来了解数组

什么是数组:数组是一种非常常用的数据结构,用于存储一组有序的值。这些值可以是数字、字符串、对象,甚至是其他数组。数组中的每个值都有一个索引(从 0 开始),可以通过索引来访问和操作数组中的元素。

(类似于我们学过的数学里的集合,但只是表现上类似而已)

创建数组

方法 :数组字面量

这是最常用的方式,直接用方括号 [] 包裹一组值。

javascript 复制代码
let fruits = ["苹果", "香蕉", "橙子"];

let numbers = [1, 2, 3, 4, 5];

let mixed = [1, "hello", true, { name: "张三" }, [1, 2, 3]];

访问数组元素

数组中的每个元素都有一个索引,从 0 开始。可以通过索引来访问和修改数组中的元素。

javascript 复制代码
let fruits = ["苹果", "香蕉", "橙子"];

// 访问元素

console.log(fruits[0]); // 输出 "苹果"

console.log(fruits[1]); // 输出 "香蕉"

// 修改元素

fruits[1] = "草莓";

console.log(fruits); // 输出 ["苹果", "草莓", "橙子"]

数组的常用方法

添加和删除元素

push():向数组末尾添加一个或多个元素,并返回新数组的长度。

javascript 复制代码
fruits.push("葡萄");

console.log(fruits); // 输出 ["苹果", "草莓", "橙子", "葡萄"]

pop():从数组末尾移除一个元素,并返回被移除的元素。

javascript 复制代码
let removedItem = fruits.pop();

console.log(removedItem); // 输出 "葡萄"

console.log(fruits); // 输出 ["苹果", "草莓", "橙子"]

shift():从数组开头移除一个元素,并返回被移除的元素。

javascript 复制代码
let firstItem = fruits.shift();

console.log(firstItem); // 输出 "苹果"

console.log(fruits); // 输出 ["草莓", "橙子"]

unshift():向数组开头添加一个或多个元素,并返回新数组的长度。

javascript 复制代码
fruits.unshift("樱桃");

console.log(fruits); // 输出 ["樱桃", "草莓", "橙子"]
查找元素

indexOf() :查找某个值在数组中的索引,如果找不到返回 -1

javascript 复制代码
let index = fruits.indexOf("橙子");

console.log(index); // 输出 2

(因为计数的时候第一个数字记为0,也就是说你觉的苹果应该是1但他的序号实际为0)

includes():检查数组是否包含某个值,返回布尔值。

javascript 复制代码
console.log(fruits.includes("草莓")); // 输出 true

console.log(fruits.includes("西瓜")); // 输出 false
遍历数组

for 循环

javascript 复制代码
for (let i = 0; i < fruits.length; i++) {

  console.log(fruits[i]);

}
数组的拷贝和拼接

slice():返回数组的一个浅拷贝,不会修改原数组。

javascript 复制代码
let newFruits = fruits.slice(1, 3); // 从索引 1 到 3(不包括 3)

console.log(newFruits); // 输出 ["草莓", "橙子"]

concat():将多个数组拼接成一个新数组,不会修改原数组。

javascript 复制代码
let moreFruits = ["西瓜", "芒果"];

let allFruits = fruits.concat(moreFruits);

console.log(allFruits); // 输出 ["樱桃", "草莓", "橙子", "西瓜", "芒果"]
数组的排序

sort():对数组进行排序,会修改原数组。

javascript 复制代码
let numbers = [3, 1, 4, 1, 5, 9];

numbers.sort();

console.log(numbers); // 输出 [1, 1, 3, 4, 5, 9]

如果需要按照数值大小排序,需要提供一个比较函数:

javascript 复制代码
numbers.sort(function(a, b) {

  return a - b; // 升序

});

console.log(numbers); // 输出 [1, 1, 3, 4, 5, 9]
数组的过滤和映射

filter():创建一个新数组,包含通过测试的所有元素,不会修改原数组。

javascript 复制代码
let evenNumbers = numbers.filter(function(num) {

  return num % 2 === 0;

});

console.log(evenNumbers); // 输出 [4]

map():创建一个新数组,其元素是调用一次提供的函数后的返回值,不会修改原数组。

javascript 复制代码
let squaredNumbers = numbers.map(function(num) {

  return num * num;

});

console.log(squaredNumbers); // 输出 [1, 1, 9, 16, 25, 81]

由于没有足够的实际生活应用,所以大家可能会觉得很莫名其妙,但是现在只要了解基础理论就行了,后面会有实践内容的

函数

在数学中函数的概念就像机器人一样,通过特定的指令做出特定的动作,在JavaScript开发中概念也差不多

函数的定义

函数是代码块,用于执行特定行为。在 JavaScript 中,可以通过多种方式定义函数。

函数声明:

以 function 关键字开头,后面跟着函数名、参数列表(括在圆括号中,用逗号分隔)和函数体(用大括号括起来)。

javascript 复制代码
function functionName (parameter1, parameter2, ...) {

    // 函数体,执行的代码

    // 可以使用 return 语句返回值

}

我们来分析一个例子

javascript 复制代码
function addNumbers (num1, num2) {

    let sum = num1 + num2;

    return sum;

}

这里定义了一个名为 

addNumbers 的函数,它接收两个参数 

num1 和 num2,将它们相加并将结果存储在变量 sum 中

然后通过 return 语句返回这个结果。

函数表达式:

它将函数赋值给一个变量。可以是匿名函数或者有名字的函数

javascript 复制代码
const functionName = function (parameter1, parameter2, ...) {

    // 函数体

};

比如

javascript 复制代码
const multiplyNumbers = function (num1, num2) {

    return num1 * num2;

};

或者

javascript 复制代码
const divideNumbers = function division (num1, num2) {

    return num1 / num2;

};

这样做的好处是函数可以作为一个值来传递,比如在事件处理等场景中非常有用。

函数的调用

调用函数时,使用函数名后跟一对圆括号,括号中包含实际参数(实参)。

javascript 复制代码
let result = addNumbers (5, 3);

console.log (result); // 输出 8

这里调用了之前定义的 addNumbers 函数,传入了实际参数 5 和 3,函数执行后返回它们的和 8,然后将这个结果赋值给变量 result

函数的参数

默认参数 :在定义函数时,可以给参数指定默认值。如果调用函数时没有提供对应的参数,就会使用默认值。

javascript 复制代码
function greet (name = "Guest") {

    console.log (`Hello, ${name}!`);

}

greet (); // 输出 "Hello, Guest!"

greet ("Alice"); // 输出 "Hello, Alice!"

参数的类型检查 :在 JavaScript 中,参数的类型是动态的。可以在函数内部使用 typeof 运算符来检查参数类型

javascript 复制代码
function checkType (value) {

    console.log (`The type of the parameter is: ${typeof value}`);

}

checkType (123); // 输出 "The type of the parameter is: number"

checkType ("Hello"); // 输出 "The type of the parameter is: string"

函数的返回值``使用 ``return 语句可以将值返回给调用者。如果函数中没有 ``return 语句,或者 ``return 后面没有值,返回值是 undefined。

javascript 复制代码
function sayHello () {

    console.log ("Hello!");

}

let result = sayHello ();

console.log (result); // 输出 undefined

这个函数只是输出了 "Hello!",没有返回任何值,所以 result 的值是 undefined

函数的作用域

函数作用域 :在函数内部声明的变量只能在函数内部访问,这是函数作用域。而变量的声明方式会影响其作用域。

javascript 复制代码
function createVariable () {

    var functionScopedVar = "I'm function - scoped";

    console.log (functionScopedVar);

}

createVariable (); // 正常输出

// console.log (functionScopedVar); // 会报错,因为变量只在函数内部

高阶函数

函数可以作为参数传递给其他函数。

javascript 复制代码
function execute (func, value) {

    return func (value);

}

function double (num) {

    return num * 2;

}

let result = execute (double, 5);

console.log (result); // 输出 10

这里 execute 是一个高阶函数,它接收一个函数 func 和一个值 value 作为参数,然后调用 func 函数并将 value 传递给它。

函数可以作为返回值从其他函数返回。

javascript 复制代码
function createMultiplier (multiplier) {

    return function (num) {

        return num * multiplier;

    };

}

let triple = createMultiplier (3);

console.log (triple (5)); // 输出 15

闭包

闭包是一个函数及其词法环境的组合。它可以访问其词法作用域中的变量。

javascript 复制代码
function createCounter () {

    let count = 0;

    return function () {

        count++;

        return count;

    };

}

let counter = createCounter ();

console.log (counter ()); // 输出 1

console.log (counter ()); // 输出 2

这里 createCounter 函数返回了一个闭包函数。闭包函数可以访问 createCounter 函数中的变量 count,并能够修改它。每次调用闭包函数时,count 的值都会增加并返回新的值。

递归函数

递归函数是指在函数内部调用自身的函数。

javascript 复制代码
function factorial (n) {

    if (n === 0) {

        return 1;

    } else {

        return n * factorial (n - 1);

    }

}

console.log (factorial (5)); // 输出 120

这个 factorial 函数计算了 5 的阶乘。它不断调用自身,每次将参数减 1,直到参数为 0 时返回 1,然后逐层返回计算结果。

立即调用函数表达式(IIFE)

它是一种定义并立即执行的函数模式,用于创建一个封闭的作用域,避免污染全局作用域。

javascript 复制代码
(function () {

    let privateVariable = "I'm private";

    console.log (privateVariable);

})();

// console.log (privateVariable); // 会报错,变量在 IIFE 内部

这个函数定义后立即执行,privateVariable 在 IIFE 内部被声明和使用,外部无法访问它。

类的基本定义

使用 class 关键字定义一个类,类名首字母通常大写,以区分于其他变量名。

javascript 复制代码
class MyClass {

  // 类体

}

示例:定义一个简单的 "Person" 类,用于表示一个人。

javascript 复制代码
class Person {

  // 类体暂时为空

}

构造函数

构造函数是一个特殊的方法,用于初始化对象的属性。它使用 constructor 关键字定义。

当使用 new 关键字创建类的实例时,构造函数会被自动调用。

示例:在 "Person" 类中添加构造函数,用于初始化人的姓名和年龄。

javascript 复制代码
class Person {

  constructor(name, age) {

    this.name = name; // 将传入的 name 参数赋值给对象的 name 属性

    this.age = age; // 将传入的 age 参数赋值给对象的 age 属性

  }

}

// 创建 Person 类的实例

const person1 = new Person('Alice', 25);

console.log(person1.name); // 输出:Alice

console.log(person1.age); // 输出:25

类的方法

在类中定义的方法是对象的行为,用于实现对象的功能。

方法的定义方式与普通函数类似,但要写在类的内部。

示例:在 "Person" 类中添加一个方法,用于打印个人信息。

javascript 复制代码
class Person {

  constructor(name, age) {

    this.name = name;

    this.age = age;

  }

  // 定义一个方法

  introduce() {

    console.log(`My name is ${this.name}, I am ${this.age} years old.`);

  }

}

const person1 = new Person('Alice', 25);

person1.introduce(); // 输出:My name is Alice, I am 25 years old.

类的继承

通过继承,一个类可以继承另一个类的属性和方法,从而实现代码的复用。

使用 extends 关键字实现继承,子类通过 super() 关键字调用父类的构造函数。

示例:创建一个 "Student" 类,它继承自 "Person" 类,用于表示学生。

javascript 复制代码
class Person {

  constructor(name, age) {

    this.name = name;

    this.age = age;

  }

  introduce() {

    console.log(`My name is ${this.name}, I am ${this.age} years old.`);

  }

}

// Student 类继承 Person 类

class Student extends Person {

  constructor(name, age, grade) {

    super(name, age); // 调用父类的构造函数,初始化 name 和 age

    this.grade = grade; // 子类独有的属性

  }

  // 子类自己的方法

  study() {

    console.log(`I am a student in grade ${this.grade}.`);

  }

}

const student1 = new Student('Bob', 18, '10th');

student1.introduce(); // 继承自父类的方法

student1.study(); // 子类自己的方法

静态方法和属性

静态方法和属性属于类本身,而不是类的实例。使用 static 关键字定义。

静态方法通过类名直接调用,静态属性也通过类名访问。

示例:在 "Person" 类中添加一个静态方法和一个静态属性。

javascript 复制代码
class Person {

  constructor(name, age) {

    this.name = name;

    this.age = age;

  }

  introduce() {

    console.log(`My name is ${this.name}, I am ${this.age} years old.`);

  }

  // 静态方法

  static sayHello() {

    console.log('Hello, everyone!');

  }

  // 静态属性

  static species = 'Homo sapiens';

}

Person.sayHello(); // 调用静态方法

console.log(Person.species); // 访问静态属性

访问修饰符

在 JavaScript 中,类的属性和方法默认都是公开的(public),即可以在类的外部访问。

也可以使用 # 来定义私有属性和方法,它们只能在类的内部访问。

示例:在 "Person" 类中添加一个私有属性和一个私有方法。

javascript 复制代码
class Person {

  constructor(name, age) {

    this.name = name;

    this.age = age;

    this.#privateData = 'This is private data'; // 私有属性

  }

  introduce() {

    console.log(`My name is ${this.name}, I am ${this.age} years old.`);

    this.#privateMethod(); // 调用私有方法

  }

  // 私有方法

  #privateMethod() {

    console.log(this.#privateData);

  }

}

const person1 = new Person('Alice', 25);

person1.introduce();

// 以下代码会报错,因为无法在类外部访问私有属性和方法

// console.log(person1.#privateData);

// person1.#privateMethod();

接下来我们整合内容,分析一个全面的实例

示例

目标

创建一个简单的图书管理系统,包含以下功能:

定义图书类(Book),包含书名、作者和页数。

定义图书馆类(Library),可以添加图书、列出所有图书、借阅图书和归还图书。

使用数组存储图书数据。

使用函数实现图书的借阅和归还逻辑。

使用类的继承扩展功能。

javascript 复制代码
// 数据类型

// 基本数据类型:String, Number, Boolean, Undefined, Null

// 复合数据类型:Object, Array

// 运算

// 算术运算符:+、-、*、/、%

// 比较运算符:==、===、!=、!==、>、<、>=、<=

// 逻辑运算符:&&、||、!

// 语法语句

// if...else、for、while、switch

// 对象

// 使用对象表示图书

const book1 = {

  title: 'JavaScript高级程序设计',

  author: 'Nicholas C. Zakas',

  pages: 600,

  isAvailable: true

};

const book2 = {

  title: '你不知道的JavaScript',

  author: 'Kyle Simpson',

  pages: 300,

  isAvailable: true

};

// 数组

// 使用数组存储图书

const books = [book1, book2];

// 函数

// 借阅图书的函数

function borrowBook(book) {

  if (book.isAvailable) {

    book.isAvailable = false;

    console.log(`您已成功借阅《${book.title}》。`);

  } else {

    console.log(`《${book.title}》当前不可借阅。`);

  }

}

// 归还图书的函数

function returnBook(book) {

  book.isAvailable = true;

  console.log(`您已成功归还《${book.title}》。`);

}

// 类

// 定义图书类

class Book {

  constructor(title, author, pages) {

    this.title = title;

    this.author = author;

    this.pages = pages;

    this.isAvailable = true;

  }

}

// 定义图书馆类

class Library {

  constructor() {

    this.books [];

 =  }

  // 添加图书

  addBook(book) {

    this.books.push(book);

    console.log(`图书《${book.title}》已添加到图书馆。`);

  }

  // 列出所有图书

  listBooks() {

    console.log('图书馆中的图书:');

    this.books.forEach(book => {

      console.log(`- ${book.title}(作者:${book.author},页数:${book.pages},状态:${.isbookAvailable ? '可借阅' : '已借出'})`);

    });

  }

  // 借阅图书

  borrowBook(title) {

    const book = this.books.find(book => book.title === title);

    if (book) {

      if (book.isAvailable) {

        book.isAvailable = false;

        console.log(`您已成功借阅《${book.title}》。`);

      } else {

        console.log(`《${book.title}》当前不可借阅。`);

      }

    } else {

      console.log(`图书馆中没有找到《${title}》。`);

    }

  }

  // 归还图书

  returnBook(title) {

    const book = this.books.find(book => book.title === title);

    if (book) {

      book.isAvailable = true;

      console.log(`您已成功归还《${book.title}》。`);

    } else {

      console.log(`图书馆中没有找到《${title}》。`);

    }

  }

}

// 类的继承

// 定义一个特殊图书馆类,继承自 Library

class SpecialLibrary extends Library {

  constructor() {

    super();

    this.specialBooks = [];

  }

  // 添加特殊图书

  addSpecialBook(book) {

    this.specialBooks.push(book);

    console.log(`特殊图书《${book.title}》已添加到特殊图书馆。`);

  }

  // 列出特殊图书

  listSpecialBooks() {

    console.log('特殊图书馆中的特殊图书:');

    this.specialBooks.forEach(book => {

      console.log(`- ${book.title}(作者:${book.author},页数:${book.pages},状态:${book.isAvailable ? '可借阅' : '已借出'})`);

    });

  }

}

// 测试代码

// 创建图书馆实例

const myLibrary = new Library();

// 创建图书实例

const book3 = new Book('JavaScript权威指南', 'David Flanagan', 1200);

const book4 = new Book('深入理解计算机系统', 'Randal E. Bryant', 1000);

// 添加图书到图书馆

myLibrary.addBook(book3);

myLibrary.addBook(book4);

// 列出所有图书

myLibrary.listBooks();

// 借阅图书

myLibrary.borrowBook('JavaScript权威指南');

myLibrary.listBooks();

// 归还图书

myLibrary.returnBook('JavaScript权威指南');

myLibrary.listBooks();

// 创建特殊图书馆实例

const specialLibrary = new SpecialLibrary();

// 添加特殊图书

specialLibrary.addSpecialBook(book1);

specialLibrary.addSpecialBook(book2);

// 列出特殊图书

specialLibrary.listSpecialBooks();

数据类型:使用了基本数据类型(如字符串、数字、布尔值)和复合数据类型(对象、数组)。

运算:在判断图书是否可借阅时使用了比较运算符和逻辑运算符。

语法语句 :使用了 if...elseforwhile 等语句。

对象:通过对象表示图书,包含书名、作者、页数和是否可借阅的状态。

数组:使用数组存储图书数据,方便管理和遍历。

函数:定义了借阅和归还图书的函数,封装了逻辑。

:定义了 Book 类表示图书,Library 类表示图书馆,SpecialLibrary 类继承自 Library 类,扩展了功能。

至此,JavaScript完成,传统前端开发也完成了

相关推荐
安全系统学习几秒前
【网络安全】文件上传型XSS攻击解析
开发语言·python·算法·安全·web安全
赛博丁真Damon40 分钟前
【VSCode插件】【p2p网络】为了硬写一个和MCP交互的日程表插件(Cursor/Trae),我学习了去中心化的libp2p
前端·cursor·trae
江城开朗的豌豆1 小时前
Vue的keep-alive魔法:让你的组件"假死"也能满血复活!
前端·javascript·vue.js
尤物程序猿1 小时前
深入理解链表数据结构:从Java LinkedList到自定义实现
开发语言·python
DanceDonkey1 小时前
泛型方法调用需要显示指定泛型类型的场景
开发语言·windows·python
BillKu1 小时前
Vue3 + TypeScript 中 let data: any[] = [] 与 let data = [] 的区别
前端·javascript·typescript
GIS之路1 小时前
OpenLayers 调整标注样式
前端
爱吃肉的小鹿1 小时前
Vue 动态处理多个作用域插槽与透传机制深度解析
前端
GIS之路1 小时前
OpenLayers 要素标注
前端
前端付豪1 小时前
美团 Flink 实时路况计算平台全链路架构揭秘
前端·后端·架构