JavaScript笔记 | 青训营

92 阅读9分钟

JavaScript笔记 | 青训营

JavaScript 是一种广泛用于网页开发的编程语言,它为网页赋予了动态和交互性。它是一门轻量级的脚本语言,可嵌入到HTML页面中,与HTML和CSS一同构成了现代网页的三大基石。在本篇笔记中,我们将介绍 JavaScript 的基础知识,包括数据类型、变量、运算符、控制流等。

1. 数据类型

JavaScript 具有动态类型,它有七种基本数据类型:

  1. 数字(Number):表示整数或浮点数,例如:42、3.14。
  2. 字符串(String):表示文本数据,使用单引号或双引号括起来,例如:"Hello, World!"。
  3. 布尔(Boolean):表示真或假,只有两个值:true 或 false。
  4. undefined:表示变量声明但未赋值时的默认值。
  5. null:表示空或无值。
  6. 对象(Object):表示复杂的数据结构,比如数组、函数等。
  7. 符号(Symbol):表示唯一且不可变的值。

2. 变量与常量

在 JavaScript 中,可以使用 varletconst 关键字声明变量和常量。其中:

  • var 是旧的变量声明方式,它存在变量提升(hoisting)的问题,不推荐在现代代码中使用。
  • let 声明的变量是块级作用域的,可以在同一作用域内重新赋值。
  • const 声明的常量也是块级作用域的,一旦赋值后不可再修改。

3. 运算符

JavaScript 支持多种运算符,包括算术运算符、比较运算符、逻辑运算符等。常见的运算符有:

  • 算术运算符:+(加法)、-(减法)、*(乘法)、/(除法)、%(取模)等。
  • 比较运算符:==(等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)等。
  • 逻辑运算符:&&(逻辑与)、||(逻辑或)、!(逻辑非)等。

4. 控制流

控制流是编程语言中用于控制程序执行流程的结构。在 JavaScript 中,我们可以使用条件语句和循环语句来实现控制流。

4.1 条件语句

条件语句用于根据条件的真假来执行不同的代码块。

4.1.1 if 语句

if 语句是最简单的条件语句,它根据给定的条件来决定是否执行代码块。如果条件为真(true),则执行 if 代码块;否则,跳过该代码块。

const age = 20;

if (age >= 18) {
  console.log("成年人");
} else {
  console.log("未成年人");
}

4.1.2 else if 语句

如果有多个条件需要判断,可以使用 else if 语句来检查额外的条件。

const score = 85;

if (score >= 90) {
  console.log("优秀");
} else if (score >= 80) {
  console.log("良好");
} else if (score >= 60) {
  console.log("及格");
} else {
  console.log("不及格");
}

4.1.3 switch 语句

switch 语句用于根据表达式的值执行不同的代码块。每个 case 表达式都会与 switch 表达式进行比较,如果匹配则执行对应的代码块。可以使用 break 关键字来结束当前 case 分支的执行。

const day = "Monday";

switch (day) {
  case "Monday":
    console.log("星期一");
    break;
  case "Tuesday":
    console.log("星期二");
    break;
  case "Wednesday":
    console.log("星期三");
    break;
  default:
    console.log("其他");
}

4.2 循环语句

循环语句允许我们多次执行同一段代码,可以用于遍历数组、重复操作等。

4.2.1 for 循环

for 循环是最常见的一种循环结构,它通过一个初始条件、一个终止条件和一个递增表达式来控制循环的执行次数。

for (let i = 0; i < 5; i++) {
  console.log(i);
}

4.2.2 while 循环

while 循环会在给定条件为真的情况下一直执行代码块,直到条件为假。

let i = 0;
while (i < 5) {
  console.log(i);
  i++;
}

4.2.3 do-while 循环

do-while 循环是一种后测试循环,它会先执行一次代码块,然后再检查条件是否为真。只要条件满足,就会继续执行循环。

let i = 0;
do {
  console.log(i);
  i++;
} while (i < 5);

4.2.4 break 和 continue

在循环中,我们还可以使用 breakcontinue 关键字来控制循环的执行。

  • break: 终止循环,立即跳出循环体。
  • continue: 终止当前迭代并跳到下一次迭代,继续执行循环。
for (let i = 0; i < 5; i++) {
  if (i === 3) {
    break; // 当 i 等于 3 时跳出循环
  }
  console.log(i);
}

for (let i = 0; i < 5; i++) {
  if (i === 3) {
    continue; // 当 i 等于 3 时跳过当前迭代,继续下一次迭代
  }
  console.log(i);
}

以上是 JavaScript 中常见的控制流语句的用法。这些结构可以帮助我们根据不同的条件执行不同的代码块,或者重复执行一段代码。了解和熟练使用这些语句对于编写更加灵活和功能强大的程序非常重要。

5.数组

5.1 创建数组

在 JavaScript 中,我们可以使用多种方式来创建数组:

  1. 使用数组字面量:最常用的方法是使用方括号 [] 来表示一个数组,其中的元素用逗号分隔。
const numbers = [1, 2, 3, 4, 5];
const fruits = ['apple', 'banana', 'orange'];
  1. 使用 new 关键字:使用 new Array() 可以创建一个空数组或指定数组的长度。
const emptyArray = new Array();
const arrayWithLength = new Array(5); // 创建一个包含 5 个 undefined 的数组

5.2 访问数组元素

数组中的元素可以通过索引来访问,数组的索引从 0 开始,依次递增。要访问数组中的元素,只需使用方括号加上索引值。

const numbers = [1, 2, 3, 4, 5];
console.log(numbers[0]); // 输出:1
console.log(numbers[2]); // 输出:3

5.3 修改数组元素

可以通过索引来修改数组中的元素。

const numbers = [1, 2, 3, 4, 5];
numbers[2] = 10; // 修改索引为 2 的元素为 10
console.log(numbers); // 输出:[1, 2, 10, 4, 5]

5.4 数组长度

可以通过 length 属性获取数组的长度(即数组中元素的个数)。

const numbers = [1, 2, 3, 4, 5];
console.log(numbers.length); // 输出:5

5.5 常用数组方法

JavaScript 提供了许多有用的数组方法来处理和操作数组:

  • push(): 将一个或多个元素添加到数组的末尾。
  • pop(): 删除并返回数组的最后一个元素。
  • shift(): 删除并返回数组的第一个元素。
  • unshift(): 在数组的开头添加一个或多个元素。
  • slice(): 从原数组中返回指定起始索引到结束索引之间的新数组。
  • splice(): 用于添加或删除元素,并可以同时修改原数组。
  • concat(): 用于连接两个或多个数组。
  • indexOf(): 返回指定元素在数组中的索引,如果不存在则返回 -1。
  • forEach(): 遍历数组中的每个元素,并对每个元素执行指定的回调函数。
const numbers = [1, 2, 3, 4, 5];

numbers.push(6); // 添加元素 6 到末尾
numbers.pop(); // 删除末尾的元素 5
numbers.shift(); // 删除开头的元素 1

const slicedArray = numbers.slice(1, 3); // 返回索引为 1 到 2 的子数组 [2, 3]

const index = numbers.indexOf(3); // 返回元素 3 的索引,此处 index 为 1

numbers.forEach((num) => {
  console.log(num); // 依次输出数组中的元素
});

以上仅是数组用法的基础介绍,实际上数组还有很多高级功能和方法,比如 map()filter()reduce() 等。掌握数组的用法对于编写复杂的 JavaScript 应用非常重要,因此建议进一步深入学习和实践,以熟练掌握数组的各种操作。

6. 函数

在 JavaScript 中,函数是一种用于封装可重复使用代码块的机制。它们允许我们将一组操作组织在一起,然后通过函数名来调用和执行这些操作。函数在 JavaScript 中是一等公民,这意味着它们可以被当作变量来传递、赋值、作为参数传递给其他函数,或者从其他函数中返回。

6.1 函数的定义与调用

在 JavaScript 中,可以使用 function 关键字来定义函数。定义函数包含函数名、参数列表以及函数体,函数名用于调用函数。

// 定义函数
function greet(name) {
  console.log("Hello, " + name + "!");
}

// 调用函数
greet("Alice"); // 输出:Hello, Alice!
greet("Bob");   // 输出:Hello, Bob!

6.2 函数的参数

函数可以接受参数,这些参数可以在函数体内使用。函数可以有零个或多个参数。

function add(a, b) {
  return a + b;
}

const result = add(5, 3);
console.log(result); // 输出:8

6.3 函数的返回值

函数可以通过 return 关键字返回一个值,如果函数没有明确返回值,则默认返回 undefined

function multiply(a, b) {
  return a * b;
}

const product = multiply(4, 6);
console.log(product); // 输出:24

6.4 匿名函数和函数表达式

除了使用函数声明方式外,我们还可以使用匿名函数和函数表达式来创建函数。

// 匿名函数
const sayHello = function() {
  console.log("Hello!");
};

// 函数表达式
const divide = function(a, b) {
  return a / b;
};

sayHello();          // 输出:Hello!
const result = divide(10, 2);
console.log(result); // 输出:5

6.5 箭头函数

箭头函数是 ES6 引入的一种简洁的函数定义语法,它使用 => 符号来定义函数,可以更简单地写出匿名函数。

// 箭头函数
const square = (x) => {
  return x * x;
};

const area = (width, height) => width * height;

console.log(square(5)); // 输出:25
console.log(area(3, 4)); // 输出:12

6.6 函数作为参数

由于函数在 JavaScript 中是一等公民,我们可以将函数作为参数传递给其他函数,实现更加灵活和抽象的编程。

function applyOperation(x, y, operation) {
  return operation(x, y);
}

const add = (a, b) => a + b;
const multiply = (a, b) => a * b;

const result1 = applyOperation(3, 5, add);      // 结果:8
const result2 = applyOperation(3, 5, multiply); // 结果:15

6.7 函数闭包

JavaScript 的函数具有闭包特性,它允许函数访问其定义时的作用域中的变量,即使函数在定义的作用域之外执行。

function outer() {
  const x = 10;

  function inner() {
    console.log(x); // 内部函数可以访问外部函数作用域的变量 x
  }

  return inner;
}

const innerFunc = outer();
innerFunc(); // 输出:10

以上是 JavaScript 中函数的基本用法。函数是代码模块化和重用的重要工具,它使我们能够更有效地组织代码并实现功能模块化。理解函数的概念以及灵活地使用它们将使你在 JavaScript 编程中更加得心应手。

7.类

在 JavaScript 中,类是一种面向对象编程的重要概念,它允许我们创建具有相同属性和方法的对象集合。类可以看作是一种模板或蓝图,用于创建实例化对象。ES6 引入了类的语法,使得在 JavaScript 中创建和使用类更加简单和易于理解。

7.1 定义类

使用 class 关键字来定义一个类。类可以包含构造函数(constructor)和其他方法。

class Person {
  // 构造函数
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  // 方法
  sayHello() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  }
}

7.2 创建对象实例

使用 new 关键字来创建类的实例。构造函数将被调用,创建一个新的对象,并返回该对象的引用。

const person1 = new Person("Alice", 30);
const person2 = new Person("Bob", 25);

person1.sayHello(); // 输出:Hello, my name is Alice and I am 30 years old.
person2.sayHello(); // 输出:Hello, my name is Bob and I am 25 years old.

7.3 类的继承

类之间可以通过继承建立父子关系。子类继承父类的属性和方法,并可以拥有自己的独特属性和方法。

class Student extends Person {
  constructor(name, age, major) {
    super(name, age); // 调用父类的构造函数
    this.major = major;
  }

  introduce() {
    console.log(`I am studying ${this.major}.`);
  }
}

7.4 方法重写

子类可以重写从父类继承的方法,即覆盖父类中相同名称的方法。

class Student extends Person {
  // ...

  sayHello() {
    console.log(`Hello, my name is ${this.name}, I am ${this.age} years old, and I am studying ${this.major}.`);
  }
}

7.5 静态方法

在类中,可以使用 static 关键字定义静态方法。静态方法属于类本身,而不是类的实例。它们可以通过类名直接调用,无需创建对象。

class MathUtility {
  static add(a, b) {
    return a + b;
  }

  static multiply(a, b) {
    return a * b;
  }
}

const sum = MathUtility.add(3, 5);      // 输出:8
const product = MathUtility.multiply(3, 5); // 输出:15

7.6 getter 和 setter 方法

使用 getset 关键字可以创建 getter 和 setter 方法,允许我们访问和修改类的属性。

class Rectangle {
  constructor(width, height) {
    this._width = width;
    this._height = height;
  }

  get area() {
    return this._width * this._height;
  }

  set width(newWidth) {
    if (newWidth > 0) {
      this._width = newWidth;
    }
  }

  set height(newHeight) {
    if (newHeight > 0) {
      this._height = newHeight;
    }
  }
}

const rect = new Rectangle(5, 3);
console.log(rect.area); // 输出:15

rect.width = 7;
console.log(rect.area); // 输出:21

以上是 JavaScript 中类的基本用法。类是一种非常强大的工具,它让我们可以更好地组织代码,并使对象之间的关系更加清晰和易于管理。类的概念是面向对象编程的核心,了解类的使用将有助于你构建更复杂和模块化的应用程序。

8. 事件处理

事件处理是在 JavaScript 中用于对用户操作或浏览器发生的事件做出响应的一种机制。通过事件处理,我们可以捕获用户的交互行为(如点击、鼠标移动、键盘输入等)或者监听浏览器触发的事件(如页面加载、网络请求完成等),然后执行相应的代码来实现交互和动态效果。

8.1 事件监听器

在 JavaScript 中,我们可以使用事件监听器(Event Listener)来捕获事件并执行相应的回调函数。事件监听器绑定在特定的 DOM 元素上,当指定类型的事件发生时,回调函数将被调用。

const button = document.getElementById("myButton");

// 添加点击事件监听器
button.addEventListener("click", function() {
  console.log("Button clicked!");
});

8.2 常见事件类型

在事件处理中,有许多常见的事件类型可供选择。以下是一些常见的 DOM 事件类型:

  • click:鼠标点击事件。
  • mouseover / mouseout:鼠标移入 / 移出事件。
  • keydown / keyup:键盘按下 / 松开事件。
  • change:表单元素值改变事件(如 input、select 等)。
  • submit:表单提交事件。
  • load:页面或图片加载完成事件。
  • scroll:滚动事件。
  • focus / blur:元素获取 / 失去焦点事件。

8.3 事件对象

事件监听器的回调函数可以接收一个事件对象(Event Object),该对象包含与事件相关的信息,如事件类型、触发的元素、鼠标位置等。

document.addEventListener("click", function(event) {
  console.log("Event type: " + event.type);
  console.log("Target element: " + event.target);
  console.log("Mouse position: " + event.clientX + ", " + event.clientY);
});

8.4 事件冒泡与阻止默认行为

在 DOM 中,事件通常会向上冒泡到其父元素,即从触发事件的元素开始,逐级向上通知父元素,直到到达文档根。这种行为称为事件冒泡(Event Bubbling)。有时候我们需要阻止事件冒泡,可以使用 event.stopPropagation() 方法。

另外,有些事件会有默认行为,比如 <a> 元素的点击会导致页面跳转。如果我们想要阻止默认行为,可以使用 event.preventDefault() 方法。

const link = document.getElementById("myLink");

link.addEventListener("click", function(event) {
  event.preventDefault(); // 阻止默认行为,不跳转到链接地址
  console.log("Link clicked!");
});

8.5 动态添加和移除事件监听器

我们可以通过 addEventListener 方法来动态地添加事件监听器,通过 removeEventListener 方法来移除事件监听器。

const button = document.getElementById("myButton");

function clickHandler() {
  console.log("Button clicked!");
}

button.addEventListener("click", clickHandler);

// 在一段时间后移除事件监听器
setTimeout(function() {
  button.removeEventListener("click", clickHandler);
}, 5000);

8.6 jQuery 中的事件处理

如果你使用了 jQuery 库,它提供了一种更简洁的方式来处理事件。

$("#myButton").click(function() {
  console.log("Button clicked!");
});

以上是事件处理在 JavaScript 中的基本用法。通过事件处理,我们可以实现与用户的交互和页面行为相关的逻辑。合理运用事件处理,可以增强用户体验并使网页交互更加动态丰富。