js(深浅拷贝,节流防抖,this指向,改变this指向的方法)
一、深浅拷贝
1.基本数据类型和引用数据类型的区别:
1. 基本数据类型的变量存储的是值
引用数据类型的变量存储的是地址值
2. 基本数据类型的变量存储的值在栈内存
引用数据类型的变量存储的值在堆内存
3. 基本数据类型的变量存储的是值和值之间相互不影响
引用数据类型的变量存储的值和值,在同用 一个地址的情况,其中一个的值发生变化,另一个也变
2. 深浅拷贝之发生在引用数据类型之间。
深拷贝: 拷贝的是值,源对象和拷贝的对象之间互不影响
浅拷贝: 拷贝的是地址,源对象和拷贝的对象存在公用一个地址的情况,所以相互之间会收到影响
3.浅拷贝
方法一:Object.assign() 方法
用于将一个或多个源对象的可枚举属性复制到目标对象。它只会进行浅拷贝。
const obj1 = {a: 1,b: {c: 2}};const obj2 = Object.assign({}, obj1);obj2.a = 2; // obj1.a 仍然是 1obj2.b.c = 3; // obj1.b.c 也变成 3console.log(obj1); // { a: 1, b: { c: 3 } }console.log(obj2); // { a: 2, b: { c: 3 } }
方法二:展开运算符...
使用展开运算符 ... 可以方便地创建一个对象的浅拷贝。
const obj1 = {a: 1,b: {c: 2}};const obj2 = {...obj1 };obj2.a = 2; // obj1.a 仍然是 1obj2.b.c = 3; // obj1.b.c 也变成 3console.log(obj1); // { a: 1, b: { c: 3 } }console.log(obj2); // { a: 2, b: { c: 3 } }
方法:Object.create()
使用 Object.create() 可以创建一个新对象,新对象的原型指向指定的对象,但这并不是传统意义上的拷贝,而是基于原型链的一个新对象。
const obj1 = {a: 1,b: {c: 2}};const obj2 = Object.create(obj1);obj2.a = 2; // obj1.a 仍然是 1obj2.b.c = 3; // obj1.b.c 也变成 3console.log(obj1); // { a: 1, b: { c: 3 } }console.log(obj2); // { a: 2 }

//===================for=================================var arr = [12, [34, 56, 78], 543, 67, 78]var brr = []for (var i = 0; i < arr.length; i++) {brr.push(arr[i])}// console.log(brr);// 第一层是深拷贝brr[0] = 20;console.log(arr); // [12, [34, 56, 78], 67, 78]console.log(brr); // [20, [34, 56, 78], 67, 78]// 第二是浅拷贝brr[1][0] = 43console.log(arr);//[12, [43, 56, 78],, 67, 78]console.log(brr);// [12, [43, 56, 78],, 67, 78]// ===================arr.slice(0)===========================var arr = [12, [34, 56, 78], 543, 67, 78]var brr = arr.slice(0)// 第一层是深拷贝brr[0] = 20;console.log(arr); // [12, [34, 56, 78],, 67, 78]console.log(brr); // [20, [34, 56, 78],, 67, 78]// 第二是浅拷贝brr[1][0] = 43console.log(arr);//[12, [43, 56, 78],, 67, 78]console.log(brr);// [12, [43, 56, 78],, 67, 78]// ===================arr.concat()===========================var arr = [12, [34, 56, 78], 543, 67, 78]var brr = arr.concat()// 第一层是深拷贝brr[0] = 20;console.log(arr); // [12, [34, 56, 78],, 67, 78]console.log(brr); // [20, [34, 56, 78],, 67, 78]// 第二层是浅拷贝brr[1][0] = 43console.log(arr);//[12, [43, 56, 78],, 67, 78]console.log(brr);// [12, [43, 56, 78],, 67, 78]//--------------------------Array.from()----------------------//Array.from() 方法可以用于创建一个新数组实例,它会浅拷贝类数组对象或可迭代对象。const arr1 = [1, 2, 3, { a: 4 }];const arr2 = Array.from(arr1);arr2[0] = 0; // arr1[0] 仍然是 1arr2[3].a = 5; // arr1[3].a 也变成 5console.log(arr1); // [1, 2, 3, { a: 5 }]console.log(arr2); // [0, 2, 3, { a: 5 }]
直接赋值和浅拷贝的区别:
直接复制的方法,只要是对象都会相互影响,因为是直接拷贝对象栈里面的地址
浅拷贝如果是一层对象,不相互影响,如果出现多层对象拷贝还会相互影响
4.深拷贝
方法一:递归
函数递归:如果一个函数在内部自己调用自己,那么这个函数就是递归函数
由于递归函数很容易发生栈溢出错误,所以需要加推出条件return
let i = 0;function fn() {console.log(`调用${i} 次 `);if (i >= 6) {return}i++fn()}fn()
利用setTimeout实现setInterval效果
function getTime() {document.querySelector('#box').innerHTML = new Date().toLocaleString()setTimeout(getTime, 1000)getTime()}getTime()
const obj1 = {a: 1,b: {c: 2}};const obj2 = {};function deepCopy(newObj, oldObj) {for (let key in oldObj) {if ((oldObj[key]).instanceof Array) {newObj[key] = []deepCopy(newObj[key], oldObj[key])} else if ((oldObj[key]).instanceof Object) {newObj[key] = {}deepCopy(newObj[key], oldObj[key])} else {newObj[key] = oldObj[key]}}}deepCopy(obj2, obj1)obj1.b.c = 6console.log('obj2, obj1', obj2, obj1);
function deepClone(obj) {if (obj === null || typeof obj !== 'object') {return obj; // 基础情况,直接返回值}// 创建一个新对象const newObj = Array.isArray(obj) ? [] : {};// 递归拷贝每个属性for (const key in obj) {if (obj.hasOwnProperty(key)) {newObj[key] = deepClone(obj[key]);}}return newObj;
}
方法二:lodash
Lodash 简介 | Lodash中文文档 | Lodash中文网
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<script>var p = {name: "zs",age: 12,wife: {name: "zs的媳妇"}}var newP = _.cloneDeep(p);newP.wife.name = 'ls的媳妇'console.log(p);console.log(newP);var arr = [12, [34], 5, 67, 78, 8]var newArr = _.cloneDeep(arr);arr[1][0] = 43;console.log(newArr);console.log(arr);
</script>
方法三:JSON.parse(JSON.stringify(obj))
var obj = { name: "zs", age: 18, wife: { name: "zs的wife", city: { name: '上海' } } }var obj1 = JSON.parse(JSON.stringify(obj))
二、节流(技能冷却)
节流:单位时间内,频繁触发事件,只执行一次
使用场景:鼠标移动mousemove,页面尺寸缩放resize,滚动条滚动scroll等
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#box {width: 200px;height: 200px;background-color: #ededed;}</style>
</head>
<body><div id="box"></div>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<script>const box = document.querySelector('#box')let i = 1;function mouseMove() {box.innerHTML = i++}box.addEventListener('mousemove', _.throttle(mouseMove, 3000))
</script>
核心思路:
a.声明一个定时器变量
b.当鼠标每次滑动都先判断是否有定时器,如果有定时器则不开开启新定时器
c.如果没有定时器则开启定时器,记得存到变量里面
定时器里面调用执行的函数
定时器里面要把定时器清空
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#box {width: 200px;height: 200px;background-color: #ededed;}</style>
</head>
<body><div id="box"></div>
</body>
</html>
<script>const box = document.querySelector('#box')let i = 1;function mouseMove() {box.innerHTML = i++}box.addEventListener('mousemove', throttle(mouseMove, 3000))function throttle(fn, t) {let timer = null;return function() {if (!timer) {timer = setTimeout(() => {fn()clearTimeout(timer)timer = null}, t)}}}// let timer = null;// timer = setTimeout(() => {// clearTimeout(timer)// console.log(timer)// }, 1000)//setTimeout中无法清除定时器,因为定时器还在运行
</script>
三、防抖(回城)
防抖:单位时间内,频繁触发事件,只执行最后一次,只要被打断就需要重来
使用场景:搜索框搜索输入,手机号、邮箱验证输入检测
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#box {width: 200px;height: 200px;background-color: #ededed;}</style>
</head>
<body><div id="box"></div>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<script>const box = document.querySelector('#box')let i = 1;function mouseMove() {box.innerHTML = i++}box.addEventListener('mousemove', _.debounce(mouseMove, 3000))
</script>
核心思路:
a.声明一个定时器变量
b.当鼠标每次滑动都先判断是否有定时器,如果有定时器则清除前面的定时器
c.如果没有定时器则开启定时器,记得存到变量里面
d.定时器里面调用执行的函数
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#box {width: 200px;height: 200px;background-color: #ededed;}</style>
</head>
<body><div id="box"></div>
</body>
</html>
<script>const box = document.querySelector('#box')let i = 1;function mouseMove() {box.innerHTML = i++}box.addEventListener('mousemove', debounce(mouseMove, 3000))function debounce(fn, t) {let timer = null;return function() {if (timer) {clearTimeout(timer)}timer = setTimeout(() => {fn()}, t)}}// debounce(mouseMove, 3000)调用函数拿到return结果// debounce(mouseMove, 3000)=function(){}
</script>
| 性能优化 | 说明 | 使用场景 |
| 节流 | 单位时间内,频繁触发事件,只执行一次 | 鼠标移动mousemove,页面尺寸缩放resize,滚动条滚动scroll等 |
| 防抖 | 单位时间内,频繁触发事件,只执行最后一次 | 搜索框搜索输入,手机号、邮箱验证输入检测 |
四、节流案例
页面打开,可以记录上一次视频播放的位置
思路:
在ontimeupdate事件触发的时候,每隔1秒,就记录当前时间到本地存储
下次打开页面,onloadeddata事件触发,就可以从本地存储取出时间,让视频从取出的时间播放,如果没有就默认0s
获取当前时间video.currentTime
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#box {width: 200px;height: 200px;background-color: #ededed;}</style>
</head>
<body><div id="box"><video src="https://v.itheima.net/LapADhV6.mp4" controls autoplay loop muted preload="auto" width="640" height="360"></video></div>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<script>//ontimeupdate事件在视频/音频当前的播放位置发生改变时触发//onloadeddata事件在当前帧的数据加载完成且没有足够的数据播放视频/音频的下一帧时触发const video = document.querySelector('video')video.ontimeupdate = _.throttle(() => {console.log(video.currentTime);localStorage.setItem('currentTime', video.currentTime)}, 1000)video.onloadeddata = () => {video.currentTime = localStorage.getItem('currentTime') || 0}
</script>
五、this指向
普通函数:谁调用this的值指向谁
1.全局函数 === window
2.回调函数 ===window
回调函数: 当一个函数作为另一个函数的参数, 那么这个函数就叫回调函数
console.log(this); //windowfunction fn() {console.log(this); //window}fn()setTimeout(function() {console.log(this); //window}, 1000)
3.在对象方法中 ===对象本身
4.事件中的 ===绑定事件的事件源
document.querySelector('button').addEventListener('click', function() {console.log(this); //<button>按钮</button> ,指向button})const obj = {sayHi: function() {console.log(this);//{sayHi: ƒ},指向obj}}obj.sayHi()
5.构造函数中 === new出来的对象
6.原型对象上对应的方法体内的this ===new出来的对象
let a;let b;function Star(name, age, sex) {a = this;this.name = name;this.age = age;}const ldh = new Star('ldh', 55)console.log(a === ldh);//true//构造函数里面的 this就是实例对象Star.prototype.sing = function() {b = this;console.log('唱歌');};ldh.sing()console.log(b === ldh);//true
7.箭头函数===没有this 指向上级作用域
箭头函数:箭头函数中不存在this,箭头函数会默认绑定外层this的值,this引用的就是最近作用域中的this,向外层作用域中,一层一层查找this,直到有this的定义
const obj = {sayHi: () => {console.log(this); //window}}obj.sayHi()document.querySelector('button').addEventListener('click', () => {console.log(this); //window})
六、修改this的指向
有3个方法可以动态指定普通函数中的this指向
call(),apply(),bind()
1.fun.call(thisArg,arg1,arg2,...)
thisArg是在fun函数运行时指定的this值
返回值就是函数的返回值,因为它就是调用函数

2.fun.apply(thisArg,[arg1,arg2,...])
const obj = {name: 'zs'}function fn(x, y) {console.log(this); //windowconsole.log(x + y);}fn()//调用函数,改变this指向fn.apply(obj, [1, 2])
const arr = [11, 22, 33, 44, 55]const max = Math.max.apply(Math, arr)console.log('max', max);
3.fun.bind(thisArg,arg1,arg2,...)
bind()方法不会调用函数,
能改变函数内部的this指向
返回值是个函数,但是这个里面的this是更改过的this
const obj = {name: 'zs'}function fn(x, y) {console.log(this); //windowconsole.log(x + y);}fn()//不会调用函数,能改变this指向//返回值是个函数,但是这个函数里面的this是更改过的thisconst fun = fn.bind(obj)fun()

案例:点击按钮禁用,2秒后开启
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button>发送短信</button>
</body>
</html>
<script>const btn = document.querySelector('button')btn.addEventListener('click', function() {this.disabled = truesetTimeout(function() {//在这个普通函数里,我们要this的指向由原来的window改为btn,可以使用箭头函数,也可以使用bindthis.disabled = false}.bind(btn), 2000)})
</script>
4.总结
call,apply,bind
相同点:都可以改变this的指向
区别点:
call和apply会调用函数,并且改变函数内部this的指向。
call和apply传递的参数不同,call传递多个参数,apply以数组的形式传递多个参数
bind不会调用函数,而是返回了一个this指向改变后的函数,需要调用这个函数。
相关文章:
js(深浅拷贝,节流防抖,this指向,改变this指向的方法)
一、深浅拷贝 1.基本数据类型和引用数据类型的区别: 1. 基本数据类型的变量存储的是值 引用数据类型的变量存储的是地址值 2. 基本数据类型的变量存储的值在栈内存 引用数据类型的变量存储的值在堆内存 3. 基本数据类型的变量存储的是值和值之间相互不影响 引用数据…...
香橙派5(RK3588)使用npu加速yolov5推理的部署过程
香橙派5使用npu加速yolov5推理的部署过程 硬件环境 部署过程 模型训练(x86主机) 在带nvidia显卡(最好)的主机上进行yolo的配置与训练, 获取最终的best.pt模型文件, 详见另一篇文档 模型转换(x86主机) 下载airockchip提供的yolov5(从pt到onnx) 一定要下这个版本的yolov5, …...
基于MWORKS的蓝桥杯「智能装备数字化建模大赛」正式发布,首期培训本周六开启
为强化装备数字化人才培养,推动装备数字化技术快速发展,第十六届蓝桥杯全国软件和信息技术专业人才大赛设置专项赛暨智能装备数字化建模大赛,使用MWORKS作为参赛软件。关于参赛软件授权、技术支持与培训、教材与案例开发支持、成果转化培训及…...
021、深入解析前端请求拦截器
目录 深入解析前端请求拦截器: 1. 引言 2. 核心实现与基础概念 2.1 基础拦截器实现 2.2 响应拦截器配置 3. 实际应用场景 3.1 完整的用户认证系统 3.2 文件上传系统 3.3 API请求缓存系统 3.4 请求重试机制 3.5 国际化处理 4. 性能优化实践 4.1 请求合并…...
windows中的tracert命令
在 Windows 操作系统中,tracert(全称 Trace Route)是一个用于确定 IP 数据包到达目标主机所经过的路径的命令行工具。它通过发送具有不同生存时间(TTL)的 ICMP(Internet Control Message Protocolÿ…...
【玩儿】Java 数字炸弹小游戏(控制台版)+ IO 数据存储
Java 数字炸弹小游戏(控制台版) IO 数据存储 数字炸弹小游戏概述功能实现实体类User.java 玩家信息实体类GameRecode.java 游戏记录实体类 自定义异常AccountLockedException.java 账号锁定异常PasswordErrorException.java 密码错误异常UnknowAccountEx…...
今日头条躺赚流量:自动化新闻爬取和改写脚本
构建一个自动化的新闻爬取和改写系统,实现热点新闻的自动整理和发布,需要分为以下几个模块:新闻爬取、信息解析与抽取、内容改写、自动发布。以下是每个模块的详细实现步骤和代码示例: 1. 新闻爬取模块 目标:从新闻网…...
日常实习与暑期实习详解
日常实习与暑期实习详解 问了下正在实习的同学,发现天要塌了–才知道日常实习是没有笔试的 1. 实习的定义 1.1 日常实习 日常实习是企业长期招聘的实习岗位,通常没有时间限制。企业会在需要时进行招聘,招聘对象包括在校大学生和大一、大二的…...
Git的原理和使用(六)
本文主要讲解企业级开发模型 1. 引入 交付软件的流程:开发->测试->发布上线 上面三个过程可以详细划分为一下过程:规划、编码、构建、测试、发 布、部署和维护 最初,程序⽐较简单,⼯作量不⼤,程序员⼀个⼈可以完…...
Elasticsearch 中的高效按位匹配
作者:来自 Elastic Alexander Marquardt 探索在 Elasticsearch 中编码和匹配二进制数据的六种方法,包括术语编码(我喜欢的方法)、布尔编码、稀疏位位置编码、具有精确匹配的整数编码、具有脚本按位匹配的整数编码以及使用 ESQL 进…...
LSTM,全称长短期记忆网络(Long Short-Term Memory),是一种特殊的循环神经网络(RNN)结构
关于lstm超参数设置,每个参数都有合适的范围,超过这个范围则lstm训练不再有效,loss不变,acc也不变 LSTM,全称长短期记忆网络(Long Short-Term Memory),是一种特殊的循环神经网络&am…...
导出问题处理
问题描述 测试出来一个问题,使用地市的角色,导出数据然后超过了20w的数据,提示报错,我还以为是偶然的问题,然后是发现是普遍的问题,本地环境复现了,然后是,这个功能是三套角色&…...
通过cv库智能切片 把不同的分镜切出来 自媒体抖音快手混剪
用 手机自动化脚本,从自媒体上获取视频,一个商品对应几百个视频,我们把这几百个视频下载下来,进行分镜 视频切片,从自媒体上下载视频,通过cv库用直方图识别每个镜头进行切片。 下载多个图片进行视频的伪原…...
【机器学习】——numpy教程
文章目录 1.numpy简介2.初始化numpy3.ndarry的使用3.1numpy的属性3.2numpy的形状3.3ndarray的类型 4numpy生成数组的方法4.1生成0和1数组4.2从现有的数组生成4.3生成固定范围的数组4.4生成随机数组 5.数组的索引、切片6.数组的形状修改7.数组的类型修改8.数组的去重9.ndarray的…...
多线程——线程的状态
线程状态的意义 线程状态的意义在于描述线程在执行过程中的不同阶段和条件,帮助开发者更好地管理和调度线程资源。 线程的多种状态 线程的状态是一个枚举类型(Thread.State),可以通过线程名.getState()…...
开源数据库 - mysql - 组织结构(与oracle的区别)
组织形式区别 mysql(Schema -> Table -> Column -> Row) Schema(方案): Scheme是关于数据库和表的布局及特性的信息。它可以用来描述数据库中特定的表以及整个数据库和其中表的信息,如表的一些特…...
vue3+vite 部署npm 包
公司需要所以研究了一下怎么部署安装,比较简单 先下载个vue项目 不用安准路由,pinna 啥的,只需要一个最简单的模版 删掉App.vue 中的其它组件 npm create vuelatest 开始写自定义组件 新建一个el-text 组件, name是重点,vue3中…...
华为鸿蒙HarmonyOS应用开发者高级认证视频及题库答案
华为鸿蒙开发者高级认证的学习资料 1、课程内容涵盖HarmonyOS系统介绍、DevEco Studio工具使用、UI设计与开发、Ability设计与开发、分布式特性、原子化服务卡片以及应用发布等。每个实验都与课程相匹配,帮助加深理解并掌握技能 2、学习视频资料 华为HarmonyOS开发…...
【计网】从零开始认识IP协议 --- 认识网络层,认识IP报头结构
从零开始认识IP协议 1 网络层协议1.1 初步认识IP协议1.2 初步理解IP地址 2 IP协议报头3 初步理解网段划分 1 网络层协议 1.1 初步认识IP协议 我们已经熟悉了传输层中的UDP和TCP协议,接下来我们来接触网络层的协议: 网络层在计算机网络中的意义主要体现…...
大一物联网要不要转专业,转不了该怎么办?
有幸在2014年,踩中了物联网的风口,坏消息,牛马的我,一口汤都没喝上。 依稀记得,当时市场部老大,带我去上海参加电子展会,印象最深的,一些物联网云平台,靠着一份精美PPT&a…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...
