JavaScript完整版知识体系(持续更新~~)

一、Variables变量

(1)变量的声明方式。

在 JavaScript 中,letconstvar 是用于声明变量的关键字,但它们在作用域、可变性、以及提升(Hoisting)行为上有所不同。下面是对这三者的详细解释:

1. var:

  • 作用域var 声明的变量有函数作用域,意味着如果 var 在函数内声明,变量只在函数内有效。如果在函数外部声明,变量会成为全局变量。

  • 提升(Hoisting)var 声明的变量会在作用域内“提升”到顶部,这意味着你可以在声明之前访问该变量,但它的值为 undefined

  • 可重复声明:在同一个作用域中,可以多次使用 var 来声明同一个变量,不会抛出错误。

    例子:

2. let:

  • 作用域let 声明的变量有块级作用域,即它仅在最近的代码块(如 {})内有效。

  • 提升(Hoisting)let 变量也会被提升,但不会被初始化,即你不能在声明之前使用它,若使用会报错。其作用域从声明处开始。

  • 可重复声明:在同一作用域内不能重复声明同一个变量,使用 let 会抛出错误。

    例子

let与var声明的变量可以被重新赋值:

三者均具备有块级作用域:

3. const:

  • 作用域constlet 一样,也有块级作用域

  • 提升(Hoisting)const 变量也会被提升,但和 let 一样,不能在声明之前访问。

  • 不可变性const 用于声明常量,意味着声明后其值不能再改变(对于原始数据类型如 numberstring 等)。但如果 const 声明的是一个对象或数组,虽然引用不能变,但对象或数组的内容仍然可以修改。

  • 可重复声明:与 let 相同,不能在同一作用域内重复声明同一个变量。

    例子

    
    

总结:

  • var:函数作用域、会提升、可重复声明、不推荐使用(因为有些行为可能造成问题)。
  • let:块级作用域、会提升但不会初始化、不可重复声明,通常用于可变值。
  • const:块级作用域、会提升但不会初始化、不可重复声明、声明常量,通常用于不可变值或引用不变的对象。

通常,建议在 JavaScript 中优先使用 letconst,而尽量避免使用 var,因为 var 在作用域和提升方面的行为较为复杂,容易导致意外错误。
 

(2)变量的类型

JavaScript 中的基本数据类型包括以下几种:

1. 原始数据类型 (Primitive Types)

原始数据类型是不可变的,也就是说它们的值一旦被创建,就不能被改变。原始数据类型包括:

  • String:表示文本数据,例如 'hello'"world"
  • Number:表示数字,包括整数和浮点数,例如 1233.14
  • BigInt:用于表示任意大小的整数,常用于处理大数,例如 123n
  • Boolean:表示布尔值,只有两个值:truefalse
  • undefined:表示变量未赋值时的初始状态,例如:
    let x;
    console.log(x);  // 输出:undefined
    
  • null:表示“无”或“空”的值,通常用于表示一个空对象引用:
    let y = null;
    
  • Symbol:表示唯一的、不可变的值,通常用于创建对象的唯一标识符:
    let sym = Symbol('description');
    

2. 引用数据类型 (Reference Types)

引用数据类型是由多个值组成的数据结构,它们是可变的。引用数据类型包括:

  • Object:表示一组键值对的数据结构。对象可以包含多个属性和方法。例如:
    let person = {name: "John",age: 30
    };
    
  • Array:数组是一种特殊的对象,表示一系列按顺序排列的值。例如:
    let fruits = ['apple', 'banana', 'cherry'];
    
  • Function:函数也是一种对象,代表一段可以执行的代码。例如:
    function greet() {console.log('Hello, world!');
    }
    
  • Date:用于表示日期和时间的对象。例如:
    let now = new Date();
    

3. 类型转换

在 JavaScript 中,原始数据类型和引用数据类型之间是可以进行转换的。例如,字符串和数字之间可以转换,或者将 nullundefined 作为特殊值来处理。

总结

JavaScript 的数据类型分为两类:

  1. 原始数据类型StringNumberBigIntBooleanundefinednullSymbol
  2. 引用数据类型ObjectArrayFunctionDate

这些数据类型是构建 JavaScript 程序的基础。了解它们之间的区别和使用方法对于高效编程非常重要!

二、Functions 函数

(1)基本概念

在 JavaScript 中,函数是非常重要的一部分,它帮助你封装代码,实现可复用性。下面我会从几个方面详细解释 JavaScript 中的函数。

(2)函数的声明方式

JavaScript 中有几种声明函数的方式:

1.这种方式是最常见的函数声明方式,它通过 function 关键字来声明一个函数。

function FunctionName(){console.log("hello world");
}

2.函数也可以作为一个表达式被赋值给变量。这个方式常用于匿名函数。

const FunctionName = function(){console.log("hello world");
}

3.箭头函数是 ES6 引入的一种简化的函数写法,语法更简洁,尤其适合用作回调函数。
const FunctionName = () => {console.log("hello world");
}

(3) 函数参数

函数可以接受参数,这些参数可以是任何类型的数据,包括基本类型、对象、数组等。

const FunctionName = (name) => {console.log(`hello ${name}`);
}

如果函数未传递足够的参数,JavaScript 会将未传入的参数设为 undefined

(4) 返回值(Return)

函数可以通过 return 语句返回一个值。如果没有显式的 return,默认返回 undefined

const FunctionName = (a,b) => {return a+b;}

(5)函数作用域(Scope)

JavaScript 函数有自己的作用域,意味着函数内部定义的变量不能在函数外部访问,反之亦然。

 

5. 闭包(Closure)

闭包是指函数可以“记住”并访问它定义时的作用域,即使该函数在外部作用域执行时,仍然可以访问原作用域中的变量。

 

javascript

复制编辑

function outer() { let count = 0; return function inner() { count++; console.log(count); }; } const counter = outer(); counter(); // 输出 1 counter(); // 输出 2

6. 函数的 this 关键字

this 关键字指向函数调用时的上下文对象。在普通函数中,this 通常指向全局对象(在浏览器中是 window),在对象方法中,this 指向调用该方法的对象。

 

javascript

复制编辑

function show() { console.log(this); } show(); // 在浏览器中输出 window 对象 const obj = { name: "Alice", greet: function() { console.log(this.name); } }; obj.greet(); // 输出 "Alice"

7. 函数重载

JavaScript 不支持传统意义上的函数重载。即不能根据参数的数量或类型来区分多个同名函数。你可以在函数体内根据参数的不同情况来手动处理不同的功能。

 

javascript

复制编辑

function greet(name, age) { if (arguments.length === 1) { console.log(`Hello, ${name}!`); } else if (arguments.length === 2) { console.log(`Hello, ${name}, you are ${age} years old!`); } } greet("Alice"); // 输出 "Hello, Alice!" greet("Alice", 30); // 输出 "Hello, Alice, you are 30 years old!"

8. 高阶函数

在 JavaScript 中,函数可以作为参数传递给其他函数,或者返回一个函数。这种函数被称为高阶函数。

 

javascript

复制编辑

function greet(name, callback) { console.log(`Hello, ${name}!`); callback(); } greet("Alice", function() { console.log("Goodbye!"); });

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

立即调用函数表达式(IIFE)是指声明并立即执行的函数。它常用于创建一个独立的作用域,避免污染全局命名空间。

 

javascript

复制编辑

(function() { console.log("This function is invoked immediately!"); })();

10. 函数的默认参数

在 ES6 中,函数的参数可以设定默认值,若调用时没有传递参数,则会使用默认值。

 

javascript

复制编辑

function greet(name = "Guest") { console.log(`Hello, ${name}!`); } greet(); // 输出 "Hello, Guest!" greet("Alice"); // 输出 "Hello, Alice!"

总结

JavaScript 中的函数非常灵活,具有多种特性,比如匿名函数、箭头函数、闭包、作用域、this 关键字等。通过函数,你可以实现代码的封装、复用和更好的结构化。

三、object面向对象编程

在 JavaScript 中,Object 是一种数据类型,它用于存储键值对。对象可以包含多种类型的属性,包括数字、字符串、函数等。JavaScript 中的对象非常灵活,可以用来表示现实世界的各种事物,比如人、车、学生等。接下来我会详细介绍 JavaScript 中对象的相关知识。

定义object类型的变量

判断变量是否是对象

1. 创建对象

对象可以通过多种方式来创建:

1.1 对象字面量(Object Literal)

最常用的方式是通过对象字面量创建对象,即使用 {} 来创建一个对象。

const person = {name: "Alice",age: 25,greet: function() {console.log(`Hello, my name is ${this.name}.`);}
};
1.2 new Object() 语法

你也可以使用 new Object() 来创建对象,不过这种方式较为少见。

const person = new Object();
person.name = "Alice";
person.age = 25;
person.greet = function() {console.log(`Hello, my name is ${this.name}.`);
};

2. 访问对象的属性

可以通过两种方式来访问对象的属性:

2.1 点操作符(Dot Notation)
console.log(person.name); // 输出 "Alice"
console.log(person.age);  // 输出 25
2.2 方括号操作符(Bracket Notation)

这种方式适合当属性名是动态的或者包含特殊字符时。

console.log(person["name"]); // 输出 "Alice"
console.log(person["age"]);  // 输出 25

3. 修改对象的属性

你可以直接修改对象的属性:

person.name = "Bob"; // 修改 name 属性
console.log(person.name); // 输出 "Bob"

或者使用方括号语法:

person["age"] = 30;
console.log(person.age); // 输出 30

4. 添加新的属性

你可以随时为对象添加新的属性:

person.address = "123 Main St";
console.log(person.address); // 输出 "123 Main St"

5. 删除对象的属性

使用 delete 操作符可以删除对象的属性:

delete person.age;
console.log(person.age); // 输出 undefined

6. 对象的遍历

6.1 for...in 循环

for...in 循环用于遍历对象的所有可枚举属性。

for (let key in person) {console.log(key, person[key]);
}
// 输出:
// name Bob
// greet [Function: greet]
// address 123 Main St
6.2 Object.keys()forEach

Object.keys() 返回对象的所有属性名组成的数组,你可以使用 forEach 来遍历:

Object.keys(person).forEach(function(key) {console.log(key, person[key]);
});
// 输出:
// name Bob
// greet [Function: greet]
// address 123 Main St

7. 对象的this 关键字

在对象的方法中,this 关键字通常指向调用该方法的对象。

const person = {name: "Alice",greet: function() {console.log(`Hello, my name is ${this.name}.`);}
};
person.greet(); // 输出 "Hello, my name is Alice."

8. 对象的方法

对象不仅可以包含数据,还可以包含方法。方法是对象的属性,它的值是一个函数。

const person = {name: "Alice",greet: function() {console.log(`Hello, my name is ${this.name}.`);}
};
person.greet(); // 输出 "Hello, my name is Alice."

9. 对象的constructor 属性

每个对象都有一个 constructor 属性,它指向创建该对象的构造函数。例如,普通对象的构造函数是 Object

const person = {name: "Alice"
};
console.log(person.constructor); // 输出 [Function: Object]

10. 对象的 Object 方法

10.1 Object.keys()

Object.keys() 返回一个包含对象所有属性名称的数组。

const person = { name: "Alice", age: 25 };
console.log(Object.keys(person)); // 输出 ["name", "age"]
10.2 Object.values()

Object.values() 返回一个包含对象所有属性值的数组。

console.log(Object.values(person)); // 输出 ["Alice", 25]
10.3 Object.entries()

Object.entries() 返回一个包含对象所有键值对的二维数组。

console.log(Object.entries(person));
// 输出 [["name", "Alice"], ["age", 25]]
10.4 Object.assign()

Object.assign() 用于将一个或多个源对象的所有可枚举属性复制到目标对象。

const person = { name: "Alice" };
const details = { age: 25, gender: "female" };
const newPerson = Object.assign({}, person, details);
console.log(newPerson); // 输出 { name: "Alice", age: 25, gender: "female" }

11. 对象的原型

每个 JavaScript 对象都有一个原型(prototype),通过原型,子对象可以继承父对象的属性和方法。

const person = {name: "Alice",greet: function() {console.log(`Hello, my name is ${this.name}.`);}
};const student = Object.create(person);
student.grade = "A";
student.greet(); // 输出 "Hello, my name is Alice."(继承自person对象的方法)
console.log(student.grade); // 输出 "A"

12. 类(Class)与对象

在 JavaScript 中,你可以使用类(ES6 引入)来定义对象的模板。类本质上是一个构造函数。

class Person {constructor(name, age) {this.name = name;this.age = age;}greet() {console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);}
}const person = new Person("Alice", 25);
person.greet(); // 输出 "Hello, my name is Alice and I am 25 years old."

Document Object Model (DOM) in JavaScript

DOM(文档对象模型)是浏览器提供的一种 API(应用程序接口),允许开发者通过编程的方式访问和操作 HTML 或 XML 文档的结构。DOM 把网页的结构表示为一个树形结构,网页中的每个元素都被表示为树的一个节点。

1. DOM的基本概念

  • 文档对象模型(DOM)是网页的表示形式。它把整个网页结构转化为树形结构,其中每个节点代表网页中的一个部分,例如元素、属性、文本等。

  • DOM 树:DOM 将网页中的每个元素都看作是一个对象,形成了一个类似树形的结构,这个树形结构可以通过 JavaScript 操控。

    比如,网页内容:

    <html><body><div id="container"><p>Hello, World!</p></div></body>
    </html>
    

    它对应的 DOM 树是:

    HTML├── HEAD└── BODY└── DIV (id="container")└── P└── "Hello, World!"
    

2. DOM 树的节点类型

DOM 树包含多种类型的节点,主要有:

  • 元素节点(Element Nodes):代表 HTML 标签,如 <div><p> 等。
  • 文本节点(Text Nodes):代表 HTML 元素中的文本内容。
  • 属性节点(Attribute Nodes):表示 HTML 元素的属性,例如 classid 等。
  • 文档节点(Document Node):代表整个文档。

3. DOM 操作

JavaScript 可以通过 DOM 来访问和修改网页内容,DOM 提供了大量的方法来操作这些节点。

3.1 获取元素

DOM 提供了几种方法来获取元素或节点:

  • document.getElementById(id):通过元素的 id 获取一个元素。

    const element = document.getElementById("container");
    
  • document.getElementsByClassName(className):通过元素的 class 获取一组元素。

    const elements = document.getElementsByClassName("class-name");
    
  • document.getElementsByTagName(tagName):通过元素的标签名获取一组元素。

    const paragraphs = document.getElementsByTagName("p");
    
  • document.querySelector(selector):通过 CSS 选择器获取一个元素。

    const element = document.querySelector(".class-name");
    
  • document.querySelectorAll(selector):通过 CSS 选择器获取所有匹配的元素。

    const elements = document.querySelectorAll("p.class-name");
    
3.2 修改元素

一旦获取了元素,你就可以通过 JavaScript 修改它们的内容、样式、属性等。

  • 修改文本内容:使用 textContentinnerText 修改文本。

    const paragraph = document.querySelector("p");
    paragraph.textContent = "New text!";
    
  • 修改 HTML 内容:使用 innerHTML 修改元素的 HTML 内容。

    const div = document.querySelector("#container");
    div.innerHTML = "<p>New HTML content</p>";
    
  • 修改属性:使用 setAttribute() 方法修改元素的属性。

    const img = document.querySelector("img");
    img.setAttribute("src", "new-image.jpg");
    
  • 修改样式:使用 style 属性修改元素的样式。

    const div = document.querySelector("#container");
    div.style.backgroundColor = "blue";
    
3.3 添加和删除元素
  • 创建元素:使用 createElement() 创建一个新的元素。

    const newDiv = document.createElement("div");
    
  • 添加元素到页面:使用 appendChild()insertBefore() 把新的元素添加到页面中。

    const parent = document.querySelector("#container");
    parent.appendChild(newDiv);
    
  • 删除元素:使用 removeChild() 删除一个子元素。

    const parent = document.querySelector("#container");
    const child = document.querySelector("p");
    parent.removeChild(child);
    
3.4 事件处理

DOM 允许你为页面上的元素添加事件监听器,以便在用户交互时执行代码。

  • 添加事件监听器:使用 addEventListener() 为元素添加事件监听器。

    const button = document.querySelector("button");
    button.addEventListener("click", function() {alert("Button clicked!");
    });
    
  • 移除事件监听器:使用 removeEventListener() 移除事件监听器。

    button.removeEventListener("click", function() {alert("Button clicked!");
    });
    

4. DOM 中的导航

  • 父节点(parentNode):获取元素的父节点。

    const child = document.querySelector("p");
    const parent = child.parentNode;
    
  • 子节点(childNodes):获取元素的所有子节点。

    const parent = document.querySelector("#container");
    const children = parent.childNodes;
    
  • 第一个子节点(firstChild):获取元素的第一个子节点。

    const parent = document.querySelector("#container");
    const firstChild = parent.firstChild;
    
  • 最后一个子节点(lastChild):获取元素的最后一个子节点。

    const parent = document.querySelector("#container");
    const lastChild = parent.lastChild;
    
  • 兄弟节点(nextSibling, previousSibling):获取元素的兄弟节点。

    const element = document.querySelector("p");
    const next = element.nextSibling;
    const previous = element.previousSibling;
    

5. DOM 的作用与应用

  • 动态网页交互:DOM 使得网页能够响应用户的输入、点击等交互,动态地改变页面内容。

  • 表单验证:通过 DOM 操控表单,可以验证用户输入的有效性,给用户提示信息。

  • AJAX 和 API 请求:DOM 可以与 JavaScript 中的异步请求(例如 fetchXMLHttpRequest)结合,动态更新页面内容而无需刷新整个页面。

6. DOM 与性能

  • DOM 操作可能会比较慢,特别是在进行大量节点操作时。为了提高性能,尽量减少 DOM 的访问次数,使用一些优化技术(例如:批量操作事件委托等)。

  • 虚拟 DOM:一些现代框架(如 React)引入了虚拟 DOM 技术,它通过先在内存中更新虚拟 DOM,再与实际 DOM 进行比较,最后进行最小化的更新,从而提高页面性能。

7. 总结

  • DOM 是浏览器提供的一种 API,用于表示和操作 HTML 或 XML 文档。通过 JavaScript,开发者可以访问和修改页面的结构、内容和样式。
  • DOM 的操作是基于树形结构的,开发者可以使用 JavaScript 动态创建、删除、修改、访问网页元素。
  • DOM 提供了事件处理机制,使得网页能够响应用户交互。

总结

JavaScript 中的对象是一个非常灵活的数据类型,它可以包含多个不同类型的数据和方法。对象通过键值对来存储数据,支持动态的属性修改和删除。对象的特性,如继承、原型链等,都是面向对象编程的重要概念。通过熟悉对象的使用,你可以更好地组织和管理你的代码。

flex和grid

在 CSS 中,flexgrid 是两种用于布局的现代技术,它们可以帮助你更灵活地创建响应式、复杂的网页布局。它们都提供了比传统的布局方式(如浮动和定位)更加简便和强大的工具。接下来,我将详细解释它们各自的概念和使用方法。

1. Flexbox(弹性盒子布局)

Flexbox 是一种一维布局模型,主要用于在 水平垂直 方向上排列和分配空间,适用于需要沿某一方向(行或列)对元素进行对齐和分布的情况。

1.1 基础概念

Flexbox 布局的核心是通过设置容器的 display: flex 属性,将容器内的子元素变为弹性项(flex items),然后通过一些属性来控制这些子元素的排列方式。

1.2 主要属性
  • 容器的属性(作用于父元素):

    • display: flex;:定义一个 flex 容器。

    • flex-direction:设置主轴的方向,决定了弹性项的排列方向。

      • row(默认值):水平排列,主轴从左到右。
      • row-reverse:水平排列,主轴从右到左。
      • column:垂直排列,主轴从上到下。
      • column-reverse:垂直排列,主轴从下到上。
    • justify-content:控制弹性项在主轴方向上的对齐方式。

      • flex-start(默认值):将项目靠近主轴的起点对齐。
      • flex-end:将项目靠近主轴的终点对齐。
      • center:将项目居中对齐。
      • space-between:项目之间的间距相等,首尾项目靠近容器的两端。
      • space-around:项目之间的间距相等,项目两侧的间距也相等。
    • align-items:控制弹性项在交叉轴(与主轴垂直的方向)上的对齐方式。

      • stretch(默认值):将项目拉伸以填满容器。
      • flex-start:项目在交叉轴的起点对齐。
      • flex-end:项目在交叉轴的终点对齐。
      • center:项目在交叉轴上居中对齐。
      • baseline:项目的基线对齐。
    • align-content:控制多行之间的对齐方式。与 align-items 类似,但它影响的是多行之间的对齐,而不是单行。

  • 弹性项的属性(作用于子元素):

    • flex-grow:定义弹性项如何伸展以填充额外空间。默认值是 0,表示不伸展。如果一个项的 flex-grow1,它就会占据剩余的空间。

    • flex-shrink:定义弹性项如何缩小以适应容器。如果容器空间不足,子元素会根据该属性进行缩小。默认值是 1,表示可以缩小。

    • flex-basis:定义弹性项的初始大小。可以使用像素、百分比等单位。默认值是 auto,表示元素的初始大小根据其内容决定。

    • flex:一个简写属性,flex-grow, flex-shrink, flex-basis 的缩写,通常用来控制弹性项的扩展和缩小。

    • align-self:允许单个子元素覆盖 align-items 属性的对齐方式,可以为某一项设置不同的对齐方式。

1.3 Flexbox 示例
<div style="display: flex; justify-content: center; align-items: center; height: 200px;"><div style="width: 50px; height: 50px; background-color: red;"></div><div style="width: 50px; height: 50px; background-color: blue;"></div><div style="width: 50px; height: 50px; background-color: green;"></div>
</div>

这个例子中,flex 容器内的子元素被水平和垂直居中排列。

2. Grid Layout(网格布局)

Grid 是一种二维布局模型,允许你在 水平垂直 方向上同时控制元素的排列和分布。它适用于更复杂的布局,比如分为多个区域的页面布局。

2.1 基础概念

Grid 布局通过设置容器的 display: grid 来启用,并通过定义 (rows)和 (columns)来规划元素的位置。

2.2 主要属性
  • 容器的属性(作用于父元素):

    • display: grid;:定义一个网格容器。

    • grid-template-columns:定义网格的列。可以设置具体的列宽度,例如 200px, 1fr(占可用空间的1份),或 auto(根据内容宽度自动调整)。

    • grid-template-rows:定义网格的行。类似于 grid-template-columns,用于设置行高。

    • grid-template-areas:通过命名的区域来定义网格。每个子元素可以分配一个区域。

    • grid-gap(或 gap):定义行和列之间的间距。

    • grid-auto-rowsgrid-auto-columns:定义自动生成的行和列的大小(当元素超出预设的网格时)。

  • 网格项的属性(作用于子元素):

    • grid-column:定义元素跨越的列数。可以设置一个起始列和结束列,或者使用 span 来指定跨越多少列。

    • grid-row:定义元素跨越的行数,使用方式与 grid-column 类似。

    • grid-area:定义元素所占的区域,可以使用命名的区域来定位。

    • justify-items:控制元素在水平(行)方向上的对齐方式。

    • align-items:控制元素在垂直(列)方向上的对齐方式。

    • justify-selfalign-self:分别控制单个元素在网格容器内的水平和垂直对齐方式。

2.3 Grid 示例
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; grid-gap: 10px;"><div style="background-color: red;">Item 1</div><div style="background-color: blue;">Item 2</div><div style="background-color: green;">Item 3</div>
</div>

在这个例子中,我们创建了一个有三列的网格布局,每列占据相等的空间,元素之间有 10px 的间距。

2.4 Grid 布局的优势
  • 灵活性:Grid 可以轻松处理二维布局,适合设计复杂的页面结构。
  • 简洁性:通过定义列和行,开发者可以轻松管理元素的对齐和分布。

3. Flexbox 和 Grid 的对比

特性FlexboxGrid
布局方向仅限于一维布局(行或列)支持二维布局(行和列)
适用场景简单的线性布局,适合小范围的排列复杂的页面布局,适合大范围的区域布局
灵活性灵活且适用于简单的布局更加灵活,适用于复杂的布局
空间分配支持在主轴方向上的空间分配支持同时在水平和垂直方向上的空间分配

总结

  • Flexbox:适用于一维布局,简单的对齐和空间分配,通常用于需要在行或列中对齐元素的情况。
  • Grid:适用于二维布局,能够在行和列上同时控制布局,适合复杂的网页布局。

这两种布局方式可以单独使用,也可以结合起来使用,帮助开发者在现代网页设计中实现灵活且高效的布局。

CSS中的单位详解

CSS中的单位可分为多个类别,每种单位适用于不同的场景。以下是对各类单位的详细解释及示例:


一、绝对长度单位

基于物理测量,适合固定尺寸,但在不同设备上可能显示不一致。

  • px(像素):屏幕显示的基本单位(1px = 1/96英寸)。

    width: 20px; /* 固定宽度为20像素 */
    
  • pt(点):印刷常用单位(1pt = 1/72英寸)。

    font-size: 12pt; /* 字体大小为12点 */
    
  • in(英寸)、cm(厘米)、mm(毫米):

    width: 2in;  /* 2英寸 */
    padding: 0.5cm; /* 0.5厘米 */
    
  • pc(派卡):1pc = 12pt。

    line-height: 1.5pc; /* 18pt */
    

二、相对长度单位

相对于其他元素或视口的尺寸,灵活适应不同环境。

  1. 字体相关单位

    • em:相对于父元素的字体大小。

      .child { font-size: 1.5em; } /* 父元素字体为16px → 24px */
      
    • rem:相对于根元素(<html>)的字体大小。

      html { font-size: 16px; }
      .element { width: 2rem; } /* 32px */
      
    • ex:当前字体的x高度(小写字母x的高度)。

    • ch:字符“0”的宽度(等宽字体中更准确)。

  2. 百分比(%)

    • 相对于父元素的对应属性。
      .child { width: 50%; } /* 父元素宽度的50% */
      .box { padding-top: 10%; } /* 相对于父元素宽度计算 */
      
  3. 视口单位

    • vw(视口宽度):1vw = 视口宽度的1%。
    • vh(视口高度):1vh = 视口高度的1%。
    • vmin:取vw和vh中较小值的1%。
    • vmax:取vw和vh中较大值的1%。
      .full-screen { width: 100vw; height: 100vh; }
      
  4. 动态视口单位(较新):

    • svw/svh:小视口尺寸(设备UI可见时)。
    • lvw/lvh:大视口尺寸(设备UI隐藏时)。
    • dvw/dvh:动态调整视口尺寸。

三、容器查询单位

相对于容器尺寸(需父元素声明为容器)。

  • cqw:容器宽度的1%。
  • cqh:容器高度的1%。
  • cqi:容器内联方向(水平)的1%。
  • cqb:容器块方向(垂直)的1%。
    @container (width > 300px) {.item { width: 50cqw; } /* 容器宽度的一半 */
    }
    

四、网格单位(CSS Grid)

  • fr:按比例分配剩余空间。
    grid-template-columns: 1fr 2fr; /* 两列宽度比为1:2 */
    

五、角度单位

用于旋转、渐变等。

  • deg(度)、rad(弧度)、grad(百分度)、turn(圈数)。
    transform: rotate(45deg);
    background: linear-gradient(90grad, red, blue);
    

六、时间单位

用于动画和过渡。

  • s(秒)、ms(毫秒)。
    animation: slide 2s ease-in;
    transition: opacity 300ms;
    

七、分辨率单位

用于高分辨率屏幕检测(媒体查询)。

  • dpi(每英寸点数)、dpcm(每厘米点数)、dppx(每像素点数)。
    @media (min-resolution: 2dppx) { ... } /* 视网膜屏 */
    

八、其他单位

  • lh:元素的行高(如 height: 2lh;)。
  • % 的特殊行为:
    • margin/padding 的百分比始终相对于父元素宽度
    • line-height 的百分比相对于当前字体大小。

最佳实践

  1. 响应式布局:优先使用 rem%vw/vh 或容器查询单位。
  2. 字体大小:用 rem 避免层级问题。
  3. 精确控制px 适合边框或小元素。
  4. 动态视口:使用 dvh 替代 vh 解决移动端工具栏问题。
/* 示例:综合使用 */
.container {width: min(90%, 1200px); /* 结合百分比和固定值 */padding: 2rem;margin: 0 auto;
}

通过合理选择单位,可实现灵活且自适应的布局。

CallBack Function 回调函数

function Run(CallBack){CallBack();
}function CallBack(){console.log("This is callBack Functions")
}Run(CallBack);

回调函数(Callback Function)是编程中一种常用的技术,它指的是将一个函数作为参数传递给另一个函数,并在特定事件发生或操作完成后调用这个被传入的函数。下面将从多个角度详细解释回调函数的概念、工作原理、使用场景及注意事项。


1. 回调函数的概念

简单来说,回调函数就是“把函数当作参数传进去”,在合适的时候由另一个函数来调用。这样做的主要目的是使程序具有更高的灵活性和可扩展性,例如处理异步操作、事件响应或定制化逻辑。


2. 回调函数的工作原理

回调函数的执行流程大致如下:

  1. 定义回调函数
    编写一个函数,它将用于在某个操作完成后执行特定的逻辑。

  2. 传递回调函数
    将这个回调函数作为参数传递给另一个函数。被调用的函数内部会保存这个回调函数的引用。

  3. 触发调用
    当某个事件发生或者特定操作完成时,被调用的函数会“回调”传入的函数,通常还会传入操作的结果或者状态信息。

例如,在异步编程中,常见的模式是启动一个耗时操作(比如网络请求或文件读写),操作完成后调用回调函数来处理结果,而不会阻塞程序的其他部分。


3. 常见的使用场景

3.1 异步编程

在处理耗时操作时(如网络请求、数据库查询、文件读写等),使用回调函数可以避免程序阻塞。例如,在 JavaScript 中,很多异步 API 都使用回调函数来通知操作完成后的结果:

// 模拟异步操作:读取数据
function fetchData(callback) {setTimeout(function() {let data = "数据加载完成";callback(data); // 操作完成后调用回调函数}, 1000);
}// 使用回调函数处理结果
fetchData(function(result) {console.log(result); // 输出:数据加载完成
});

3.2 事件处理

在用户界面编程中,经常需要对用户的操作(如点击、悬停等)做出响应。回调函数常常被注册为事件处理器:

// 在浏览器中注册点击事件的回调函数
document.getElementById("myButton").addEventListener("click", function() {alert("按钮被点击了!");
});

3.3 函数扩展

有时候,我们希望在某个函数执行完毕后能够插入一些自定义逻辑,而不修改原函数的实现。回调函数使这种扩展变得简单:

// 定义一个可以接受回调函数的函数
function processData(data, callback) {// 对数据进行处理let processedData = data.toUpperCase();// 调用回调函数,并传入处理后的数据callback(processedData);
}processData("hello", function(result) {console.log(result); // 输出:HELLO
});

4. 回调函数的注意事项

4.1 回调地狱(Callback Hell)

当多个回调函数嵌套使用时,会导致代码层层嵌套,难以阅读和维护。这种情况常被称为“回调地狱”。为了解决这个问题,现代编程中常使用 Promise、async/await 等方式来管理异步流程,从而提高代码的可读性和可维护性。

4.2 错误处理

在使用回调函数时,需要设计良好的错误处理机制。很多异步 API 采用“错误优先回调”(Error-First Callback)的模式,即回调函数的第一个参数用于传递错误信息。例如:

function fetchData(callback) {setTimeout(function() {// 模拟出错的情况let error = null; // 如果没有错误,则为 nulllet data = "数据加载完成";// 第一个参数为错误信息,第二个参数为数据callback(error, data);}, 1000);
}fetchData(function(err, result) {if (err) {console.error("发生错误:", err);} else {console.log(result); // 输出:数据加载完成}
});

5. 其他语言中的回调函数

回调函数不仅存在于 JavaScript 中,在许多其他编程语言中也有类似的概念。例如:

  • C/C++:常用于库函数或事件驱动编程中,通过函数指针实现回调。
  • Python:函数可以作为参数传递,许多框架(如 Flask、Django)也使用回调机制来处理请求或事件。

总结

回调函数是一种将函数作为参数传递并在特定时机执行的编程模式,它为处理异步操作、事件响应以及扩展程序逻辑提供了灵活且强大的机制。虽然回调函数非常实用,但在设计和实现时需要注意代码的可读性、错误处理以及避免过度嵌套(即回调地狱)等问题。

希望这篇详细解释能帮助你更好地理解和应用回调函数!

setTimeout 设置超时函数:

function CallBack(){console.log("This is callBack Functions0")
}Run(CallBack);//setTimeout(CallBackFunctionName,times(/ms));  //设置超时函数 setTimeout(function(){console.log("This is setTimeout Function0")
}, 3000);
//3s后打印 : "This is setTimeout Function0"setTimeout(() => {console.log("This is setTimeout Function2")
}, 2000);
//2s后打印 :"This is setTimeout Function2"setTimeout(CallBack,1000);
//1s后打印 : "This is setTimeout Function0"

定时器

​
setInterval(()=>{console.log("This is a Interval after 3 seconds");
},3000)  //每3s打印一次​

利用超时计数器来停止定时器

const intervalId = setInterval(()=>{console.log("This is a Interval after 3 seconds");
},3000)  //每3s打印一次const timeoutId = setTimeout(() => {console.log("This is a timeout after 2 seconds");
} , 2000);const timeoutOfStopIntervalId = setTimeout(() =>{clearInterval(intervalId);console.log("Clear interval after 10 seconds");
},10000); //10s后停止定时器

运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/70641.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenStack-Train版-Allinone自动化部署脚本

一、环境准备 操作系统&#xff1a;CentOS 7 或以上版本 建议配置&#xff1a; CPU&#xff1a;8 核或以上 内存&#xff1a;16 GB 或以上 磁盘&#xff1a;500 GB 或以上 网络配置&#xff1a; 确保虚拟机已配置静态 IP 地址 确保虚拟机可以正常访问外部网络 二、自动…

【0403】Postgres内核 检查(procArray )给定 db 是否有其他 backend process 正在运行

文章目录 1. 给定 db 是否有其他 backend 正在运行1.1 获取 allPgXact[] 索引1.1.1 MyProc 中 databaseId 初始化实现1.2 allProcs[] 中各 databaseId 判断1. 给定 db 是否有其他 backend 正在运行 CREATE DATABASE 语句创建用户指定 数据库名(database-name)时候, 会通过 …

git fetch和git pull 的区别

git pull 实际上就是 fetch merge 的缩写, git pull 唯一关注的是提交最终合并到哪里&#xff08;也就是为 git fetch 所提供的 destination 参数&#xff09; git fetch 从远程仓库下载本地仓库中缺失的提交记录,并更新远程分支指针 git pull抓取更新再合并到本地分支,相当于…

详解在Pytest中忽略测试目录的三种方法

关注开源优测不迷路 大数据测试过程、策略及挑战 测试框架原理&#xff0c;构建成功的基石 在自动化测试工作之前&#xff0c;你应该知道的10条建议 在自动化测试中&#xff0c;重要的不是工具 你是否曾因无关或过时的代码导致测试失败&#xff1f; 这可能会增加调试和故障排除…

SQL Server查询计划操作符(7.3)——查询计划相关操作符(6)

7.3. 查询计划相关操作符 48)Key Lookup:该操作符对一个有簇索引的表进行书签查找。参数列包含簇索引的名字和用于查找簇索引中数据行的簇键。该操作符总是伴随一个Nested Loops操作符。如果其参数列中出现WITH PREFETCH子句,则查询处理器已决定使用异步预取(预读,read-ah…

Python Pandas(5):Pandas Excel 文件操作

Pandas 提供了丰富的 Excel 文件操作功能&#xff0c;帮助我们方便地读取和写入 .xls 和 .xlsx 文件&#xff0c;支持多表单、索引、列选择等复杂操作&#xff0c;是数据分析中必备的工具。 操作方法说明读取 Excel 文件pd.read_excel()读取 Excel 文件&#xff0c;返回 DataF…

基于钉钉API的连接器实现:企业数据集成与自动化管理

文章目录 概要背景与需求钉钉API概述连接器实现小结 概要 在当今数字化时代&#xff0c;企业面临着海量数据的管理与整合挑战。钉钉作为国内广泛使用的办公协作平台&#xff0c;提供了丰富的API接口&#xff0c;支持企业进行数据集成与自动化管理。本文将介绍如何通过钉钉API实…

第六届MathorCup高校数学建模挑战赛-A题:淡水养殖池塘水华发生及池水自净化研究

目录 摘要 1 问题的重述 2 问题的分析 2.1 问题一的分析 2.2 问题二的分析 2.3 问题三的分析 2.4 问题四的分析 2.5 问题五的分析 3. 问题的假设 4. 符号说明 5. 模型的建立与求解 5.1 问题一的建模与求解 5.1.1 分析对象与指标的选取 5.1.2 折线图分析 5.1.3 相关性分析 5.1.4…

方舟字节码原理剖析:架构、特性与实践应用

方舟字节码原理剖析&#xff1a;架构、特性与实践应用 一、引言 在当今软件行业高速发展的大背景下&#xff0c;应用程序的性能、开发效率以及跨平台兼容性成为了开发者们关注的核心要素。编译器作为软件开发流程中的关键工具&#xff0c;其性能和特性直接影响着软件的质量和…

如何在Android Studio中开发一个简单的Android应用?

Android Studio是开发Android应用的官方集成开发环境&#xff08;IDE&#xff09;&#xff0c;它提供了许多强大的功能&#xff0c;使得开发者能够高效地创建Android应用。如果你是Android开发的初学者&#xff0c;本文将引导你如何在Android Studio中开发一个简单的Android应用…

使用 JFreeChart 创建动态图表:从入门到实战

文章目录 前言一、JFreeChart 简介二、环境准备三、 创建第一个折线图四、自定义图表样式4.1 设置背景色4.2 设置折线颜色4.3 设置字体&#xff08;解决中文乱码&#xff09;4.4 设置横坐标的标签宽度和方向 五、导出图表六、实战&#xff1a;动态生成日报图表总结 前言 在数据…

vue.js v-model实现原理

在 vue.js 3中&#xff0c;通过 v-model 指令可以方便实现表单元素数据双向绑定。实现 v-model 指令元素并不神奇&#xff0c;本质上是一种语法糖。实现原理其实是 v-bind 和 v-on 这两个指令。 v-bind 指令会将表单元素的 value 属性与一个变量绑定&#xff0c;简写为 :属性名…

Formality:探针(Probe Point)的设置与使用

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 一般情况下&#xff0c;verify命令会对参考设计和实现设计所有匹配的比较点各自进行验证&#xff0c;但有些时候为了调试&#xff0c;可能需要验证参考设计和实现设…

idea如何使用AI编程提升效率-在IntelliJ IDEA 中安装 GitHub Copilot 插件的步骤-卓伊凡

idea如何使用AI编程提升效率-在IntelliJ IDEA 中安装 GitHub Copilot 插件的步骤-卓伊凡 问题 idea编译器 安装copilot AI工具 实际操作 在 IntelliJ IDEA 中安装 GitHub Copilot 插件的步骤如下&#xff1a; 打开 IntelliJ IDEA&#xff1a; 打开你的 IntelliJ IDEA 应用…

【计算机网络】TCP/IP 网络模型有哪几层?

目录 应用层 传输层 网络层 网络接口层 总结 为什么要有 TCP/IP 网络模型&#xff1f; 对于同一台设备上的进程间通信&#xff0c;有很多种方式&#xff0c;比如有管道、消息队列、共享内存、信号等方式&#xff0c;而对于不同设备上的进程间通信&#xff0c;就需要网络通…

Spring Boot: 使用 @Transactional 和 TransactionSynchronization 在事务提交后发送消息到 MQ

Spring Boot: 使用 Transactional 和 TransactionSynchronization 在事务提交后发送消息到 MQ 在微服务架构中&#xff0c;确保消息的可靠性和一致性非常重要&#xff0c;尤其是在涉及到分布式事务的场景中。本文将演示如何使用 Spring Boot 的事务机制和 TransactionSynchron…

c/c++蓝桥杯经典编程题100道(14)矩阵转置

矩阵转置 ->返回c/c蓝桥杯经典编程题100道-目录 目录 矩阵转置 一、题型解释 二、例题问题描述 三、C语言实现 解法1&#xff1a;使用额外空间&#xff08;难度★&#xff09; 解法2&#xff1a;原地转置&#xff08;仅限方阵&#xff0c;难度★★&#xff09; 四、…

整合 Redis 分布式锁:从数据结构到缓存问题解决方案

引言 在现代分布式系统中&#xff0c;Redis 作为高性能的键值存储系统&#xff0c;广泛应用于缓存、消息队列、实时计数器等多种场景。然而&#xff0c;在高并发和分布式环境下&#xff0c;如何有效地管理和控制资源访问成为一个关键问题。Redis 分布式锁正是为了解决这一问题…

(done) openMP学习 (Day10: Tasks 原语)

url: https://dazuozcy.github.io/posts/introdution-to-openmp-intel/#19-%E6%8A%80%E8%83%BD%E8%AE%AD%E7%BB%83%E9%93%BE%E8%A1%A8%E5%92%8Copenmp 本章节内容仅提供引入&#xff0c;关于 task 更详细的细节请看 openMP 手册或者源材料 Day9 介绍了一个优化链表遍历的粗糙方…

《代码随想录第二十八天》——回溯算法理论基础、组合问题、组合总和III、电话号码的字母组合

《代码随想录第二十八天》——回溯算法理论基础、组合问题、组合总和III、电话号码的字母组合 本篇文章的所有内容仅基于C撰写。 1. 基础知识 1.1 概念 回溯是递归的副产品&#xff0c;它也是遍历树的一种方式&#xff0c;其本质是穷举。它并不高效&#xff0c;但是比暴力循…