【JS进阶】第一天

news2025/1/13 13:50:56

参考视频——黑马程序员

JavaScript 进阶 - 第 1 天

学习作用域、变量提升、闭包等语言特征,加深对 JavaScript 的理解,掌握变量赋值、函数声明的简洁语法,降低代码的冗余度。

  • 理解作用域对程序执行的影响
  • 能够分析程序执行的作用域范围
  • 理解闭包本质,利用闭包创建隔离作用域
  • 了解什么变量提升及函数提升
  • 掌握箭头函数、解析剩余参数等简洁语法

一、作用域

了解作用域对程序执行的影响及作用域链的查找机制,使用闭包函数创建隔离作用域避免全局变量污染。

作用域(scope)规定了变量能够被访问的“范围”,离开了这个“范围”变量便不能被访问,作用域分为全局作用域和局部作用域。

1.1局部作用域

局部作用域分为函数作用域和块作用域。

函数作用域

在函数内部声明的变量只能在函数内部被访问,外部无法直接访问。

<script>
  // 声明 counter 函数
  function counter(x, y) {
    // 函数内部声明的变量
    const s = x + y;
    console.log(s); // 18
  }
  // 设用 counter 函数
  counter(10, 8);
  // 访问变量 s
  console.log(s); // 报错
</script>

总结:

  1. 函数内部声明的变量,在函数外部无法被访问
  2. 函数的参数也是函数内部的局部变量
  3. 不同函数内部声明的变量无法互相访问
  4. 函数执行完毕后,函数内部的变量实际被清空了
块作用域

在 JavaScript 中使用 {} 包裹的代码称为代码块,代码块内部声明的变量外部将【有可能】无法被访问。

<script>
  {
    // age 只能在该代码块中被访问
    let age = 18;
    console.log(age); // 正常
  }

  // 超出了 age 的作用域
  console.log(age); // 报错

  let flag = true;
  if (flag) {
    // str 只能在该代码块中被访问
    let str = "hello world!";
    console.log(str); // 正常
  }

  // 超出了 age 的作用域
  console.log(str); // 报错

  for (let t = 1; t <= 6; t++) {
    // t 只能在该代码块中被访问
    console.log(t); // 正常
  }

  // 超出了 t 的作用域
  console.log(t); // 报错
</script>

JavaScript 中除了变量外还有常量,常量与变量本质的区别是【常量必须要有值且不允许被重新赋值】,常量值为对象时其属性和方法允许重新赋值。

<script>
  // 必须要有值
  const version = "1.0.0";

  // 不能重新赋值
  // version = '1.0.1';

  // 常量值为对象类型
  const user = {
    name: "小明",
    age: 18,
  };

  // 不能重新赋值
  user = {};

  // 属性和方法允许被修改
  user.name = "小小明";
  user.gender = "男";
</script>

总结:

  1. let 声明的变量会产生块作用域,var 不会产生块作用域
  2. const 声明的常量也会产生块作用域
  3. 不同代码块之间的变量无法互相访问
  4. 推荐使用 letconst

注:开发中 letconst 经常不加区分的使用,如果担心某个值会不小被修改时,则只能使用 const 声明成常量。

1.2 全局作用域

<script> 标签和 .js 文件的【最外层】就是所谓的全局作用域,在此声明的变量在函数内部也可以被访问。

<script>
  // 此处是全局

  function sayHi() {
    // 此处为局部
  }

  // 此处为全局
</script>

全局作用域中声明的变量,任何其它作用域都可以被访问,如下代码所示:

<script>
  // 全局变量 name
  const name = "小明";

  // 函数作用域中访问全局
  function sayHi() {
    // 此处为局部
    console.log("你好" + name);
  }

  // 全局变量 flag 和 x
  const flag = true;
  let x = 10;

  // 块作用域中访问全局
  if (flag) {
    let y = 5;
    console.log(x + y); // x 是全局的
  }
</script>

总结:

  1. window 对象动态添加的属性默认也是全局的,不推荐!
  2. 函数中未使用任何关键字声明的变量为全局变量,不推荐!!!
  3. 尽可能少的声明全局变量,防止全局变量被污染

JavaScript 中的作用域是程序被执行时的底层机制,了解这一机制有助于规范代码书写习惯,避免因作用域导致的语法错误。

1.3 作用域链

在解释什么是作用域链前先来看一段代码:

<script>
  // 全局作用域
  let a = 1;
  let b = 2;
  // 局部作用域
  function f() {
    let c;
    // 局部作用域
    function g() {
      let d = "yo";
    }
  }
</script>

函数内部允许创建新的函数,f 函数内部创建的新函数 g,会产生新的函数作用域,由此可知作用域产生了嵌套的关系。

如下图所示,父子关系的作用域关联在一起形成了链状的结构,作用域链的名字也由此而来。

作用域链本质上是底层的变量查找机制,在函数被执行时,会优先查找当前函数作用域中查找变量,如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域,如下代码所示:

<script>
  // 全局作用域
  let a = 1;
  let b = 2;

  // 局部作用域
  function f() {
    let c;
    // let a = 10;
    console.log(a); // 1 或 10
    console.log(d); // 报错

    // 局部作用域
    function g() {
      let d = "yo";
      // let b = 20;
      console.log(b); // 2 或 20
    }

    // 调用 g 函数
    g();
  }

  console.log(c); // 报错
  console.log(d); // 报错

  f();
</script>

总结:

  1. 嵌套关系的作用域串联起来形成了作用域链
  2. 相同作用域链中按着从小到大的规则查找变量
  3. 子作用域能够访问父作用域,父级作用域无法访问子级作用域

1.4 垃圾回收机制

  1. 引用计数
  2. 标记清除法(常用

1.5 闭包

闭包 : 内层函数 + 外层函数变量

闭包是一种比较特殊和函数,使用闭包能够访问函数作用域中的变量。从代码形式上看闭包是一个做为返回值的函数,如下代码所示:

<body>
  <script>
    // 1. 闭包 : 内层函数 + 外层函数变量
    // function outer() {
    //   const a = 1
    //   function f() {
    //     console.log(a)
    //   }
    //   f()
    // }
    // outer()

    // 2. 闭包的应用: 实现数据的私有。统计函数的调用次数
    // let count = 1
    // function fn() {
    //   count++
    //   console.log(`函数被调用${count}次`)
    // }

    // 3. 闭包的写法  统计函数的调用次数
    function outer() {
      let count = 1;
      function fn() {
        count++;
        console.log(`函数被调用${count}`);
      }
      return fn;
    }
    const re = outer();
    // const re = function fn() {
    //   count++
    //   console.log(`函数被调用${count}次`)
    // }
    re();
    re();
    // const fn = function() { }  函数表达式
    // 4. 闭包存在的问题: 可能会造成内存泄漏
  </script>
</body>
const fun1 = () => {
  const a = 1;
  return () => {
    console.log("a", a);
  };
};
const fun = fun1();
fun();

总结:

  1. 怎么理解闭包?
  • 闭包 = 内层函数 + 外层函数的变量
  1. 闭包的作用?
  • 封闭数据,实现数据私有,外部也可以访问函数内部的变量
  • 闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来
  1. 闭包可能引起的问题?
  • 内存泄漏(没有被回收),因为外层函数 return 内层函数,又被全局作用域使用,而全局作用域暂时不会被销毁;再根据标记消除法,一直能找到 fn,fn 找到 i,所以会泄露

变量提升

变量提升是 JavaScript 中比较“奇怪”的现象(是一种缺陷),它允许在变量声明之前即被访问,仅存在于var声明变量
注意:

  1. 在代码在执行之前,首先会把所有在当前作用域下,所有var声明的变量提升到当前作用域的最前面
  2. 只提升声明,不提升赋值
    例如:
// 初始代码:
console.log("num是:", num);
var num = 10;

// 提升后 :
var num;
console.log("num是:", num);
num = 10;

<script>
  // 访问变量 str
  console.log(str + "world!");

  // 声明变量 str
  var str = "hello ";
</script>

因为不提升赋值,所以打印出来的是undefined
在这里插入图片描述例子2:
在这里插入图片描述
提升后:
在这里插入图片描述

总结:

  1. 变量在未声明即被访问时会报语法错误
  2. 变量在声明之前即被访问,变量的值为 undefined
  3. let 声明的变量不存在变量提升,推荐使用 let
  4. 变量提升出现在相同作用域当中
  5. 实际开发中推荐先声明再访问变量

注:关于变量提升的原理分析会涉及较为复杂的词法分析等知识,而开发中使用 let 可以轻松规避变量的提升,因此在此不做过多的探讨,有兴趣可查阅资料。

二、函数

知道函数参数默认值、动态参数、剩余参数的使用细节,提升函数应用的灵活度,知道箭头函数的语法及与普通函数的差异。

2.1 函数提升

函数提升与变量提升比较类似,是指函数在声明之前即可被调用
注意:

  1. 会把所有函数声明提升到当前作用域的最前面
  2. 只提升函数声明,不提升函数调用
<script>
  // 调用函数
  foo();
  // 声明函数
  function foo() {
    console.log("声明之前即被调用...");
  }

  // 不存在提升现象
  bar(); // 错误
  var bar = function () { // 函数表达式
    console.log("函数表达式不存在提升现象...");
  };
  // 相当于:
  var bar;
  bar();
  bar =  function () { // 函数表达式
    console.log("函数表达式不存在提升现象...");
  };
</script>

在这里插入图片描述在这里插入图片描述

总结:

  1. 函数提升能够使函数的声明调用更灵活
  2. 函数表达式不存在提升的现象
  3. 函数提升出现在相同作用域当中

2.2 函数参数

函数参数的使用细节,能够提升函数应用的灵活度。
还有形参实参,不再赘述

默认值
<script>
  // 设置参数默认值
  function sayHi(name = "小明", age = 18) {
    document.write(`<p>大家好,我叫${name},我今年${age}岁了。</p>`);
  }
  // 调用函数
  sayHi();
  sayHi("小红");
  sayHi("小刚", 21);
</script>

总结:

  1. 声明函数时为形参赋值即为参数的默认值
  2. 如果参数未自定义默认值时,参数的默认值为 undefined
  3. 调用函数时没有传入对应实参时,参数的默认值被当做实参传入
动态参数

arguments 是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参。

<script>
  // 求生函数,计算所有参数的和
  function sum() {
    // console.log(arguments)
    let s = 0;
    for (let i = 0; i < arguments.length; i++) {
      s += arguments[i];
    }
    console.log(s);
  }
  // 调用求和函数
  sum(5, 10); // 两个参数
  sum(1, 2, 4); // 两个参数
</script>

在这里插入图片描述

function fun() {
  console.log("argument", arguments);
  let sum = 0;
  //   arguments 对象并不是一个真正的数组,
  //   它是一个类似数组的对象,但没有数组的方法,比如 map
  let argsArray = Array.from(arguments); // 将 arguments 转换为数组
  argsArray.map((item) => {
    sum += item;
  });

  console.log("sum", sum);
}
fun(2, 2, 3, 6, 9, 8);

或者:

function fun() {
  console.log("argument", arguments);

  //   arguments 对象并不是一个真正的数组,
  //   它是一个类似数组的对象,但没有数组的方法,比如 map
  let argsArray = Array.from(arguments); // 将 arguments 转换为数组
  const result = argsArray.reduce((sum, item) => {
    return (sum += item);
  }, 0);

  console.log("result", result);
}
fun(2, 2, 3, 6, 9, 8);

总结:

  1. arguments 是一个伪数组(不能使用pushmap等方法),只存在函数中
  2. arguments 的作用是动态获取函数的实参
  3. 箭头函数没有arguments,所以更推荐使用下面的👇剩余函数
剩余参数(真数组
<script>
  function config(baseURL, ...other) {
    console.log(baseURL); // 得到 'http://baidu.com'
    console.log(other); // other  得到 ['get', 'json']
  }
  // 调用函数
  config("http://baidu.com", "get", "json");
</script>

总结:

  1. ... 是语法符号,置于最末函数形参之前,用于获取多余的实参
  2. 借助 ... 获取的剩余实参,是个真数组
补充:展开运算符 …arr

上面的剩余参数和展开运算符是2个东西,不是同一个概念

使用场景1:合并对象
const obj1 = {
  name: "slx",
  age: 11,
};

const obj2 = {
  clsss: "jk",
  sex: "f",
  name: "dddd",
};

const obj3 = { ...obj1, ...obj2 };
console.log("obj3", obj3);

在这里插入图片描述

使用场景2:合并数组
const arr1 = [1, 2, 3, 4];
const arr2 = [5, 6, 7];
console.log([...arr1, ...arr2]);

在这里插入图片描述

使用场景3: 数组求最大值
const arr = [1, 2, 3, 4];
console.log(Math.max(...arr)); // 也就是...arr ==== 1,2,3,4


// 错误写法:
console.log(Math.max(arr)); // 不能直接对数组求最大值

在这里插入图片描述

补充:匿名函数

在JavaScript中,匿名函数是一个没有名字的函数表达式,它通常用于立即调用或作为参数传递给其他函数。匿名函数是非常灵活的,可以在多种情况下使用。
匿名函数主要有两种形式:函数表达式和函数声明。

  1. 函数表达式(Function Expression)
    函数表达式是一种匿名函数的写法,它使用大括号 {} 来定义函数体,并且通过变量名来引用函数。例如:
const myFunction = function() {
  console.log('这是一个匿名函数!');
};
myFunction(); // 调用匿名函数

在这个例子中,myFunction 是一个变量,它引用了匿名函数。你可以给这个匿名函数赋值给任何变量,包括匿名函数的返回值。
2. 箭头函数(Arrow Function)
箭头函数是ES6引入的一种新的函数语法,它提供了一种更简洁的写法。箭头函数通常用于匿名函数,并且有一些不同于传统函数的表达式。例如:

const myArrowFunction = () => {
  console.log('这是一个箭头函数!');
};
myArrowFunction(); // 调用箭头函数
  1. 作为回调函数传递给其他函数,例如事件处理函数或异步操作的回调:
document.querySelector('#myButton').addEventListener('click', function() {
  console.log('按钮被点击!');
});
  1. 立即调用一个函数,通常用于封装一些代码并在创建函数时就执行它:
(function() {
  console.log('这是一个立即调用的匿名函数!');
})();

匿名函数是JavaScript中非常强大的特性之一,它们在异步编程和函数式编程中扮演着重要角色。

2.3 箭头函数

箭头函数是一种声明函数的简洁语法,它与普通函数并无本质的区别,差异性更多体现在语法格式上。
使用场景:箭头函数更适用于那些本来需要匿名函数的地方

<body>
  <script>
    // const fn = function () {
    //   console.log(123)
    // }
    // 1. 箭头函数 基本语法
    // const fn = () => {
    //   console.log(123)
    // }
    // fn()
    // const fn = (x) => {
    //   console.log(x)
    // }
    // fn(1)
    // 2. 只有一个形参的时候,可以省略小括号
    // const fn = x => {
    //   console.log(x)
    // }
    // fn(1)
    // // 3. 只有一行代码的时候,我们可以省略大括号
    // const fn = x => console.log(x)
    // fn(1)
    // 4. 只有一行代码的时候,可以省略return
    // const fn = x => x + x
    // console.log(fn(1))
    // 5. 箭头函数可以直接返回一个对象
    // const fn = (uname) => ({ uname: uname })
    // console.log(fn('刘德华'))
  </script>
</body>

总结:

  1. 箭头函数属于表达式函数,因此不存在函数提升
  2. 箭头函数只有一个参数时可以省略圆括号 ()
  3. 箭头函数函数体只有一行代码时可以省略花括号 {},并自动做为返回值被返回
箭头函数参数

箭头函数中没有 arguments,只能使用 ... 动态获取实参

<body>
  <script>
    // 1. 利用箭头函数来求和
    const getSum = (...arr) => {
      let sum = 0;
      for (let i = 0; i < arr.length; i++) {
        sum += arr[i];
      }
      return sum;
    };
    const result = getSum(2, 3, 4);
    console.log(result); // 9
  </script>
</body>
箭头函数 this

箭头函数不会创建自己的 this,它只会从自己的作用域链的上一层沿用 this。

<script>
  // 以前this的指向:  谁调用的这个函数,this 就指向谁
  // console.log(this)  // window
  // // 普通函数
  // function fn() {
  //   console.log(this)  // window
  // }
  // window.fn()
  // // 对象方法里面的this
  // const obj = {
  //   name: 'andy',
  //   sayHi: function () {
  //     console.log(this)  // obj
  //   }
  // }
  // obj.sayHi()

  // 2. 箭头函数的this  是上一层作用域的this 指向
  // const fn = () => {
  //   console.log(this)  // window
  // }
  // fn()
  // 对象方法箭头函数 this
  // const obj = {
  //   uname: 'pink老师',
  //   sayHi: () => {
  //     console.log(this)  // this 指向谁? window
  //   }
  // }
  // obj.sayHi()

  const obj = {
    uname: "pink老师",
    sayHi: function () {
      console.log(this); // obj
      let i = 10;
      const count = () => {
        console.log(this); // obj
      };
      count();
    },
  };
  obj.sayHi();
</script>

在这里插入图片描述在这里插入图片描述

三、解构赋值

知道解构的语法及分类,使用解构简洁语法快速为变量赋值。

解构赋值是一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值,分为数组解构、对象解构两大类型。

3.1 数组解构

数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法,如下代码所示:

<script>
  // 普通的数组
  let arr = [1, 2, 3];
  // 批量声明变量 a b c
  // 同时将数组单元值 1 2 3 依次赋值给变量 a b c
  let [a, b, c] = arr;
  console.log(a); // 1
  console.log(b); // 2
  console.log(c); // 3
</script>

用剩余参数解决

总结:

  1. 赋值运算符 = 左侧的 [] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量

  2. 变量的顺序对应数组单元值的位置依次进行赋值操作

  3. 变量的数量大于单元值数量时,多余的变量将被赋值为 undefined

  4. 变量的数量小于单元值数量时,可以通过 ... 获取剩余单元值,但只能置于最末位
    在这里插入图片描述

  5. 允许初始化变量的默认值,且只有单元值为 undefined 时默认值才会生效
    在这里插入图片描述6. 按需导入,忽略某些返回值
    在这里插入图片描述7. 多维数组的结构
    在这里插入图片描述

注:支持多维解构赋值,比较复杂后续有应用需求时再进一步分析

补充:js前面必须加分号的两种情况

  1. 立即执行函数
    在这里插入图片描述

  2. 数组解构
    在这里插入图片描述

  3. [1,2,3].map
    在这里插入图片描述

3.2 对象解构

对象解构是将对象属性和方法快速批量赋值给一系列变量的简洁语法,如下代码所示:

  1. 基本用法
<script>
  // 普通对象
  const user = {
    name: "小明",
    age: 18,
  };
  // 批量声明变量 name age
  // 同时将数组单元值 小明  18 依次赋值给变量 name  age
  const { name, age } = user;

  console.log(name); // 小明
  console.log(age); // 18
</script>

在这里插入图片描述
2. 对象解构的变量名可以重新改名
旧变量名:新变量名

const obj1 = {
  name111: "slx",
  age1111: 12,
};

const { name111: name, age111: age } = obj1;
console.log("name", name);
console.log("age", age);

  1. 数组对象解构
    在这里插入图片描述4. 多级解构
    在这里插入图片描述

总结:

  1. 赋值运算符 = 左侧的 {} 用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量
  2. 对象属性的值将被赋值给与属性名相同的变量
  3. 对象中找不到与变量名一致的属性时变量值为 undefined
  4. 允许初始化变量的默认值,属性不存在或单元值为 undefined 时默认值才会生效

注:支持多维解构赋值

<body>
  <script>
    // 1. 这是后台传递过来的数据
    const msg = {
      code: 200,
      msg: "获取新闻列表成功",
      data: [
        {
          id: 1,
          title: "5G商用自己,三大运用商收入下降",
          count: 58,
        },
        {
          id: 2,
          title: "国际媒体头条速览",
          count: 56,
        },
        {
          id: 3,
          title: "乌克兰和俄罗斯持续冲突",
          count: 1669,
        },
      ],
    };

    // 需求1: 请将以上msg对象  采用对象解构的方式 只选出  data 方面后面使用渲染页面
    // const { data } = msg
    // console.log(data)
    // 需求2: 上面msg是后台传递过来的数据,我们需要把data选出当做参数传递给 函数
    // const { data } = msg
    // msg 虽然很多属性,但是我们利用解构只要 data值
    function render({ data }) {
      // const { data } = arr
      // 我们只要 data 数据
      // 内部处理
      console.log(data);
    }
    render(msg);

    // 需求3, 为了防止msg里面的data名字混淆,要求渲染函数里面的数据名改为 myData
    function render({ data: myData }) {
      // 要求将 获取过来的 data数据 更名为 myData
      // 内部处理
      console.log(myData);
    }
    render(msg);
  </script>
</body>

综合案例

forEach 遍历数组

forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数

注意:

1.forEach 主要是遍历数组

2.参数当前数组元素是必须要写的, 索引号可选。

<body>
  <script>
    // forEach 就是遍历  加强版的for循环  适合于遍历数组对象
    const arr = ["red", "green", "pink"];
    const result = arr.forEach(function (item, index) {
      console.log(item); // 数组元素 red  green pink
      console.log(index); // 索引号
    });
    // console.log(result)
  </script>
</body>

filter 筛选数组

filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素

主要使用场景: 筛选数组符合条件的元素,并返回筛选之后元素的新数组

<body>
  <script>
    const arr = [10, 20, 30];
    // const newArr = arr.filter(function (item, index) {
    //   // console.log(item)
    //   // console.log(index)
    //   return item >= 20
    // })
    // 返回的符合条件的新数组

    const newArr = arr.filter((item) => item >= 20);
    console.log(newArr);
  </script>
</body>

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

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

相关文章

三维坐标系之间的转换

一、概括 这个完全是抄别人的&#xff0c;给我自己看的主要是想当我要看的时候我直接能找到&#xff0c;而不用再去网上搜索&#xff0c;后期会吧代码更新上去。 彻底搞懂“旋转矩阵/欧拉角/四元数”&#xff0c;让你体会三维旋转之美_欧拉角判断动作-CSDN博客 在不同的坐标…

Python语法糖

N u m P y NumPy NumPy的 n d i t e r nditer nditer nditer 是 NumPy 提供的一种多维迭代器&#xff0c;用于对多维数组进行迭代操作。它可以替代传统的嵌套循环&#xff0c;在处理多维数组时更加方便和高效。 迭代器可以按照不同的顺序遍历数组的元素&#xff0c;也可以控制…

✅技术社区—通过Canal框架实现MySQL与ElasticSearch的数据同步

Canal 是一个由阿里巴巴开源的&#xff0c;基于 Java 的数据库变更日志解析的中间件&#xff0c;其原理是基于Binlog订阅的方式实现&#xff0c;模拟一个MySQL Slave 订阅Binlog日志&#xff0c;从而实现CDC&#xff0c;主要用于实现 MySQL 数据库的增量数据同步。它主要的使用…

Linux:PostGreSQL|PostGIS部署

由于更换了云服务器&#xff0c;需要重新部署PostGreSQL|PostGIS&#xff0c;所以记录一下Linux CentOS 7 x86-64环境下&#xff0c;PostGreSQL|PostGIS的部署过程。 参考文档&#xff1a;PostgreSQL: Linux downloads (Red Hat family)。 yum安装PostGreSQL 通过yum安装PostG…

PC-DARTS: PARTIAL CHANNEL CONNECTIONS FOR MEMORY-EFFICIENT ARCHITECTURE SEARCH

PC-DARTS&#xff1a;用于内存高效架构搜索的部分通道连接 论文链接&#xff1a;https://arxiv.org/abs/1907.05737 项目链接&#xff1a;https://github.com/yuhuixu1993/PC-DARTS ABSTRACT 可微分体系结构搜索(DARTS)在寻找有效的网络体系结构方面提供了一种快速的解决方案…

网络编程-套接字相关基础知识

1.1. Socket简介 套接字&#xff08;socket&#xff09;是一种通信机制&#xff0c;凭借这种机制&#xff0c; 客户端<->服务器 模型的通信方式既可以在本地设备上进行&#xff0c;也可以跨网络进行。 Socket英文原意是“孔”或者“插座”的意思&#xff0c;在网络编程…

ROS——ROS安装遇到的问题

1、添加ROS软件源 打开终端&#xff0c;将下面这条命令复制到ubuntu的终端执行 sudo sh -c . /etc/lsb-release && echo "deb http://mirrors.ustc.edu.cn/ros/ubuntu/ $DISTRIB_CODENAME main" > /etc/apt/sources.list.d/ros-latest.list2、添加密钥 …

Java面试题总结200道(三)

51、什么是 Spring IOC 容器 Spring 框架的核心是 Spring 容器。容器创建对象&#xff0c;将它们装配在一起&#xff0c;配置它 们并管理它们的完整生命周期。Spring 容器使用依赖注入来管理组成应用程序的 组件。容器通过读取提供的配置元数据来接收对象进行实例化&#xff0…

Windows Docker 部署 Solr 搜索引擎

一、简介 Solr 是 Apache 下的一个顶级开源项目&#xff0c;采用 Java 开发&#xff0c;它是基于 Lucene 的全文搜索服务器。Solr 可以独立运行在 Jetty、Tomcat 等这些 Servlet 容器中。Solr 提供了比 Lucene 更为丰富的查询语言&#xff0c;同时实现了可配置、可扩展&#x…

OpenHarmony4.0对RK3566的烧写过程

前面已经编译的过程搞了比较长的时间,因为遇到了不少问题,老是编译出错,后来经过努力还是编译成功了。 我这里主要针对RK3566的Purple Pi OH开发板,如下图: 因为开源鸿蒙里没有针对这个板的特殊配置,需要下载下面这个文件: purple-pi-oh-patch.zip 这个文件里包含了可…

(二)OpenOFDM频偏校正

频偏校正 This paper [1]解释了频率偏移发生的原因以及如何纠正它。简而言之&#xff0c;有两种类型的频率偏移。第一个称为载波频率偏移 (CFO)&#xff0c;是由发射器和接收器的本地振荡器 (LO) 之间的差异引起的。这种偏移的症状是输入 I/Q 样本&#xff08;时域&#xff09…

国际前十正规外汇实时行情走势app软件最新排名(综合版)

外汇交易&#xff0c;作为当今世界金融市场上一个重要的板块&#xff0c;备受关注和热议。随着金融市场的日益发展&#xff0c;外汇交易也发展成为一个新兴的投资交易渠道。为了更好地满足投资者对外汇市场的需求&#xff0c;外汇实时行情走势app软件应运而生&#xff0c;它为投…

R语言聚类分析-K均值聚类与系统聚类法

一、数据集为firm.csv&#xff0c;给出了22家美国公用事业公司的相关数据集&#xff0c;各数据集变量的名称和含义如下&#xff1a;X1为固定费用周转比&#xff08;收入/债务&#xff09;&#xff0c;X2为资本回报率&#xff0c;X3为每千瓦容量成本&#xff0c;X4为年载荷因子&…

YOLOv9详解

1.概述 在逐层进行特征提取和空间转换的过程中&#xff0c;会损失大量信息&#xff0c;例如图中的马在建模过程中逐渐变得模糊&#xff0c;从而影响到最终的性能。YOLOv9尝试使用可编程梯度信息PGI解决这一问题。 具体来说&#xff0c; PGI包含三个部分&#xff0c;&#xff0…

LeetCode每日一题[C++]-310.最小高度树

题目描述 树是一个无向图&#xff0c;其中任何两个顶点只通过一条路径连接。 换句话说&#xff0c;一个任何没有简单环路的连通图都是一棵树。 给你一棵包含 n 个节点的树&#xff0c;标记为 0 到 n - 1 。给定数字 n 和一个有 n - 1 条无向边的 edges 列表&#xff08;每一个…

数据过滤的练习

定义一个集合&#xff0c;并添加一些整数1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6&#xff0c;7&#xff0c;8&#xff0c;9&#xff0c;10&#xff0c;过滤奇数&#xff0c;只留下偶数&#xff0c;并将结果保存起来。 package MyStream;import j…

SAP Activate项目管理方法论路线图

SAP Activate 是 SAP 推出的一种基于敏捷方法论的灵活、快速且引导式的实施方法论&#xff0c;专为加速SAP S/4HANA和其他SAP解决方案的部署而设计。这个方法论结合了最佳实践、引导配置和方法论本身的强大能力&#xff0c;以确保项目的快速实施和成功部署。SAP Activate的核心…

MySQL中出现‘max_allowed_packet‘ variable.如何解决

默认情况下&#xff0c;MySQL的max_allowed_packet参数可能设置得相对较小&#xff0c;这对于大多数常规操作来说足够了。但是&#xff0c;当你尝试执行包含大量数据的操作&#xff08;如大批量插入或大型查询&#xff09;时&#xff0c;可能会超过这个限制&#xff0c;从而导致…

Bit的下载及安装和错误解决方案

文章目录 一、Git初识二、Git安装三、使用四、*可能出现的问题及解决方案1、vscode中没有Git Bash 一、Git初识 1、概念&#xff1a;一个免费开源、分布式的代码版本控制系统&#xff0c;帮助开发团队维护代码 2、作用&#xff1a;记录代码内容&#xff0c;切换代码版本&#x…

(官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell

前言 查了很多资料都不靠谱&#xff0c;在安装过程中遇到很多的坑&#xff0c;mangoDB 服务重视起不来&#xff1b;出现了很多难以解决的报错&#xff0c;现在把安装过程中遇到的问题&#xff0c;和如何闭坑说一下&#xff0c;很多时候都是准备工作不足导致的&#xff1b;很多方…