JavaScript 基础

发布于:2025-05-10 ⋅ 阅读:(13) ⋅ 点赞:(0)

JS概念

JS基础概念

  • JS是一种运行在客户端(浏览器)的编程语言, 实现人机交换结果

  • 作用:

    • 网页特效
    • 表单验证
    • 数据交互
    • 服务端编程(node.js)
  • JS的组成

    • ECMAScript—javaScript语言基础
    • Web APIs—(DOM: 页面文档对象模型)(BOM: 浏览器对象模型)

JS书写

  • 位置

    • 内部: 写到< /body >上方

      <script>
        alert('hello js');
      </script>
      </body>
      
    • 外部: 以.js结尾的文件, 然后引入至html中, 引入位置与内部一致

      <script src="./index.js"></script>
      </body>
      
    • 内联: 类似于引入CSS样式

      <button onclick="alert('hello world')">f**k me</button>
      
  • 注释写法: 与C语言一致, 即 // 和 /* */

  • 结束符: 以 ; 为结束符, 在实际开发中可写可不写, 但要统一

字面量

在计算机科学中, 字面量是在计算机中描述 事和物

JS语法

输入和输出

  • 输出语法

    document.write("<h1> 输出至文档 </h1>");
    
    alert("警示框");
    
    console.log("控制台打印");
    
  • 输入语法

    prompt('在警示框内输入');
    

变量基础

  • 定义

    • 用来存储数据的"盒子"
    • 变量是容器, 而非数据
  • 使用(与C语言差不多)

1. 声明变量: 
let age;

2. 赋值变量:
age = 18;
  • 命名规则与规范

    • 规则:

      • 不能用关键字
      • 只能由下划线、字母、数字、$组成, 不能数字开头
      • 字母严格区分大小写
    • 规范:

      • 起名要有意义, 让人能看的懂
      • 起名遵守小驼峰命名法
  • var的缺点

    1. 可以先使用, 再声明(不合理)
    2. var可以重复声明
    3. 比如变量提升、全局变量、没有块级作用域等
数组
  • 数组是一种将一组数据存储在单个变量名下的优雅方式

    let numArr = [1, 2, 3, 4, 5];
    
  • 数组是有序的, 编号从0开始

    console.log(numArr[0]);       //打印1
    
  • 数组内的数据类型是任意的, 不必一致

  • 用.length属性获得数组的长度

    console.log(numArr.length);  
    

常量基础

  • 定义: 使用const声明的变量称为常量, 声明时必须赋值, 不允许再次赋值

    const PI = 3.14;
    

数据类型

  • 意义:

    1. 更加充分利用高效的利用内存
    2. 更加方便程序员使用数据

基本数据类型

  • JS 是一门弱数据类型的语言, 不同于 java

  • 有以下几种类型(基本数据类型)

    1. number
    2. string
    3. boolean
    4. undefined
    5. null
  • 如何检测数据类型

typeof(X);
或
typeof X;
  • 如何转换数据类型

    • 隐式转换

      1. ‘+’ 两边只要有一个是字符串, 就会把另外一个转为字符串, 但+"123"的操作会把字符型转换为数字型

      2. ‘-’, ‘*’, ‘/’, '%'等运算符, 会把字符串转换为数字类型

let numSt = "123";
let numSt1 = numSt + 456; // num = "123456"

let num = +numSt; // num = 123
  • 显式转换

    1. Number(数据) — 转化为数字型
    2. parseInt(数据) — 只保留整数()
    3. parseFloat(数据) — 保留小数

数字类型(number)

  • 算术运算符: + 、- 、* 、/ 、% (优先级为日常运算)

  • 当运算时有错误的数据类型会输出 NaN, 任何对 NaN 的操作都会返回 NaN

字符串类型(string)

  • 通过单引号, 双引号, 反引号包裹的数据为字符串类型

  • 引号之间可以相互嵌套, 但不能相同嵌套

  • 可以使用 + 来拼接字符串(数字相加, 字符相连, 字符串 + 数字 = 字符串)

  • 当然, JS 和 C 语言一样, 可以格式化输出

    let str = `javaScript`;
    console.log("%s", str);
    
  • 模版字符串, 相较于格式化输出更方便, 字符串必须用反引号, 变量放入${}内

    console.log(`这是${str}`);
    

布尔类型(bool)

  • 只有两个值, true 和 false, 表示判断真假

  • “”、0、NaN、null、undefined 都为 false, 其他都为 true

未定义类型

  • 只有一个值—undefined, 当声明变量时却没赋值, 则这个变量为未定义类型

null(空类型)

  • 只有一个值—null, 把 null 作为尚未创建的对象

运算符

  • 类型:

    1. 赋值运算符
    2. 自增自减运算符
    3. 比较运算符
    4. 逻辑运算符
  • 运算符优先级: 与C语言等其他语言相同

赋值运算符

  • 对变量进行赋值的运算符, 如 " = ", 其他赋值运算(+=)和 C 语言大差不差

自增自减运算符

  • 自增/自减运算符" ++ ", " – ". 用法和 C 语言相同

比较运算符

  • " === " 表示左右类型是否全等, " !== " 表示左右两边是否不全等

  • " == "运算符也会进行隐式转换, 转换为数字型

  • NaN 不等于任何类型和值, 包括它自己, 参与它的运算返回值均为 false

  • 比较结果为 bool 类型

  • 字符串比较, 是比较的字符对应的 ascll 码

逻辑运算符

  • 包括" && ", " || ", " ! ", 用法和 C 语言相同

隐式类型转换

  • 运算符的左右两边的数据类型不同时, 会进行隐式类型转换, 转换规则如下:

    • 布尔值和数字值: 布尔值转换为数字值 1/0, 数字值转换为布尔值 true/false
    • 字符串和数字值: 字符串转换为数字值, 数字值转换为字符串
    • 字符串和布尔值: 布尔值转换为字符串"true"/“false”
    • 其他类型转换为字符串
    • 隐式类型转换的优先级低于其他运算符, 如" - "运算符, 它会先将字符串转换为数字值再进行运算
    • 只有" + "可以将数字型转换为字符串型, 在字符串与数字的运算中
    • 隐式类型转换的常见场景:
      • 条件判断语句中的条件表达式
      • 算术运算符的操作数
      • 赋值运算符的右侧表达式
        • 函数调用的参数
        • 变量初始化表达式
        • 数组元素赋值
        • 对象属性赋值
        • 等等

运算符的特殊行为(类型转换总结)

  • + 运算符:当任一操作数为字符串时,执行字符串拼接
1 + "2" // "12"
true + "false" // "truefalse"
  • 其他算术运算符(-, *, /, %):将操作数转换为数字
"5" - 3 // 2
"10" / "2" // 5
  • 常见隐式转换场景
  1. 条件判断
if (1) { /* 会执行,因为1被转换为true */ }
if ("") { /* 不会执行,空字符串被转换为false */ }
  1. 算术运算
let result = "10" * 2; // 20
  1. 比较运算
"10" == 10 // true (类型转换后比较)
"10" === 10 // false (严格相等,不转换类型)
  1. 其他场景
// 函数参数
function log(x) { console.log(x) }
log(123); // 数字
log("123"); // 字符串

// 数组元素
let arr = [1, "2", true];

// 对象属性
let obj = {
  num: "123",
  bool: 1
};

注意事项:
== 会进行隐式类型转换,而 === 不会

+ 是唯一会优先进行字符串拼接的算术运算符

某些转换结果可能出乎意料:

[] + {} // "[object Object]"

# 语句和结构

## 选择(分支)结构

### if 语句

```javascript
let num = +prompt("请输入一个数字");
if (num % 4 === 0 && num % 100 !== 0) {
  alert("true");
} else {
  alert("false");
}

switch 语句

注: switch 匹配时是全等(类型和值), 不只是数值相等

let num1 = +prompt("输入第一个数字");
let num2 = +prompt("输入第二个数字");

let sp = prompt("输入运算符");

switch (sp) {
  case "+":
    alert(num1 + num2);
    break;
  case "-":
    alert(num1 - num2);
    break;
  case "*":
    alert(num1 * num2);
    break;
  case "/":
    alert(num1 / num2);
    break;
  default:
    console.log("运算符错误");
}

基本循环语句

while 语句

let num = 0;
let cut = 0;
while (cut < 10) {
  num += 2;
  cut++;
}
alert(num);
  • 循环三要素

    1. 变量起始值
    2. 终止条件
    3. 变量变化量
  • break 语句: 跳出循环

  • continue 语句: 跳过本次循环, 继续下一次循环

for 语句

注: 在遍历数组时, 数组越界时会打印 undefined

for (let i = 0; i < 10; i++) {
  console.log(i);
}
  • for 语句三要素

    1. 初始化
    2. 循环条件
    3. 变化量
  • 循环嵌套

for (let i = 0; i < 10; i++) {
  for (let j = 0; j < 10; j++) {
    console.log(i + " " + j);
  }
}

数组进阶

声明数组

  • 字面量声明(推荐使用)
let arr = [1, 2, 3, "四", 5, true];
let arr = []; // 声明一个空数组
  • 构造函数声明
let arr = new Array(1, 2, 3, "四", 5, true);
let arr = new Array(); // 声明一个空数组
  • 构造二维数组(使用字面量构造, 推荐使用)
let numArr = [];
for (let i = 0; i < 10; i++) {
  numArr[i] = [];
  for (let j = 0; j < 10; j++) {
    numArr[i][j] = 0;
  }
}
  • 使用 fill 和 map 方法声明二维数组
const rows = 3;
const cols = 4;
const matrix = new Array(rows).fill().map(() => new Array(cols).fill(0));

console.log(matrix);

遍历数组

  • for 循环
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}
  • forEach 方法(数组方法)
arr.forEach(function (item, index, arr) {
  // item: 数组元素
  // index: 数组索引
  // arr: 数组本身
  console.log(item);
});
  • for…of 循环
for (let item of arr) {
  console.log(item);
}

数组方法

  • push 方法
arr.push(6);
// 向数组 arr(末尾) 中添加元素 6
// 返回数组的新长度
  • pop 方法
arr.pop();
// 移除数组的最后一个元素
// 返回移除的元素
  • shift 方法
arr.shift();
// 移除数组的第一个元素,并返回该元素
  • unshift 方法
arr.unshift(0);
// 在数组的开头添加元素 0
  • splice 方法
arr.splice(2, 1, 4, 5);
// 从索引 2 开始(包括索引2),删除 1 个元素,并在该位置插入 4, 5
// 若删除0个元素, 则在索引2后面插入元素
// 返回被删除的元素组成的数组
  • concat 方法
let newArr = arr.concat([7, 8, 9]);
// 使用 concat 方法将数组 arr 与包含元素 7, 8, 9 的新数组合并,结果存储在 newArr 中
  • join 方法
let str = arr.join("-");
// 将数组 arr 中的元素使用 "-" 连接成一个字符串,并赋值给变量 str, 默认使用逗号分隔
  • map 方法
// 可以遍历数组处理数据, 并返回一个新的数组
let newArr = arr.map(function (item, index) {
  return item * 2;
});
  • fill 方法
arr.fill(0, 2, 4);
// 用 0 填充数组 arr 中索引 2 到 4 之间的元素(包括第一个索引但不包括最后一个索引)

排序(三大基础排序, 了解即可)

冒泡排序

// 冒泡排序
function bubbleSort(arr) {
  let len = arr.length;
  for (let i = 0; i < len - 1; i++) {
    for (let j = 0; j < len - i - 1; j++) {
        if (arr[j] > arr[j + 1]) {
            let temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
        }
    }
  }
}

选择排序


// 选择排序
function selectionSort(arr) {
  let len = arr.length;
  for (let i = 0; i < len - 1; i++) {
    let minIndex = i;
    for (let j = i + 1; j < len; j++) {
      if (arr[j] < arr[minIndex]) {
        minIndex = j;
      }
    }
    if (minIndex !== i) {
      let temp = arr[i];
      arr[i] = arr[minIndex];
      arr[minIndex] = temp;
    }
  }
}

插入排序


// 插入排序
function insertionSort(arr) {
  let len = arr.length;
  for (let i = 1; i < len; i++) {
    let current = arr[i];
    let j = i - 1;
    while (j >= 0 && arr[j] > current) {
      arr[j + 1] = arr[j];
      j--;
    }
    arr[j + 1] = current;
  }
}

函数

函数的定义

function myFunction(arg1, arg2) {
    // 函数体
  return arg1 + arg2;
    // 返回值
}

函数的调用

myFunction(1, 2); // 3

函数的参数

  • 函数可以有0个或多个参数。参数可以是任意类型,包括数字、字符串、对象、数组等。
function myFunction(arg1 = 0, arg2 = 0) { // 默认参数
  // 函数体
  return arg1 + arg2;
}

let result = myFunction(1, 2); // 3
let result2 = myFunction("hello", "world"); // "helloworld"

函数的返回值

  • 函数可以返回任意类型的值,包括数字、字符串、对象、数组等。
function myFunction(arg1, arg2) {
  // 函数体
  return arg1 + arg2;
  // 若要返回多个值,可以返回一个数组
  // return [arg1, arg2];
  // 也可以返回对象
  // return {sum: arg1 + arg2};
}

let result = myFunction(1, 2); // 3
console.log(result); // 3

函数的作用域

  • 函数的作用域决定了函数内的变量能访问哪些变量,以及它们的值是什么。

  • 使用letconst声明的变量,其作用域为函数内部的块级作用域。

  • 如果函数内部, 变量没有使用letconst声明, 则该变量为全局变量。

  • 函数的形参可以看做局部变量。

  • 访问原则: 局部变量 > 全局变量 > 函数参数。

// 使用var声明的变量, 其作用域为函数内部的块级作用域顶部, 但值不会提升到顶部
function myFunction() {
  console.log(x); // undefined, 因为变量提升, 若用let或const声明, 为ReferenceError
  var x = 1;
  console.log(x); // 1
}

函数的作用域链(学习对象之后了解)

  • 函数的作用域链是一个对象,它包含了函数执行时的作用域链。

  • 当函数执行时,会创建一个作用域链,包含了函数的局部作用域、其上层函数的作用域、全局作用域。

function myFunction() {
  var x = 1;
  console.log(x); // 1
}

myFunction();

console.log(x); // ReferenceError: x is not defined

函数的闭包

  • 函数可以访问其外部作用域的变量(全局变量),这种函数称为闭包。
function myFunction() {
  var x = 1;
  function innerFunction() {
    console.log(x); // 1
  }
  return innerFunction;
}

var myClosure = myFunction();
myClosure();

函数的递归

  • 函数可以调用自身,这种函数称为递归函数。
// 阶乘函数
function factorial(n) {
  if (n === 1) {
    return 1;
  } else {
    return n * factorial(n - 1);
  }
}

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

匿名函数

var myFunc = function() {
  console.log("Hello, world!");
};

myFunc(); // "Hello, world!"
  • 匿名函数与具名函数的区别:

    1. 具名函数的调用可以写到任何位置
    2. 匿名函数必须在定义后调用

立即执行函数表达式(IIFE)

  • 避免全局变量污染,提高代码的可读性。
(function() {
  console.log("Hello, world!");
})(); // "Hello, world!"

逻辑中断

  • 如果左边能够判断真假, 则不必判断右边。(不推荐使用)

function myFunction(x, y) {
  x = x || 0;
  y = y || 0;
  // 类似于形参的默认值, 若x或y为false, 则返回0
  return x + y;
}

  • 在新语法中, 用空值运算符
const value = someValue ?? "default";
// 只在someValue为null或undefined时使用默认值, default.

对象(object)

什么是对象?

  • 在计算机编程中,对象是一个抽象概念,它是由数据和操作数据的行为组成的整体。对象是对现实世界中事物的一种抽象,它可以包含数据和操作数据的行为。对象是由属性和方法组成的,属性是对象的状态,方法是对象可以执行的操作。对象可以被创建、使用、修改和销毁。对象是软件系统的基本构造块,是构成系统的基本单元。

  • 在JavaScript中,对象是一个无序的集合,它由属性和方法组成。属性是对象的状态,方法是对象可以执行的操作。对象可以被创建、使用、修改和销毁。对象是JavaScript的核心概念之一。

  • 在JS中, 一切皆对象, 包括数字, 字符串, 数组, 函数, 正则表达式, 日期, 等等。

对象创建

  • 对象可以被创建使用两种方式:字面量和构造函数。

字面量创建对象(推荐使用)

  • 字面量创建对象是指通过直接在代码中定义一个对象,并将属性和方法(函数)赋值给它。
// 创建一个对象
let person = {
  name: 'John',         // 注意标点符号
  age: 30,
  'now-time': '2025-03-20', // 属性名中包含特殊字符时,需要用单引号括起来
  greet: function() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

console.log(person); // {name: "John", age: 30, greet: ƒ}

// 访问对象的属性
console.log(person.name); // John
console.log(person['now-time']); // 2025-03-20, 注意属性名需要用单引号括起来

// 调用对象的方法
person.greet(); // Hello, my name is John

person.age = 35; // 修改对象的属性
console.log(person.age); // 35
 
person.city = 'New York'; // 添加新的属性
console.log(person.city); // New York

delete person.age; // 删除对象的属性
console.log(person); // {name: "John", greet: ƒ, city: "New York"}

构造函数创建对象

  • 构造函数创建对象是指通过定义一个函数,并将属性和方法赋值给它,然后通过new关键字来调用该函数,创建出一个对象。
// 创建一个构造函数
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.greet = function() {
        console.log(`Hello, my name is ${this.name}`);
    };
    }
    // 创建一个对象
    const person1 = new Person('John', 30); // 使用 new 来实例化
    const person2 = new Person('Mary', 25);

    // 访问对象的属性
    console.log(person1.name); // John
    console.log(person2.age);  // 25

    // 调用对象的方法
    person1.greet(); // Hello, my name is John
    person2.greet(); // Hello, my name is Mary

    // 验证person1和person2是否是同一个对象
    console.log(person1 === person2); // false
  • 构造函数创建对象时,每次调用构造函数都会创建一个新的对象。因此,person1和 person2是两个不同的对象。

对象遍历

  • 对象可以被遍历,可以遍历对象的属性和方法。
// 遍历对象属性
for (let key in person) {
    console.log(key); // name, age, greet   key是属性名, 字符串类型
    console.log(person[key]); // John, 30, ƒ(){}  person[key]是属性值
}

// 遍历对象方法
for (let key in person) {
    if (typeof person[key] === 'function') {
        console.log(key); // greet
    }
}

对象数组

  • 对象数组是指一个数组中包含多个对象。
// 创建一个对象数组
let people = [
    {name: 'John', age: 30},
    {name: 'Mary', age: 25},
    {name: 'Tom', age: 20}
];

// 遍历对象数组
for (let i = 0; i < people.length; i++) {
    console.log(people[i].name); // John, Mary, Tom
}

// 遍历对象数组的属性
for (let i = 0; i < people.length; i++) {
    for (let key in people[i]) {
        console.log(key); // name, age
    }
}

// 遍历对象数组的属性和方法
for (let i = 0; i < people.length; i++) {
    for (let key in people[i]) {
        if (typeof people[i][key] === 'function') {
            console.log(key); // greet
        } else {
            console.log(key); // name, age
        }
    }
}

内置对象

Math对象

  • Math对象是JavaScript的内置对象,它提供了一些常用的数学函数。
// 计算平方根
console.log(Math.sqrt(9)); // 3

// 计算绝对值
console.log(Math.abs(-3)); // 3

// 计算最大值
console.log(Math.max(3, 5, 1)); // 5

// 计算最小值
console.log(Math.min(3, 5, 1)); // 1

// 计算随机数    左闭右开 [0, 1)
console.log(Math.random()); // 0.123456789

console.log(Math.floor(Math.random() * (10 + 1))); // 随机生成10(包括10)以内的整数

// 在数组中随机抽取元素
let arr = [1, 2, 3, 4, 5];
console.log(arr[Math.floor(Math.random() * arr.length)]); // 随机抽取数组中的一个元素

// 生成n到m的随机整数
console.log(Math.floor(Math.random() * (m - n + 1)) + n); // 随机生成n到m的整数

// 计算圆周率
console.log(Math.PI); // 3.141592653589793

// 向上取整
console.log(Math.ceil(3.2)); // 4

// 向下取整 
console.log(Math.floor(3.8)); // 3

// 四舍五入     在计算负数时, .5取大的, .5以上取小的
console.log(Math.round(3.5)); // 4

Date对象

  • Date对象是JavaScript的内置对象,它提供了日期和时间处理函数。
// 创建一个日期对象
let date = new Date();

// 格式化日期
console.log(date.toLocaleString()); // 2021/10/12 下午10:15:30

// 获取日期
console.log(date.getDate()); // 12

// 获取月份
console.log(date.getMonth()); // 9

// 获取年份
console.log(date.getFullYear()); // 2021

// 日期加减
let newDate = new Date(date.getTime() + 1000 * 60 * 60 * 24); // 加一天
console.log(newDate.toLocaleString()); // 2021/10/13 下午10:15:30

let newDate = new Date(date.getTime() - 1000 * 60 * 60 * 24); // 减一天
console.log(newDate.toLocaleString()); // 2021/10/11 下午10:15:30

网站公告

今日签到

点亮在社区的每一天
去签到