【ES新特性三】Object 原型、原型链相关方法
一、Object 原型、原型链相关方法
1.1 静态方法(Object 调用):
-
Object.setPrototypeOf(obj,prototype) 方法用于设置某个实例对象的原型(可以是null,也可以是一个对象)
-
Object.getPrototypeOf(obj)
注:ES5之前,实例化对象通过 __proto__ 属性来获取原型对象;ES5中,不推荐以 __ 开头的语句,所以提供了 getPropertyOf() 方法用于获取对象的原型对象
原生JavaScipt案例合集
JavaScript +DOM基础
JavaScript 基础到高级
Canvas游戏开发
1.2 原型方法(实例调用)
此方法为 Object.prototype 原型方法,Object.prototype 作为任意对象在原型链上的顶级原型对象,在 JS 中定义的任意一个对象(自定义对象、数组对象等都可以调用子方法)。
- isPrototypeOf() 方法用于测试一个对象是否存在于另一个对象的原型链上。
- hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。
<body>
<ul><li>111</li><li>222</li><li>333</li><li>444</li>
</ul>
</body>
<script>// 获取类数组对象var lis = document.getElementsByTagName("li");// 定义数组var arr = [10,20,30,40];// 自定义对象var obj = {name:"张三"}// 查看Array.prototype这个原型是哪个实例化对象的原型console.log(Array.prototype.isPrototypeOf(lis));//falseconsole.log(Array.prototype.isPrototypeOf(obj));//falseconsole.log(Array.prototype.isPrototypeOf(arr));//true// 查找过程中,会查找整个原型链console.log(Object.prototype.isPrototypeOf(lis));//trueconsole.log(Object.prototype.isPrototypeOf(obj));//trueconsole.log(Object.prototype.isPrototypeOf(arr));//true// 获取实例化对象 arr 的原型对象// 原始方式console.log(arr.__proto__);//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]// ES5方式console.log(Object.getPrototypeOf(arr));//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]// 对比console.log(arr.__proto__ === Object.getPrototypeOf(arr));//true// 设置实例化对象 arr 的原型对象 可以为null 也可以是一个对象 会修改整个原型链Object.setPrototypeOf(arr,null);console.log(Object.getPrototypeOf(arr));//nullObject.setPrototypeOf(arr,{a:10});console.log(Object.getPrototypeOf(arr));//{a:10}// 构造函数的原型不变 只是实例化对象原型指向改变console.log(Array.prototype);//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
</script>
- __proto__ 属性是一个访问器属性(一个 getter 函数和一个 setter 函数), 暴露了通过它访问的对象的内部
[[Prototype]](一个对象或null)。proto 属性也可以在对象文字定义中使用对象 [[Prototype]] 来创建,作为Object.create()的一个替代。
1.3 操作属性的方法(Object 调用)
**Object.getOwnPropertyNames()**方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性)组成的数组。
Object.getOwnPropertySymbols() 方法返回一个给定对象自身的所有 Symbol 属性的数组。
Object.hasOwn() 如果指定的对象自身有指定的属性,则返回 true。如果属性是继承的或者不存在,该方法返回 false。
备注:
Object.hasOwn()旨在取代Object.hasOwnProperty()。
// 类数组对象
var obj = { 0: "a", 1: "b", 2: "c"};
console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]// 数组对象
var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]// Symbols
var obj = {};
var a = Symbol("a");
var b = Symbol.for("b");
obj[a] = "localSymbol";
obj[b] = "globalSymbol";
var objectSymbols = Object.getOwnPropertySymbols(obj);// hasOwn()
const example = {};
Object.hasOwn(example, 'prop'); // false - 'prop' has not been definedexample.prop = 'exists';
Object.hasOwn(example, 'prop'); // true - 'prop' has been defined
二、Object 相关方法
2.1 Object.preventExtensions() 取消对象可拓展性
Object.preventExtensions(obj) 方法用于取消对象的可拓展性
Object.isExtensible(obj) 判断对象是否取消了可拓展性。返回值是一个布尔值,返回true对象可以拓展属性 返回false对象不可拓展属性
注:当一个对象被取消了可拓展性之后,对象不能再拓展属性,但是可以修改和删除属性
var obj = {a:1,b:2
}console.log("取消对象可拓展性前对象:",obj);// 取消对象拓展
Object.preventExtensions(obj);// 拓展属性
obj.c = 3;// 删除属性
delete obj.a;// 修改属性值
obj.b = 22;// 判断对象是否可拓展
console.log(Object.isExtensible(obj));//trueconsole.log("取消对象可拓展性后并操作属性后的对象:",obj);
2.2 Object.seal() 封闭对象
Object.seal(obj) 封闭对象的属性
Object.isSealed(obj) 判断对象属性是否被封闭。返回值布尔值,返回true 对象被封闭 返回false对象没有被封闭
注:当一个对象被封闭后,不能拓展和删除属性,但是可以修改属性。
var obj = {a:1,b:2
}console.log("封闭前对象:",obj);// 封闭对象
Object.seal(obj);// 拓展属性
obj.c = 3;// 删除属性
delete obj.a;// 修改属性值
obj.b = 22;// 判断对象是否被封闭
console.log(Object.isSealed(obj));//trueconsole.log("封闭后并操作属性后的对象:",obj);
2.3 Object.freeze() 冻结对象
Object.freeze(obj) 方法用于冻结对象的属性
Object.isFrozen(obj) 方法用于判断对象属性是否被冻结。返回值 一个布尔值 返回true对象被冻结,返回false对象没有被冻结
注:当一个对象被冻结后,不能拓展、修改和删除对象的属性
var obj = {a:1,b:2
}console.log("冻结前对象:",obj);// 冻结对象
Object.freeze(obj);// 拓展属性
obj.c = 3;// 删除属性
delete obj.a;// 修改属性值
obj.b = 22;// 判断对象是否被冻结
console.log(Object.isFrozen(obj));//trueconsole.log("冻结后并操作属性后的对象:",obj);
2.4 Object.create() 创建对象
Object.create(proto,[ propertiesObject ]) 方法使用现有对象作为新创建的对象的原型来创建新对象。
-
参数
- proto 该对象应该是新创建对象的原型。可以是null
- propertiesObject 可选的。指定要添加到新创建的对象的属性描述符,以及相应的属性名称。这些属性对应于的第二个参数Object.defineProperties()对象属性的特性。
-
返回值 具有指定原型对象和属性的新对象。
// 学过的创建对象的方式
// var obj = {};
// var obj1 = new Object();
// var obj2 = Object();// ES5新增创建一个空对象 第一个参数新创建对象的原型设置为null
// var obj3 = Object.create(null);
// console.log(obj3)//使用Object.create() 来创建一个对象,第一个参数原型对象为一个常量对象
// var obj = Object.create({
// sayHi:function(){
// console.log("Hello");
// }
// })// 第一个参数为空,第二个参数为 要创建对象的空对象的属性特性描述(类似于Object.defineProperty()设置的对象特性)
// var obj = Object.create(null,{
// name:{
// // 配置值
// value:"张三",
// // 配置是否可写
// writable:false,
// // 配置是否可枚举
// enumerable:false
// },
// age:{
// // 配置值
// value:10,
// // 配置是否可写
// writable:false,
// }
// })
// console.log(obj);
// console.log(obj.name);
// // 通过这种对象特性的方式创建的对象,默认属性不能被删除 修改
// obj.name = "haha";
// delete obj.age;
// console.log(obj);
// console.log(obj.name);// 创建一个对象,并能继承另外一个对象的方法;将一个对象作为另外一个对象的原型
// 创建需要的原型对象
var prototype = {sayHi:function(){console.log("Hello");}
}// 创建需要的特性属性对象
var options = {name:{// 配置值value:"张三",// 配置是否可写writable:false,// 配置是否可枚举enumerable:false},age:{// 配置值value:10,// 配置是否可写writable:false,}
}// 两者组合创建对象
var obj = Object.create(prototype,options);console.log(obj)//查看原型
obj.sayHi();
2.5 Object.create()完善继承
// 定义父类
function People(name,sex,age){this.name = name;this.sex = sex;this.age = age;
}// 原型中定义方法
People.prototype.sayHi = function(){return "姓名:" + this.name + ",性别:" + this.sex + ",年龄:" + this.age;
}People.prototype.sayHello = function(){return "Hello";
}// 定义子类
function Student(name,sex,age,score){// applay实现继承(改变调用对象People.apply(this,arguments);// 定义子类拓展的属性this.score = score;
}// var p = new People();
// delete p.name;
// delete p.sex;
// delete p.age;// 子类继承父类中的方法 必须要使用原型继承 将子类的原型指向父类的实例
// Student.prototype = new Student();// 使用Object.create()优化继承
Student.prototype = Object.create(People.prototype);// 原型继承会造成结构的紊乱,将原型对象的构造函数手动改回到Student
Student.prototype.constructor = Student;// 实例化对象
var s = new Student("张三","男",23,100);// 调用父类原型中的方法
console.log(s.sayHi());/*
* 原型继承,子类的原型就是父类的实例,这种方式会在子类的原型中多出几个无用的属性
* 此时,会在子类的原型中多出几个属性:name:undefined,age:undifined,sex:undefined
* 如果不考虑寄生组合继承这种方式进行优化,ES5还提供了Object.create()方法来优化
**/
2.6 封装实现Object.create()方法
// 定义父类
function People(name,sex,age){this.name = name;this.sex = sex;this.age = age;
}// 原型中定义方法
People.prototype.sayHi = function(){return "姓名:" + this.name + ",性别:" + this.sex + ",年龄:" + this.age;
}People.prototype.sayHello = function(){return "Hello";
}// 定义子类
function Student(name,sex,age,score){// applay实现继承(改变调用对象People.apply(this,arguments);// 定义子类拓展的属性this.score = score;
}// 取消Object.create方法
Object.create = null;
// 重新自定义 create 方法,实现相同的功能
Object.create = function(prototype){// 定义一个构造函数var F = function(){}// 将F的原型指向传入的原型F.prototype = prototype;// 返回F的实例return new F();
}// 使用Object.create方法实现继承
Student.prototype = Object.create(People.prototype);// 实例化对象
var s = new Student("张三","男",23,100);
console.log(s.sayHi());
2.7 Object.entries() 等返回可枚举数组方法
Object.entries() 方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。
Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致。
Object.values() 方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用 for...in 循环的顺序相同(区别在于 for-in 循环枚举原型链中的属性)。
const info = {name: "Jack",country: "Russia",age: 35
}// 使用 Object.keys() 将对象所有自身可枚举属性收集到一个新数组中
const keys = Object.keys(info);// 使用 Object.values() 将对象所有自身可枚举值收集到一个新数组中
const values = Object.values(info);// 使用 Object.entries() 将对象所有自身可枚举所有键值对收集到一个新数组中
const keyVals = Object.entries(info)
// 使用 for...of 遍历自身的键值对(key 和 value)
for (const [key, value] of keyVals) {console.log(`${key}: ${value}`);
}
2.8 Object.assign()
Object.assign(target, …sources) 方法将所有可枚举(Object.propertyIsEnumerable() 返回 true)的自有(Object.hasOwnProperty() 返回 true)属性从一个或多个源对象复制到目标对象,返回修改后的对象。如果目标对象与源对象具有相同的 key,则目标对象中的属性将被源对象中的属性覆盖
参数: target 目标对象,接收源对象属性的对象,也是修改后的返回值。
sources 源对象,包含将被合并的属性。
返回值:目标对象
注意点:
- 针对 深拷贝, 需要使用其他办法,因为
Object.assign()只复制属性值。假如源对象是一个对象的引用,它仅仅会复制其引用值(地址)。 - 原型链生的属性以及不可枚举属性不能被复制
'use strict';// Object.assign() 属于浅拷贝
let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);
console.log(JSON.stringify(obj2)); // { "a": 0, "b": { "c": 0}}obj1.a = 1;
console.log(JSON.stringify(obj1)); // { "a": 1, "b": { "c": 0}}
console.log(JSON.stringify(obj2)); // { "a": 0, "b": { "c": 0}}obj2.a = 2;
console.log(JSON.stringify(obj1)); // { "a": 1, "b": { "c": 0}}
console.log(JSON.stringify(obj2)); // { "a": 2, "b": { "c": 0}}obj2.b.c = 3;
console.log(JSON.stringify(obj1)); // { "a": 1, "b": { "c": 3}}
console.log(JSON.stringify(obj2)); // { "a": 2, "b": { "c": 3}}// 深拷贝(深度克隆)
obj1 = { a: 0 , b: { c: 0}};
let obj3 = JSON.parse(JSON.stringify(obj1));
obj1.a = 4;
obj1.b.c = 4;
console.log(JSON.stringify(obj3)); // { "a": 0, "b": { "c": 0}}// 合并对象
const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, target object itself is changed.//合并相同属性的对象
const o1 = { a: 1, b: 1, c: 1 };
const o2 = { b: 2, c: 2 };
const o3 = { c: 3 };const obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
2.9 Object.is() 判断两个值是否为同一个值。
Object.is(value1, value2) 方法判断两个值是否为同一个值,如果满足以下任意条件则两个值相等:
- 都是
undefined - 都是
null - 都是
true或都是false - 都是相同长度、相同字符、按相同顺序排列的字符串
- 都是相同对象(意味着都是同一个对象的值引用)
- 都是数字且
- 都是
+0 - 都是
-0 - 都是
NaN - 都是同一个值,非零且都不是
NaN
- 都是
Object.is() 与 == 不同。== 运算符在判断相等前对两边的变量(如果它们不是同一类型)进行强制转换(这种行为将 "" == false 判断为 true),而 Object.is 不会强制转换两边的值。
Object.is() 与 === 也不相同。差别是它们对待有符号的零和 NaN 不同,例如,=== 运算符(也包括 == 运算符)将数字 -0 和 +0 视为相等,而将 Number.NaN 与 NaN 视为不相等。
// Case 1: Evaluation result is the same as using ===
Object.is(25, 25); // true
Object.is('foo', 'foo'); // true
Object.is('foo', 'bar'); // false
Object.is(null, null); // true
Object.is(undefined, undefined); // true
Object.is(window, window); // true
Object.is([], []); // false
var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo); // true
Object.is(foo, bar); // false// Case 2: Signed zero
Object.is(0, -0); // false
Object.is(+0, -0); // false
Object.is(-0, -0); // true
Object.is(0n, -0n); // true// Case 3: NaN
Object.is(NaN, 0/0); // true
Object.is(NaN, Number.NaN) // true
相关文章:
【ES新特性三】Object 原型、原型链相关方法
一、Object 原型、原型链相关方法 1.1 静态方法(Object 调用): Object.setPrototypeOf(obj,prototype) 方法用于设置某个实例对象的原型(可以是null,也可以是一个对象) Object.getPrototypeOf(obj) …...
学习大数据应该掌握哪些基础语言
大数据技术的体系庞大且复杂,每年都会涌现出大量新的技术,目前大数据行业所涉及到的核心技术主要就是:数据采集、数据存储、数据清洗、数据查询分析和数据可视化。 学习大数据需要掌握什么语言基础? 1、Java基础 大数据框架90%以…...
Kubernetes技术--k8s核心技术 ingress
1.引入 我们之前在部署应用(如nginx)的时候,如果你需要外部进行访问,使用的是service中的nodePort方式进行对外的暴露。然后外部就可以使用ip + 端口号来进行访问部署应用。 其实这一种方式是存在着较为明显的缺陷,每一个端口你只能够使用一次,一个端口对应一个应用,而且访…...
中级深入--day15
案例:使用BeautifuSoup4的爬虫 我们以腾讯社招页面来做演示:搜索 | 腾讯招聘 使用BeautifuSoup4解析器,将招聘网页上的职位名称、职位类别、招聘人数、工作地点、发布时间,以及每个职位详情的点击链接存储出来。 # bs4_tencent.p…...
内存四区(个人学习笔记黑马学习)
1、内存分区模型 C程序在执行时,将内存大方向划分为4个区域: 代码区:存放函数体的二进制代码,由操作系统进行管理的全局区:存放全局变量和静态变量以及常量栈区:编译器自动分配释放,存放函数的参数值,局部变量等 堆区:由程序员分配和释放,若程…...
如何使用RPA + ChatGPT自动化提高自己的工作效率
使用RPA(Robotic Process Automation)和ChatGPT可以结合来自动化提高自己的工作效率。下面是一些步骤: (1)确定自动化任务 首先,需要确定哪些任务或工作流程可以通过自动化来提高效率。这些任务应该是重复…...
uni-app之android项目配置和打包
1,项目根目录,找到mainfest.json,如果appid是空的,需要生成一个appid 2,点击重新获取appid,这个时候需要登录,那就输入账号密码登录下 3,登陆后可以看到获取appid成功 4,…...
go语言配置
1、Go语言的环境变量 与Java等编程语言一样,安装Go语言开发环境需要设置全局的操作系统环境变量(除非是用包管理工具直接安装) 主要的系统级别的环境变量有两个: (1)GOROOT:表示Go语言环境在计算机上的安…...
【深度学习】ChatGPT
本文基于Andrej Karpathy(OpenAI 联合创始人,曾担任特斯拉的人工智能和自动驾驶视觉主管)在Microsoft Build 2023上的演讲整理而成(完整的视频在文末,直接拖到文章底部),主要分为2大部分: 1.如何训练GPT(可…...
爬虫--爬取自己想去的目的的车票信息
前言: 本篇文章主要作为一个爬虫项目的小练习,来给大家进行一下爬虫的大致分析过程以及来帮助大家在以后的爬虫编写中有一个更加清晰的认识。 一:环境配置 Python版本:3.7 IDE:PyCharm 所需库:requests࿰…...
Metinfo6.0.0任意文件读取【漏洞复现】
文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现代码审计漏洞点 1.5、深度利用EXP编写 1.6、漏洞挖掘1.7修复建议 1.1、漏洞描述 漏洞名称:MetInfo任意文件读取 漏洞简介:MetInfo是一套使用PHP和MySQL开发的内容管理系统,其…...
Postgresql JSON对象和数组查询
文章目录 一. Postgresql 9.5以下版本1.1 简单查询(缺陷:数组必须指定下标,不推荐)1.1.1 模糊查询1.1.2 等值匹配1.1.3 时间搜索1.1.4 在列表1.1.5 包含 1.2 多层级JSONArray(推荐)1.2.1 模糊查询1.2.2 模糊查询 NOT1.2.3 等值匹配…...
搭配购买——并查集+01背包
Joe觉得云朵很美,决定去山上的商店买一些云朵。 商店里有 n 朵云,云朵被编号为 1,2,…,n,并且每朵云都有一个价值。但是商店老板跟他说,一些云朵要搭配来买才好,所以买一朵云则与这朵云有搭配的云都要买。但是Joe的钱有…...
JVM调优指令参数
常用命令查找文档站点:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/index.html -XX:PrintFlagsInitial 输出所有参数的名称和默认值,默认不包括Diagnostic和Experimental的参数。可以配合 -XX:UnlockDiagnosticVMOptions和-XX:UnlockEx…...
数据结构入门 — 队列
本文属于数据结构专栏文章,适合数据结构入门者学习,涵盖数据结构基础的知识和内容体系,文章在介绍数据结构时会配合上动图演示,方便初学者在学习数据结构时理解和学习,了解数据结构系列专栏点击下方链接。 博客主页&am…...
MongoDB - 安装
一、Docker安装MongoDB 1. 安装 安装版本: 7.0.0 docker run -itd --name mongodb -v C:\\data\\mongodb\\data:/data/db -p 27017:27017 mongo:7.0.0 --auth-v: 将容器目录/data/db映射到本地C:\\data\\mongodb\\data目录,防止容器删除数据丢失-p: 端口映射--aut…...
Qt应用开发(基础篇)——颜色选择器 QColorDialog
一、前言 QColorDialog类继承于QDialog,是一个设计用来选择颜色的对话框部件。 对话框窗口 QDialog QColorDialog颜色选择器一般用来让用户选择颜色,比如画图工具中选择画笔的颜色、刷子的颜色等。你可以使用静态函数QColorDialog::getColor()直接显示对…...
vscode 清除全部的console.log
在放页面的大文件夹view上面右键点击在文件夹中查找 console.log.*$ 注意:要选择使用正则匹配 替换为 " " (空字符串)...
UG\NX CAM二次开发 插入工序 UF_OPER_create
文章作者:代工 来源网站:NX CAM二次开发专栏 简介: UG\NX CAM二次开发 插入工序 UF_OPER_create 效果: 代码: void MyClass::do_it() {tag_t setup_tag=NULL_TAG;UF_SETUP_ask_setup(&setup_tag);if (setup_tag==NULL_TAG){uc1601("请先初始化加工环境…...
C++指针、指针函数、函数指针、类指针
1、指针变量 #include <iostream>using namespace std;int main () {int var 20; // 实际变量的声明int *ip; // 指针变量的声明ip &var; // 在指针变量中存储 var 的地址cout << "Value of var variable: ";cout << var …...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
FTP(File Transfer Protocol)本身是一个基于 TCP 的协议,理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况,主要原因包括: ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...
结构化文件管理实战:实现目录自动创建与归类
手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题,进而引发后续程序异常。使用工具进行标准化操作,能有效降低出错概率。 需要快速整理大量文件的技术用户而言,这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB,…...
