从ES5迈向ES6:探索 JavaScript 新增声明命令与解构赋值的魅力


在这里插入图片描述



个人主页:学习前端的小z

个人专栏:JavaScript 精粹

本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结,欢迎大家在评论区交流讨论!
在这里插入图片描述


ES5、ES6介绍


文章目录

  • 💯声明命令 let、const
    • 🍟1 let声明符
      • 🎲1.1 基础特性
      • 🎲1.2 不进行变量提升
      • 🎲1.3 致死域(暂时性死区)
      • 🎲1.4 无法重复声明
      • 🎲1.5 块作用域 (block scope)
      • 🎲1.6 块作用域下的函数声明
    • 🍟2 const声明符
      • 🎲2.1 声明时必须赋值
      • 🎲2.2 值为对象
  • 💯解构赋值
    • 🍟1 数组解构
      • 🎲1.1 基础变量赋值
      • 🎲1.2 声明分别赋值
      • 🎲1.3 解构默认值
      • 🎲1.4 交换变量值
      • 🎲1.5 解析函数返回的数组
      • 🎲1.6 忽略返回值/跳过某项
      • 🎲1.7 赋值数组剩余值给一个变量
      • 🎲1.8 嵌套数组解构
    • 🍟2 对象解构
      • 🎲2.1 基础对象解构
      • 🎲2.2 无声明解构
      • 🎲2.3 赋值给新变量名
      • 🎲2.4 解构默认值
      • 🎲2.5 赋值给新变量名的同时提供默认值
      • 🎲2.6 嵌套对象和数组解构
      • 🎲2.7 可计算对象属性名与解构
      • 🎲2.8 同时使用数组和对象解构
      • 🎲2.9 注意点
    • 🍟3 函数参数的解构赋值
    • 🍟4 解构的用途
      • 🎲4.1 交换变量的值
      • 🎲4.2 从函数返回多个值
      • 🎲4.3 函数参数的定义
      • 🎲4.4 提取 JSON 数据
      • 🎲4.5 函数参数的默认值


在这里插入图片描述


💯声明命令 let、const

🍟1 let声明符

ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

🎲1.1 基础特性

if(true){
  let a = 'let';
  var b = 'var';
}

console.log(b); //var
console.log(a); //Uncaught ReferenceError: a is not defined

---------------------------------------------------------

//使用let,声明的变量仅在块级作用域内({ })有效,最后输出的是 6。
for(let i = 0; i < 10; i++){
    
}
console.log(i); //Uncaught ReferenceError: i is not defined

上面代码在代码块之中,分别用letvar声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效。

// 在循环体表达式中let声明迭代变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量
var a = [];
for (let i = 0; i < 10; i++) {
  a.push(function () {
    console.log(i);
  });
}
a[5](); // 5
// 在循环体表达式中let声明 和循环体中let 声明同名变量是不冲突的 设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。相当于每次循环{}内部都会单独开一个局部作用域
for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}

🎲1.2 不进行变量提升

var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined

let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。 这一点需要特殊注意

// var 的情况
console.log(num); // 输出undefined
var num = 2;

-------------------------
    
// let 的情况
console.log(age); // 报错ReferenceError
let age = 16;

🎲1.3 致死域(暂时性死区)

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

//正常调用
let num = 10;
if (true) {
    console.log(num); //10
}

------------------

//if { }内部let为独立局部作用域 访问为 20
let num = 10;
if (true) {
    let num = 20;
    console.log(num); //20
}

------------------


//发生致死 因为fn局部作用域中有let声明num 所以在作用域内 不能先调用再使用let声明。
let num = 10;
function fn() {
    console.log(num); //Uncaught ReferenceError: Cannot access 'num' before initialization
    let num = 20;
}
fn();


------------------

//typeof操作影响

typeof num;
let num; //Uncaught ReferenceError: Cannot access 'num' before initialization

当程序的控制流程在新的作用域(module function 或 block 作用域)进行实例化时,在此作用域中用let/const声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,所以是不能被访问的,如果访问就会抛出错误。因此,在这运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时死区。

es6规定 let/const 会使区域形成封闭的作用域 若在声明之前使用变量就会发生错误, 在代码块内使用let命令声明变量之前 该变量都无法使用,称为“暂时性死区”(temporal dead zone,简称 TDZ)。总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。使用let 确保先 声明 再 使用 变量 不要混用let和var在同一个作用域链上 避免死区

🎲1.4 无法重复声明

let不允许在相同作用域内,重复声明同一个变量。

//发生致死 因为var会变量提升。
let num = 10;
if (true) {
    var num = 20; //Uncaught SyntaxError: Identifier 'num' has already been declared
    console.log(num);
}

🎲1.5 块作用域 (block scope)

在ES5中,只全局作用域和函数作用域。这会导致函数作用域覆盖了全局作用域;亦或者循环中的变量泄露为全局变量。

EcmaScript 6引入了块级作用域(block scope),块级作用域只能在块中被访问,以下两种情况可以创建块级作用域的变量。

  • 在函数中

  • 在被{}包裹的块中

{
    var x = 10;
}
console.log(x); //10

------------------

{
    let x = 10;
}
console.log(x);//x is not defined

------------------

//函数有两个代码块,都声明了变量num,运行后输出 3。这表示外层代码块不受内层代码块的影响。如果两次都使用var定义变量num,最后输出的值才是 6。
function fn() {
  let num = 3;
  if (true) {
    let num = 6;
  }
  console.log(num); // 3
}

🎲1.6 块作用域下的函数声明

ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。

ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。

function a() {
    console.log('我是全局作用域内声明的函数a');
}

(function () {
    if (false) {
        function a() {
            console.log('我是块级作用域内声明的函数a');
        }
    }
    a();
})();

----------------------


function a() {
    console.log('我是全局作用域内声明的函数a');
}
(function () {
    var a;
    if (false) {
        a = function () {
            console.log('我是块级作用域内声明的函数a');
        }
    }
    a();
})();

为了减轻因此产生的不兼容问题,ES6 在附录 B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。

  • 允许在块级作用域内声明函数。
  • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
  • 同时,函数声明还会提升到所在的块级作用域的头部。

🍟2 const声明符

const声明一个只读的常量。一旦声明,常量的值就不能改变。 const与let在 块作用域 重复声明 致死域的问题上是一致的 const的作用域与let命令相同:只在声明所在的块级作用域内有效。

const DATA = '我是常量 不能改变哦';
DATA //  '我是常量 不能改变哦'

DATA = '改一个试试看';
// TypeError: Assignment to constant variable.

const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

🎲2.1 声明时必须赋值

const X;
//Uncaught SyntaxError: Missing initializer in const declaration

🎲2.2 值为对象

const KEY_MAP = {
    a:1,
    b:2
}

KEY_MAP['a'] = 2; //不报错

-----------
    
const ARRAY = [];
ARRAY.push('something'); // 可执行
ARRAY.length = 0;    // 可执行
ARRAY = ['something'];    // 报错

在这里插入图片描述


💯解构赋值

ES6提供了更简洁的赋值模式, 从数组和对象中提取值. 这被称为解构(Destructuring)。

[a, b] = [50, 100];

console.log(a);
// expected output: 50

console.log(b);
// expected output: 100

[a, b, ...rest] = [10, 20, 30, 40, 50];

console.log(rest);
// expected output: [30, 40, 50]

我们有很多种不同的方式使用 JavaScript 解构。

🍟1 数组解构

数组解构是极为简单整洁的,在复制表达式的左侧使用数组字面量。数组字面量中的每个变量名称映射为解构数组的相同索引项。

🎲1.1 基础变量赋值

let foo = ['one', 'two', 'three'];

let [red, yellow, green] = foo;
console.log(red); // "one"
console.log(yellow); // "two"
console.log(green); // "three"

🎲1.2 声明分别赋值

你可以通过变量声明分别解构赋值。举例:首先,声明变量,然后分别赋值。

// 声明变量
let a, b;
// 然后分别赋值
[a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2

🎲1.3 解构默认值

如果解构取出的值是 undefined,可以设置默认值:

let a, b;
// 设置默认值
[a = 5, b = 7] = [1];
console.log(a); // 1
console.log(b); // 7

在上面的例子中,我们给 ab 设置了默认值。这种情况下,如果 ab 的值是 undefined,它将赋值默认值 5a 7b

🎲1.4 交换变量值

解构可以在一个解构表达式中交换两个变量值

let a = 1;
let b = 3;

[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1

如果你想不使用解构交换变量值,将必须提供一个缓存变量或者同解构一起使用

🎲1.5 解析函数返回的数组

可以解构函数返回的数组。

function c() {
  return [10, 20];
}

let a, b;
[a, b] = c();
console.log(a); // 10
console.log(b); // 20

在上面的例子中,c() 的返回值 [10, 20] 可以在单独的一行代码中使用解构解析。

🎲1.6 忽略返回值/跳过某项

你也可以跳过一些没有用的返回值。

function c() {
  return [1, 2, 3];
}

let [a, , b] = c();
console.log(a); // 1
console.log(b); // 3

在罕见的情况下,你想忽略所有的值。

[, ,] = c();

当然,这是不会发生的。

🎲1.7 赋值数组剩余值给一个变量

当你使用数组解构,你可以赋值数组剩余部分给一个单独的变量。

let [a, ...b] = [1, 2, 3];
console.log(a); // 1
console.log(b); // [2, 3]

小心结尾的逗号语法错误,它将爆发如果在剩余元素的左侧使用结尾逗号:

let [a, ...b,] = [1, 2, 3];
// SyntaxError: rest element may not have a trailing comma

🎲1.8 嵌套数组解构

像对象一样,你也可以使用数组嵌套解构。这里有一个例子:

const color = ['#FF00FF', [255, 0, 255], 'rgb(255, 0, 255)'];

// Use nested destructuring to assign red, green and blue
// 使用嵌套解构赋值 red, green, blue
const [hex, [red, green, blue]] = color;

console.log(hex, red, green, blue); // #FF00FF 255 0 255

🍟2 对象解构

🎲2.1 基础对象解构

let x = { y: 22, z: true };
let { y, z } = x; // let {y:y,z:z} = x;的简写

console.log(y); // 22
console.log(z); // true

🎲2.2 无声明解构

你可以使用解构分别从它的声明赋值变量。这意味着在上面的例子中不需要创建变量 x

let y, z;

({ y, z } = { y: 1, z: 2 });

注意:圆括号 (...) 包裹赋值声明是必须的当使用对象字面量解构赋值无声明变量。

{a, b} = {a: 1, b: 2} 不是有效的独立语法,左侧的 {a, b} 被考虑为代码块而不是一个对象字面量。

因此,({a, b} = {a: 1, b: 2}) 是有效的, 等价于 var {a, b} = {a: 1, b: 2}

(...) 表达式需要前置分号或者它可能用于在前一行执行函数。

🎲2.3 赋值给新变量名

当使用对象解构时你也可以改变变量的名称,如下例子:

let o = { p: 22, q: true };
let { p: foo, q: bar } = o;

console.log(foo); // 22
console.log(bar); // true

例子中,var {p: foo} = o 获取对象 o 的属性名 p,然后赋值给一个名称为 foo 的变量。

🎲2.4 解构默认值

如果解构取出的对象值是 undefined 你也可以设置默认值。

let { a = 10, b = 5 } = { a: 3 };

console.log(a); // 3
console.log(b); // 5

🎲2.5 赋值给新变量名的同时提供默认值

let { a: aa = 10, b: bb = 5 } = { a: 3 };

console.log(aa); // 3
console.log(bb); // 5

🎲2.6 嵌套对象和数组解构

const metadata = {
  title: 'Scratchpad',
  translations: [
    {
      locale: 'de',
      localization_tags: [],
      last_edit: '2014-04-14T08:43:37',
      url: '/de/docs/Tools/Scratchpad',
      title: 'JavaScript-Umgebung',
    },
  ],
  url: '/en-US/docs/Tools/Scratchpad',
};

let {
  title: englishTitle, // 重命名
  translations: [
    {
      title: localeTitle, // 重命名
    },
  ],
} = metadata;

console.log(englishTitle); // "Scratchpad"
console.log(localeTitle); // "JavaScript-Umgebung"

🎲2.7 可计算对象属性名与解构

当使用解构改变对象属性的名称时,可以使用对象计算属性名。

let key = 'z';
let { [key]: foo } = { z: 'bar' };

console.log(foo); // "bar"

在上面的例子中,我们计算变量键值并改变它的名称为 foo

🎲2.8 同时使用数组和对象解构

在解构中数组和对象可以联合使用:

const props = [
  { id: 1, name: 'Fizz' },
  { id: 2, name: 'Buzz' },
  { id: 3, name: 'FizzBuzz' },
];

const [, , { name }] = props;

console.log(name); // "FizzBuzz"

所有的解构赋值语法是相同的,是在赋值符号左侧声明从源变量取出的值。举例来说:

let x = [1, 2, 3, 4, 5];
let [y, z] = x;
console.log(y); // 1
console.log(z); // 2

🎲2.9 注意点

(1)如果要将一个已经声明的变量用于解构赋值,必须非常小心。

// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error

上面代码的写法会报错,因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。

// 正确的写法
let x;
({x} = {x: 1});

上面代码将整个解构赋值语句,放在一个圆括号里面,就可以正确执行。

(2)解构赋值允许等号左边的模式之中,不放置任何变量名。因此,可以写出非常古怪的赋值表达式。

({} = [true, false]);
({} = 'abc');
({} = []);

上面的表达式虽然毫无意义,但是语法是合法的,可以执行。

(3)由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3

上面代码对数组进行对象解构。数组arr0键对应的值是1[arr.length - 1]就是2键,对应的值是3。方括号这种写法,属于“属性名表达式”

🍟3 函数参数的解构赋值

函数的参数也可以使用解构赋值。

function add([x, y]){
  return x + y;
}

add([1, 2]); // 3

上面代码中,函数add的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量xy。对于函数内部的代码来说,它们能感受到的参数就是xy

下面是另一个例子。

[[1, 2], [3, 4]].map(([a, b]) => a + b); 
// [ 3, 7 ]

函数参数的解构也可以使用默认值。

function move({x = 0, y = 0} = {}) {
  return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]

上面代码中,函数move的参数是一个对象,通过对这个对象进行解构,得到变量xy的值。如果解构失败,xy等于默认值。

注意,下面的写法会得到不一样的结果。

function move({x, y} = { x: 0, y: 0 }) {
  return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]

上面代码是为函数move的参数指定默认值,而不是为变量xy指定默认值,所以会得到与前一种写法不同的结果。

undefined就会触发函数参数的默认值。

[1, undefined, 3].map((x = 'yes') => x);
// [ 1, 'yes', 3 ]

🍟4 解构的用途

变量的解构赋值用途很多。

🎲4.1 交换变量的值

let x = 1;
let y = 2;

[x, y] = [y, x];

上面代码交换变量xy的值,这样的写法不仅简洁,而且易读,语义非常清晰。

🎲4.2 从函数返回多个值

函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。

// 返回一个数组

function example() {
  return [1, 2, 3];
}
let [a, b, c] = example();

// 返回一个对象

function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();

🎲4.3 函数参数的定义

解构赋值可以方便地将一组参数与变量名对应起来。

// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);

// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});

🎲4.4 提取 JSON 数据

解构赋值对提取 JSON 对象中的数据,尤其有用。

let jsonData = {
  id: 42,
  status: "OK",
  data: [867, 5309]
};

let { id, status, data: number } = jsonData;

console.log(id, status, number);
// 42, "OK", [867, 5309]

上面代码可以快速提取 JSON 数据的值。

🎲4.5 函数参数的默认值

jQuery.ajax = function (url, {
  async = true,
  beforeSend = function () {},
  cache = true,
  complete = function () {},
  crossDomain = false,
  global = true,
  // ... more config
} = {}) {
  // ... do stuff
};

指定参数的默认值,就避免了在函数体内部再写var foo = config.foo || 'default foo';这样的语句。


在这里插入图片描述


JavaScript: https://developer.mozilla.org/en-US/docs/Web/JavaScript

在这里插入图片描述


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码生成器(一)---项目概述以及项目初始化

目录 一、项目概述 1.代码生成器解决的问题 2.代码生成器的实际应用 3.本地代码生成器的业务流程 4.实现思路 二、项目初始化 项目Gitee地址&#xff1a;Code-Generator: 代码生成器&#xff01;&#xff01;&#xff01; 一、项目概述 1.代码生成器解决的问题 代码生成器本…

使用vue和element_ui搭建后端页面

使用vue和element_ui搭建后台管理页面 效果顶部和左侧内容固定&#xff0c;中间内容滚动 <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"&g…

地理信息系统(GIS)软件开发

地理信息系统&#xff08;GIS&#xff09;软件开发是一项复杂且系统性很强的工程&#xff0c;涉及空间数据的采集、管理、分析和展示。以下是一个典型的GIS软件开发流程&#xff0c;包括各个步骤的详细说明。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#…

2024电工杯B题食谱评价与优化模型思路代码论文分析

2024年电工杯数学建模竞赛B题论文和代码已完成&#xff0c;代码为B题全部问题的代码&#xff0c;论文包括摘要、问题重述、问题分析、模型假设、符号说明、模型的建立和求解&#xff08;问题1模型的建立和求解、问题2模型的建立和求解、问题3模型的建立和求解&#xff09;、模型…

【STL专题】深入探索C++之std::string:不止于字符串【万字详解】

欢迎来到CILMY23的博客 &#x1f3c6;本篇主题为&#xff1a;深入探索C之std::string&#xff1a;不止于字符串 &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 | 贪心算法 | Linux &#x1f3…

Nginx - 一键实现Nginx的快速安装和优化配置

文章目录 思路实现二次优化 思路 初始化下载工具目录并下载依赖&#xff1a; 创建临时目录 /tmp/tools。下载 OpenSSL、PCRE 和 Zlib 的压缩包。解压这些依赖包到指定目录。 设置NGINX的用户和脚本&#xff1a; 添加 nginx 用户。创建目录和启动、停止、重载NGINX的脚本。 安装…

如何异地组网添加摄像机?

本文将介绍如何使用天联技术实现异地组网添加摄像机&#xff0c;并保障数据的安全性。 安防摄像机的应用愈发广泛&#xff0c;无论是家庭安防还是企业监控&#xff0c;摄像机都扮演着重要角色。在一些特殊场合或者特殊需求下&#xff0c;我们需要将摄像机添加到异地网络中进行监…

Web开发——HTMLCSS

1、概述 Web开发分前端开发和后端开发&#xff0c;前端开发负责展示数据&#xff0c;后端开发负责处理数据。 HTML&CSS是浏览器数据展示相关的内容。 1&#xff09;网页的组成部分 文字、图片、音频、视频、超链接、表格等等 2&#xff09;网页背后的本质 程序员写的前端…

神经网络基础结构

1. 神经网络 在神经网络中&#xff0c;每个神经元都有一个与之关联的权重和偏置&#xff0c;它们用于计算神经元的输出值。神经元接收来自上一层神经元的输入&#xff0c;并将这些输入与权重相乘并加上偏置&#xff0c;然后通过激活函数进行非线性处理&#xff0c;最终产生输出…

Qt案例练习(有源码)

项目源码和资源&#xff1a;Qt案例练习: qt各种小案例练习,有完整资源和完整代码 1.案例1 项目需求&#xff1a;中间为文本框&#xff0c;当点击上面的复选框和单选按钮时&#xff0c;文本框内的文本会进行相应的变化。 代码如下&#xff1a; #include "dialog.h" …

【全开源】智能名片系统源码(Fastadmin+ThinkPHP和Uniapp)

数字时代的新名片&#xff0c;连接未来的桥梁 引言 在数字化浪潮的推动下&#xff0c;传统名片已经逐渐淡出人们的视线。取而代之的是智能名片系统&#xff0c;它以其高效、便捷和智能化的特点&#xff0c;成为了商务交流的新宠。而智能名片系统源码&#xff0c;作为其核心驱…

nextcloud 安装部署

php版本不对 ubuntu nginx 配置php 网站-CSDN博客 抄自chatgpt ubuntu完全卸载干净某个包-CSDN博客 以及设置基本的php nginx环境参照上面两篇博文 然后参照官方文档 Example installation on Ubuntu 22.04 LTS — Nextcloud latest Administration Manual latest document…

datasheet芯片数据手册—新手入门学习(二)【8-18】

参考芯片手册已经上传&#xff0c;可自行下载 因为芯片参考手册内容比较多&#xff0c;故再一次介绍本文内容主要讲解章节。 目录 8、内容介绍 命令真值表 9、Command Definitions 10、READ Operations &#xff08;1&#xff09;页面读取操作 &#xff08;2&#xff…

Docker 开启 SSL 验证

最近看 OJ 项目的远程开发阶段&#xff0c;然后踩坑踩了 2 天&#x1f602; Docker 版本&#xff1a;在 CentOS 安装 sudo yum install docker-ce-20.10.9 docker-ce-cli-20.10.9 containerd.io Client: Docker Engine - CommunityVersion: 20.10.9API version: …

1673. 找出最具竞争力的子序列

题目 给定一个整数数组 nums 和一个正整数 k&#xff0c;返回长度为 k 且最具竞争力的 nums 子序列。 数组的子序列是从数组中删除一些元素&#xff08;可能不删除元素&#xff09;得到的序列。 在子序列 a 和子序列 b 第一个不相同的位置上&#xff0c;如果 a 中的数字小于…

Redis系统架构中各个处理模块是干什么的?no.19

Redis 系统架构 通过前面的学习&#xff0c;相信你已经掌握了 Redis 的原理、数据类型及访问协议等内容。本课时&#xff0c;我将进一步分析 Redis 的系统架构&#xff0c;重点讲解 Redis 系统架构的事件处理机制、数据管理、功能扩展、系统扩展等内容。 事件处理机制 Redis…

[论文精读]Variational Bayesian Last Layers

论文网址&#xff1a;Variational Bayesian Last Layers (arxiv.org) 论文代码&#xff1a;GitHub - VectorInstitute/vbll: Simple (and cheap!) neural network uncertainty estimation 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以…

leetcode437 路径总和III-哈希表+前缀和

题目 给定一个二叉树的根节点 root &#xff0c;和一个整数 targetSum &#xff0c;求该二叉树里节点值之和等于 targetSum 的 路径 的数目。 路径 不需要从根节点开始&#xff0c;也不需要在叶子节点结束&#xff0c;但是路径方向必须是向下的&#xff08;只能从父节点到子节…

服务器数据恢复—EVA存储多块硬盘离线导致部分LUN丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 1台某品牌EVA4400控制器3台EVA4400扩展柜28块FC硬盘。 服务器故障&#xff1a; 由于两块磁盘掉线导致存储中某些LUN不可用&#xff0c;某些LUN丢失&#xff0c;导致存储崩溃。 服务器数据恢复过程&#xff1a; 1、由于EVA4400存储故障是某些磁…

Web API——获取DOM元素

目录 1、根据选择器来获取DOM元素 2.、根据选择器来获取DOM元素伪数组 3、根据id获取一个元素 4、通过标签类型名获取所有该标签的元素 5、通过类名获取元素 目标&#xff1a;能查找/获取DOM对象 1、根据选择器来获取DOM元素 语法&#xff1a; document.querySelector(css选择…