平凡前端之路_21.对象的扩展

【信息科学与工程学】计算机科学与自动化——第二十四篇 编译器04 LLVM编译器01 训推一体方案通过整合训练与推理流程,实现资源复用、效率提升和全链路自动化。以下从。 阅读详情

系列文章

平凡前端之路_0ML与 HTML5
平凡前端之路_05.CSS与CSS3
平凡前端之路_14.ES与ES6
平凡前端之路_15.let 和 const声明
平凡前端之路_16.变量的解构赋值
平凡前端之路_17.展开操作符(Spread)/剩余参数(Rest)
平凡前端之路_18.字符串的扩展
平凡前端之路_19.数组的扩展
平凡前端之路_20.函数的扩展

对象的拓展

对象属性与方法简写

ES6 引入了对象字面量的增强写法,允许在属性名与变量名相同,或定义方法时进行简化。这不仅减少了代码冗余,还提升了可读性。

属性简写

当对象属性的‌键名‌与当前作用域中的‌变量名‌相同时,可以省略键名和冒号,直接写入变量名。

const na = '说你又不听';
const ge = '听又不懂';

// 简写写法
const us = { na, ge };
us //=> { na: '说你又不听', ge: '听又不懂'}
// 等价于传统写法
// const us = { na: na, ge: ge };

方法简写

在对象中定义方法时,可以省略 function 关键字及冒号,直接使用函数名后跟参数列表。

const et = () => '听又不懂';
const obj = {  et };
obj //=> { et: () => '听又不懂'  }
// 等价于传统写法
// const obj = {
//   et: function() { return '听又不懂'; },
// };

动态属性名

可以通过方括号 [] 包裹变量、表达式或 Symbol 来实现动态属性名定义。
方括号[]会先计算内部表达式的值,将结果转换为字符串(Symbol 类型保持不变)作为最终属性名。


动态属性名分类与用法

根据属性名的类型,可以分为‌变量/表达式动态属性名‌和 ‌Symbol 类型属性名‌,两者核心用法和区别如下:

操作类型变量/表达式Symbol (唯一标识符)
‌创建或定义属性‌(对象字面量中)‌使用计算属性名:‌const key = ‘name’;const obj = { [key]: ‘Value’ };‌支持任意表达式:‌{ [‘pre_’ + suffix]: val }‌使用 Symbol:‌const sym = Symbol(‘desc’);const obj = { [sym]: ‘Value’ };‌
关键区别与注意事项- ‌变量/表达式‌:键最终会被转换为字符串。- ‌Symbol‌:Symbol‌类型的键保持为 Symbol类型
操作类型变量/表达式Symbol (唯一标识符)
‌动态添加/修改属性‌‌obj[dynamicKey] = newValue;‌obj[symRef] = newValue;‌注意引用保持:‌必须持有 Symbol 的引用才能访问或修改。
关键区别与注意事项- ‌变量‌/表达式‌:如果键已存在则覆盖,不存在则新增。- ‌Symbol‌:即使描述相同,Symbol(‘a’) !== Symbol(‘a’),因此必须使用同一个 Symbol 变量引用才能修改同一属性。
操作类型变量/表达式Symbol (唯一标识符)
‌获取属性值‌方括号取值 (动态场景):‌obj[keyVar]‌‌必须使用方括号及 Symbol 引用:‌obj[symRef]‌无法通过字符串获取:‌obj[‘Symbol(desc)’] // undefined
关键区别与注意事项- ‌变量‌/表达式‌:只要描述相同即可取值- ‌Symbol‌:即使描述相同,Symbol(‘a’) !== Symbol(‘a’),因此必须使用同一个 Symbol 变量引用才能取值。

点符号 vs 动态方括号 特性对比

访问对象属性有两种语法:点语法 . 和方括号语法 [],两者特性区别如下:

特性点符号 (.)动态方括号 ([])
‌语法格式‌object.propertyobject[expression]
‌属性名类型‌必须是合法的 JavaScript 标识符(静态字符串)。可以是任何字符串、变量、表达式、数字或 Symbol。
‌动态性‌‌静态‌:属性名在编写代码时固定,无法使用变量值作为键。‌动态‌:属性名在运行时计算,支持使用变量、拼接字符串或函数返回值作为键。
‌特殊字符支持‌‌不支持‌:若属性名包含空格、连字符 - 或以数字开头,会报语法错误。‌支持‌:可以访问包含空格、特殊字符或保留字(如 class, for)的属性名。
‌数字键支持‌‌不支持‌:obj.123 会导致语法错误。‌支持‌:obj[123] 或 obj[‘123’] 均可正常访问。
‌Symbol 支持‌‌不支持‌:无法直接通过点符号访问 Symbol 类型的键。‌支持‌:必须使用 obj[symVar] 形式访问 Symbol 键。

对象方法拓展静态方法

ES6 为对象新增了Object.values、Object.entries、Object.assign等实用静态方法,大幅简化了对象操作,让代码更简洁易读;静态方法不依赖实例,直接用于对象操作而非被对象调用。


对象属性获取与转换

‌键值对获取
方法描述
Object.values返回对象自身可枚举属性的值组成的数组
Object.entries返回对象自身可枚举属性的键值对数组
Object.values 方法接受一个参数
Object.values 方法至少接受一个参数
参数传入为 0 个,会抛出错误。
参数传入 ≥2 个:只会生效第一个,其余参数会被忽略
参数为要遍历获取自身可枚举的值的对象
传入非对象参数会强制转换为对象
传入字符串参数会强制转换为字符串对象 Object(字符串),字符串对象有自己的可枚举属性
传入 undefined / null 基本类型参数,不能被强制转换为对象。→ 直接报错 Uncaught TypeError
传入其他非字符串基本类型参数(如数字、布尔值等)会强制转换为相应对象,但基本没有自己的可枚举属性,返回一个空数组
传入 Map 和 Set 作为参数‌,没有可枚举的自有属性,返回一个空数组。
参数传 undefined / null ,不能被强制转换为对象。→ 直接报错 Uncaught TypeError
Object.values 方法不接受回调函数
Object.values 返回一个新数组
Object.values 返回的是数组,不是Iterator对象
Object.values 返回的数组不包含 Symbol 键的属性值
// ==========================================
// Object.values() 方法详解与示例
// ==========================================
// Object.values() 返回对象自身可枚举属性的值组成的数组。
// 语法: Object.values(obj)
// 参数:obj:需要返回自身可枚举属性值的对象。若参数不是对象(如原始类型),会被强制转换为对象。
// 返回值:返回一个由给定对象自身可枚举属性的值组成的数组。

// 案例一:普通对象(字符串键名)
// ------------------------------------------
const obj = { at: '懂又不做', br: '做你又做错' };
const va = Object.values(obj); 
va //=> ['懂又不做', '做你又做错']

// 案例二:普通对象(Symbol 键名)
// ------------------------------------------
// 原对象的键名有一个 Symbol 值,该属性会被忽略。
Object.values({ [Symbol()]: '懂又不做', foo: '做你又做错' });
// ['做你又做错']

// 案例三:字符串(强制转换)
// ------------------------------------------
// 字符串参数会强制转换为字符串对象 'foo' → Object('foo')
// 字符串对象其索引为可枚举属性
const sa = Object.values('懂又不做')
sa //=> ['懂', '又', '不', '做']

// 案例四: undefined / null  (抛出异常)
// ------------------------------------------
// 不能被强制转换为对象。→ 直接报错 Uncaught TypeError
const ua = Object.values(undefined ); // → 直接报错 Uncaught TypeError
const na = Object.values(null); // → 直接报错 Uncaught TypeError

// 案例五: 其他基本类型(Number, Boolean, BigInt, Symbol)
// ------------------------------------------
// 强制转换为相应对象,但基本没有自己的可枚举属性,返回一个空数组
const nu = Object.values(266); // 数字 {266} → Object(266)
const bo = Object.values(true); // 布尔 {true} → Object(true)
const bi = Object.values(266n); // BigInt {266n} → Object(266n)
const sy = Object.values(Symbol('做你又做错')); // Symbol {sym} → Object(sym)
nu //=> []
bo //=> []
bi //=> []
sy //=> []

// 案例六: Map(映射)、Set(集合)
// ------------------------------------------
// Map 和 Set 是内置对象,但基本没有自己的可枚举属性,返回一个空数组
const ma = Object.values(new Map([['懂又不做', '做你又做错'],['错又不认', 42]]));
const se = Object.values(new Set(['懂又不做', '做你又做错']));
ma //=> [];
se //=> [];
// 若要遍历 Map 获取 [值],请直接使用 ma.values(); 
// 若要遍历 Set 获取 [值],请直接使用 sa.values();


values 相似对比方法类型调用方式返回值
Object.valuesObject 静态方法Object.values(obj)真数组
Array.prototype.valuesArray 原型方法arr.values()迭代器(Iterator)
Set.prototype.valuesSet 原型方法set.values()迭代器(Iterator)
Map.prototype.valuesMap 原型方法map.values()迭代器(Iterator)
URLSearchParams.prototype.valuesURLSearchParams 原型方法params.values()迭代器(Iterator)
FormData.prototype.valuesFormData 原型方法formData.values()迭代器(Iterator)

Object.entries 方法接受一个参数
Object.entries 至少接受一个参数
参数传入为 0 个,会抛出错误。
参数传入 ≥2 个:只会生效第一个,其余参数会被忽略
参数为要遍历获取自身可枚举的键值对的对象
传入非对象参数会强制转换为对象
传入字符串参数会强制转换为字符串对象 Object(字符串),字符串对象有自己的可枚举属性
传入 undefined / null 基本类型参数,不能被强制转换为对象。→ 直接报错 Uncaught TypeError
传入其他非字符串基本类型参数(如数字、布尔值等)会强制转换为相应对象,但基本没有自己的可枚举属性,返回一个空数组
传入Map 和 Set 作为参数‌,没有可枚举的自有属性,返回一个空数组。
Object.entries 方法不接受回调函数
Object.entries 返回一个新数组
Object.entries 返回的是数组,一个二维数组,不是Iterator对象。
Object.entries 返回数组的每个子数组包含两个元素:[key, value]。
Object.entries 返回的数组不包含 Symbol 键的键值对。
// ==========================================
// Object.entries() 方法详解与示例
// ==========================================
// Object.entries() 返回对象自身可枚举属性的键值对数组
// 语法: Object.entries(obj)
// 参数:obj:需要返回自身可枚举属性的键值对的对象。若参数不是对象(如原始类型),会被强制转换为对象。
// 返回值:返回一个由给定对象自身可枚举属性的键值对组成的数组。数组的每个元素是一个包含两个元素的数组。

// 案例一: 普通对象(字符串键名)
// ------------------------------------------
const obj = { at: '错又不认', br: '认又不改' };
const entries = Object.entries(obj); 
entries //=> [ ['at', 错又不认'], ['br', '认又不改'] ]

// 案例二: 普通对象(Symbol 键名)
// ------------------------------------------
// 原对象的键名有一个 Symbol 值,该属性会被忽略。
Object.entries({ [Symbol()]: '错又不认', foo: '认又不改' });
// [ [ 'foo', '认又不改' ] ]

// 案例三: 字符串(强制转换)
// ------------------------------------------
// 字符串参数会强制转换为字符串对象 'foo' → / Object('foo'), 
// 字符串对象其索引为可枚举属性
const sa = Object.entries('错又不认');
sa //=> [['0', '错'], ['1', '又'], ['2', '不'], ['3', '认']]

// 案例四: undefined / null  (抛出异常)
// ------------------------------------------
// 不能被强制转换为对象。→ 直接报错 Uncaught TypeError
const ua = Object.entries(undefined ); // → 直接报错 Uncaught TypeError
const na = Object.entries(null); // → 直接报错 Uncaught TypeError

// 案例五: 其他基本类型(Number, Boolean, BigInt, Symbol)
// ------------------------------------------
// 强制转换为相应对象,但基本没有自己的可枚举属性,返回一个空数组
const nu = Object.entries(266); // 数字 {266} → Object(266)
const bo = Object.entries(true); // 布尔 {true} → Object(true)
const bi = Object.entries(266n); // BigInt {266n} → Object(266n)
const sy = Object.entries(Symbol('认又不改')); // Symbol {sym} → Object(sym)
nu //=> []
bo //=> []
bi //=> []
sy //=> []

// 案例六: Map(映射)、Set(集合)
// ------------------------------------------
// Map 和 Set 是内置对象,但基本没有自己的可枚举属性,返回一个空数组
const ma = Object.entries(new Map([['错又不认', '认又不改'],['改又不服', 42]]));
const se = Object.entries(new Set(['错又不认', '认又不改']));
ma //=> [];
se //=> [];
// 若要遍历 Map 获取 [键, 值] ,请直接使用 ma.entries(); 
// 若要遍历 Set 获取 [值, 值],请直接使用 sa.entries(); 
entries 相似对比方法类型调用方式返回值
Object.entriesObject 静态方法Object.entries (obj)真数组
Array.prototype.entriesArray 原型方法arr.entries()迭代器(Iterator)
Set.prototype.entriesSet 原型方法set.entries()迭代器(Iterator)
Map.prototype.entriesMap 原型方法map.entries()迭代器(Iterator)
URLSearchParams.prototype.entriesURLSearchParams 原型方法params.entries()迭代器(Iterator)
FormData.prototype.entriesFormData 原型方法formData.entries()迭代器(Iterator)

键值对转换
方法描述
Object.fromEntries返回一个对象,将键值对列表(如 Map 或数组)转换为对象,是 Object.entries() 的逆操作。
Object.fromEntries 方法接受一个参数
Object.fromEntries 至少接受一个参数
参数传入为 0 个,会抛出错误。
参数传入 ≥2 个:只会生效第一个,其余参数会被忽略
参数为可迭代对象,且可迭代对象中的每个元素应包含两个值,分别作为结果对象的键和值。
能直接正确处理 默认迭代器为 entries 的可迭代对象(如Map、 URLSearchParams‌、FormData‌) 作为参数‌。
Object.fromEntries方法不接受回调函数
Object.fromEntries方法返回一个‌新对象
Object.fromEntries 返回的对象中,重复键出现时,后出现的键值会覆盖先前的值。
即使描述相同,Symbol(‘a’) !== Symbol(‘a’),因此Object.fromEntries 返回的对象中,必须是同一个 Symbol 变量引用,后出现的键值会覆盖先前的值。。
Object.fromEntries 返回的对象 的键名只能是‌字符串‌或 ‌Symbol‌。
Object.fromEntries 返回的对象 的键名返回非字符串/非 Symbol 类型(如数字、布尔值、对象)时,会被强制转换为字符串。
Object.fromEntries 创建的 Symbol 键属性无法通过 Object.entries 完整恢复。
Object.fromEntries 处理的 Map、URLSearchParams 、FormData等无法通过 Object.entries 完整恢复。
// ==========================================
// Object.fromEntries() 方法详解与示例
// ==========================================
// Object.fromEntries() 方法把键值对列表转换为一个对象。
// 是 Object.entries() 的逆操作。
// 语法: Object.fromEntries(iterable)
// 参数 iterable: 类似 Array、Map 或者其它实现了可迭代协议的可迭代对象。

// 案例一: Array (数组)
// ------------------------------------------
// 将二维数组转换为对象。
// 数组中的每个子数组必须包含两个元素:[key, value]。
// 否则,若数组元素非键值对格式,需先通过 map 等方法将其转换为 [key, value] 形式的二维数组,
// 再进行Object.fromEntries转换,否则会报错或结果不符合预期
let ar1 = Object.fromEntries([ ['认又不改', '改又不服'], ['不服你不说', 42]])
// 解析过程:
// Array 默认的迭代器为 values()
// ['认又不改', '改又不服'] -> 键: '认又不改', 值: '改又不服'
// ['不服你不说', 42]    -> 键: '不服你不说', 值: 42
ar1 //=> { '认又不改': '改又不服', '不服你不说': 42 }

// 显式调用 .entries() 
let a2 = Object.fromEntries(['认又不改', '改又不服'].entries())
// 解析过程:
// ['0', '认又不改']  -> 键: '0', 值: '认又不改'
// ['1', '改又不服']  -> 键: '1', 值: '改又不服'
ar2 //=> { '0': '认又不改', '1': '改又不服'}

// 缺少值的异常情况
let ar3 = Object.fromEntries([ ['认又不改'], ['改又不服']])
// 解析过程:
// ['认又不改'] -> 键: '认又不改', 值: undefined 
// ['改又不服'] -> 键: '改又不服', 值: undefined
ar3 //=> { '认又不改': undefined, '改又不服': undefined }

// 存在多余元素的处理
let ar4 = Object.fromEntries([ ['认又不改', '改又不服', 'extra'], ['不服你不说', 42]])
// 只使用前两个元素,多余元素会被忽略
// 解析过程:
// ['认又不改', '改又不服'] -> 键: '认又不改', 值: '改又不服'
// ['不服你不说', 42]    -> 键: '不服你不说', 值: 42
ar4 //=> { '认又不改': '改又不服', '不服你不说': 42 }


// 案例二: Set (集合)
// ------------------------------------------
// 注意: Set 本身存储的是唯一值。
// 如果 Set 中存储的是数组(即二维结构),则可以直接转换。
let se1 = Object.fromEntries(new Set([['认又不改', '改又不服'], ['不服你不说', 42]]))
// 解析过程:
// Set 的默认迭代器 为 values()
// new Set([['认又不改', '改又不服'], ['不服你不说', 42]]) 创建了一个包含两个数组元素的 Set。
// Object.fromEntries 遍历 Set,取出每个数组作为 [key, value] 对。
se1 //=> { '认又不改': '改又不服', '不服你不说': 42 }

// 如果 Set 中存储的是原始值或非键值对结构,则需要先调用 .entries() 或其他方法将其转化为键值对形式。
// Set.prototype.entries() 返回一个迭代器,其中每个值都是 [value, value] 的形式。
let se2 = Object.fromEntries(new Set(['认又不改', 'bar']).entries())
// 解析过程:
// new Set(['认又不改', '改又不服']) 创建包含 '认又不改' 和 '改又不服' 的 Set。
// .entries() 生成迭代器: ['认又不改', '认又不改'], ['改又不服', '改又不服']。
// Object.fromEntries 将其转换为对象,键和值相同。
se2 //=> { '认又不改': '认又不改', '改又不服': '改又不服'}


// 案例三: Map (映射)
// ------------------------------------------
// Map 对象天然就是键值对的集合,因此非常适合转换为普通对象。
let ma1 = Object.fromEntries(new Map([['认又不改', '认又不改'],['不服你不说', 42]]))
// 解析过程:
// new Map(...) 创建 Map 对象。
// Map 的默认迭代器 为 entries()
// Object.fromEntries 直接遍历 Map 的键值对。
ma1 //=> { '认又不改': '认又不改', '不服你不说': 42 }

// 显式调用 .entries() 效果相同,因为 Map 默认迭代器就是 entries。
let ma2 = Object.fromEntries(new Map([['认又不改', '认又不改'],['不服你不说', 42]]).entries())
// 解析过程:
// .entries() 返回 MapIterator,内容与 Map 本身一致。
ma2 //=> { '认又不改': '认又不改', '不服你不说': 42 }


// 案例四: URLSearchParams (URL 查询参数)
// ------------------------------------------
// URLSearchParams 对象用于处理 URL 的查询字符串。
// 它也是可迭代的,迭代时产生 [key, value] 对。
let us1 = Object.fromEntries(new URLSearchParams('foo=bar&baz=42'))
// 解析过程:
// new URLSearchParams('foo=bar&baz=42') 解析查询字符串。
// 迭代时产生: ['foo', 'bar'], ['baz', '42']。
// 注意: URL 参数值始终是字符串类型,所以 42 变成了 '42'。
us1 //=> { 'foo': 'bar', 'baz': '42' }

// 显式调用 .entries() 效果相同。
let us2 = Object.fromEntries(new URLSearchParams('foo=bar&baz=42').entries())
// 解析过程:
// .entries() 返回迭代器,内容同上。
us2 //=> { 'foo': 'bar', 'baz': "42" }


// 案例五: FormData (表单数据)
// ------------------------------------------
// FormData 对象用于处理表单数据
// 它也是可迭代的,迭代时产生 [key, value] 对。

// 手动创建 FormData 示例
let formData = new FormData()
formData.append('认又不改', '改又不服')
formData.append('不服你不说', 42)

let fd1 = Object.fromEntries(formData )
// 解析过程:
// new FormData() 构造表单数据。
// 迭代时产生: ['认又不改', '改又不服'], ['不服你不说', '42']。
// 注意: FormData所有值都是字符串或 File 对象,所以 42 变成了 '42'。
fd1 //=> { '认又不改': '改又不服', '不服你不说': '42' }

// 显式调用 .entries() 效果相同。
let fd2 = Object.fromEntries(formData.entries())
// 解析过程:
// .entries() 返回迭代器,内容同上。
fd2 //=> { '认又不改: '改又不服', '不服你不说': '42'  }

对象操作与合并

对象合并与复制
方法描述
Object.assign将一个或者多个[源Source‌]中所有可枚举的自有属性复制到[目标Target‌],并返回修改后的[目标Target‌]。
Object.assign 方法接受多个参数
Object.assign 方法至少接受一个参数
参数传入为 0 个,会抛出TypeError 错误。
参数传入为 1 个,参数为[目标Target‌](若为 null 或 undefined 会报错,其他原始值会转为包装对象)。
参数传入 ≥2 个:第一个参数为[目标Target‌],后续参数为[源Source‌];所有[源Source‌]的可枚举属性都会合并到[目标Target‌]中(同名属性后者覆盖前者)
第一个参数为[目标Target‌](若为 null 或 undefined 会报错,其他原始值会转为包装对象)。
其他参数为一个或多个包含要应用的属性的[源Source‌]。参数如果不是对象,会尝试转换为对象( 若为 null 或 undefined,则‌跳过‌该参数,不会报错,也不会合并任何属性;其他原始值会转为包装对象)。
Object.assign 方法不接受回调函数
Object.assign 返回是经过 ToObject 转换后的[目标Target‌]。
[目标Target‌]原本是‌对象‌,则返回‌原对象引用
[目标Target‌]是‌基本类型‌(非 null/undefined),则返回一个‌新生成的包装对象‌(引用不同)
Object.assign 会覆盖同名属性,且仅合并可枚举属性。
Object.assign 返回的[目标Target‌]可包含 Symbol 键的属性, 仅合并可枚举属性。
// ==========================================
// Object.assign() 方法详解与示例
// ==========================================
// Object.assign() 方法将一个或者多个[源Source‌]中所有可枚举的自有属性复制到[目标Target‌],并返回修改后的[目标Target‌]。
// 语法: Object.assign(target, source1, source2)
// 参数 target: [目标Target‌],用于接收[源Source‌]的属性。
// 		source1, source2, ...: [源Source‌],提供需复制的属性(可接受多个)。
// 返回值:返回经过 ToObject 转换、并被修改后的[目标Target‌]。

// 案例一:普通对象
// ------------------------------------------
// 后面的[源Source‌]属性会覆盖前面的同名属性
// 1. 普通对象(字符串键名)
const target = { at: '改又不服', br: '不服你不说t' }, 
	source1 = { br: '不服你不说1', cv: '那叫我怎么办1' }, 
	source2 = { cv: '那叫我怎么办2' };

const result1 = Object.assign(target, source1, source2);
// 解析过程:
//  source1 的 br: '不服你不说1' 覆盖了 target 的 br: '不服你不说t'
//  source1 的 cv: '那叫我怎么办1' 添加给了 target 
//  source2 的 cv: '那叫我怎么办2'  覆盖了 source1 提供给target  的 cv: '那叫我怎么办1'
//  target 本身被修改,result1 === target 为 true
result1 //=>  { at: '改又不服', br: '不服你不说1', cv: '那叫我怎么办2' }

// 2. 普通对象(Symbol 键名)
const symA = Symbol('改又不服');
const symB = Symbol('那叫我怎么办');
const targetSym = { [symA]: '改又不服' };
const sourceSym = { [symA]: '不服你不说', [symB]: '那叫我怎么办' };
const resultSym = Object.assign(targetSym, sourceSym);
resultSym //=> { Symbol(改又不服): '不服你不说', Symbol(那叫我怎么办): '那叫我怎么办' }

// 案例二:字符串(强制转换)
// ------------------------------------------
// 字符串参数会强制转换为字符串对象 '改又不服' → Object('改又不服')
// 字符串对象其索引为可枚举属性,被转换为类数组对象,索引作为键
// 1.[目标Target‌]是字符串
const obj1 =  Object.assign('改又不服');
const obj2 =  Object.assign('改又不服', {cv: '不服你不说'});
obj1 // => { 0:'改', 1:'又', 2:'不', 3:'服'};
obj2 // => { 0:'改', 1:'又', 2:'不', 3:'服', cv: '不服你不说' };
// [目标Target‌]只读属性赋值不可写,赋值失败,复制中断
// [目标Target‌]的某个属性是‌只读的‌(writable: false)或者设置了 setter 且抛出异常
// 并停止执行。‌但是‌,在此之前已经成功复制的属性‌不会回滚‌,会保留在[目标Target‌]中。
const obj2 = Object.assign('改又不服', '不服你不说'); // 报错
const obj3 = Object.assign('改又不服', ['不','服']); // 报错
const obj4 = Object.assign('改又不服', {0: '不', 1: '服'}); /// 报错
// 如果赋值期间出错,例如如果属性不可写,则会抛出 TypeError;如果在抛出异常之前已经添加了一些属性,则这些属性会被保留,而 [目标Target‌]也会被修改。

// 2.[源Source‌]是字符串
const str = '改又不服';
const obj1 = Object.assign({}, str);
const obj2 = Object.assign({},  Object(str));
const obj3 = Object.assign({},  Object(str), '不服你不说');
// 解析: 字符串被视为可迭代对象,字符按索引位置作为属性名复制
obj1 // => { 0:'改', 1:'又', 2:'不', 3:'服'};
obj2 // => { 0:'改', 1:'又', 2:'不', 3:'服'};
obj3 // => { 0:'不', 1:'服', 2:'你', 3:'不', 4:'说'};


// 案例三: undefined / null  
// ------------------------------------------
// 1.[目标Target‌] undefined / null -> 报错
// 不能被强制转换为对象。→ 直接报错 Uncaught TypeError
const obj1 = Object.assign(undefined, { at: '改又不服' }); // → 直接报错 Uncaught TypeError
const obj2 = Object.assign(null, { at: '改又不服' }); // → 直接报错 Uncaught TypeError

// 2.[源Source‌] undefined / null -> 跳过,忽略,不会报错
const resultSafe = Object.assign({ at: '改又不服' }, null, undefined, { br: 2 });
resultSafe //=> { at: '改又不服', br: '不服你不说' }

// 案例四: 其他基本类型(Number, Boolean, BigInt, Symbol)
// ------------------------------------------
// 1.[目标Target‌],其他基本类型(Number, Boolean, BigInt, Symbol)
// 强制转换为相应对象,返回的是相应对象对象

const nu = Object.assign(266); // 数字 {266} → Object(266)
const bo = Object.assign(true); // 布尔 {true} → Object(true)
const bi = Object.assign(266n); // BigInt {266n} → Object(266n)
const sy = Object.assign(Symbol('不服你不说')); // Symbol {sym} → Object(sym)
nu //=>  Number {266}
bo //=>  Boolean {true}
bi //=>  BigInt {266n}
sy //=>  Symbol {不服你不说}

// 2.[源Source‌] 其他基本类型(Number, Boolean, BigInt, Symbol)
// 强制转换为相应对象,但基本没有自己的可枚举属性, 不会对[目标Target‌]产生任何属性拷贝效果
const ou = Object.assign({ at: '改又不服' }, 266, true, 266n, Symbol('不服你不说'));
ou //=>  { at: '改又不服' }

// 案例五:Map(映射)、Set(集合)
// ------------------------------------------
// Map 和 Set 是内置对象,没有自己的可枚举属性,
// 1.[目标Target‌],Map 和 Set 是内置对象
const ma = Object.assign(new Map([['改又不服', '不服你不说'],['那叫我怎么办', 42]]));
const se = Object.assign(new Set(['改又不服', '不服你不说']));
const ma1 = Object.assign(new Map([['改又不服', '不服你不说'],['那叫我怎么办', 42]]), { ma: 266});
const se1 = Object.assign(new Set(['改又不服', '不服你不说']), { ma: 266});
ma //=> {'改又不服' => '不服你不说', '那叫我怎么办' => 42}
se //=> {'改又不服', '不服你不说'}
Object.entries(ma1) //=> [['ma', 266]]  
ma1.entries() //=> {'改又不服' => '不服你不说', '那叫我怎么办' => 42}
Object.entries(se1) //=> [['ma', 266]]  
se1.entries() //=> {'改又不服' => '改又不服', '不服你不说' => '不服你不说'}

// 2.[源Source‌] ,Map 和 Set 是内置对象,但基本没有自己的可枚举属性,不会对[目标Target‌]产生任何属性拷贝效果
const ma = Object.assign({ at: '认又不改' }, new Map([['改又不服', '不服你不说'],['那叫我怎么办', 42]]));
const se = Object.assign({ at: '认又不改' }, new Set(['改又不服', '不服你不说']));
ma //=> { at: '认又不改' }
se //=> { at: '认又不改'}
// 如果想合并 Map,应使用 new Map([...map1, ...map2])
// 如果想合并 Set,应使用 new Set([...set1, ...set2])


数据分组
方法描述
Object.groupBy根据回调函数返回值对可迭代对象的元素分组。
Object.groupBy 接受两个参数
Object.groupBy 至少接受两个参数。
参数传入 < 2 个,会抛出错误。
参数传入 ≥ 3 个, 只会生效前两个,其余参数会被忽略。
第一个参数为一个可迭代对象(通常是数组),包含需要被分组的元素。当不是可迭代对象时,会抛出错误。
第二个参数为对可迭代对象中的每个元素执行的函数。当不是函数时,会抛出错误。
Object.groupBy 方法能接受一个回调函数,即第二个参数,是‌一个必需的参数,且必须是一个函数,该回调函数接受三个参数
- element‌: 当前遍历到的元素(可迭代对象中的元素)。
- index‌: 当前遍历到的元素的索引。
- iterable: 调用 groupBy 方法时传入的整个可迭代对象本身。
回调函数的返回值用于构建结果对象的属性名,相同值的元素会被归入同一个组。
当回调函数无返回值时,默认返回 undefined,被转换为字符串 “undefined” 作为分组键。
Object.groupBy‌ 返回一个‌无原型的新对象
Object.groupBy 返回的是 Object.create(null) 类型的对象(无原型)。
Object.groupBy 返回的对象 的键名只能是‌字符串‌或 ‌Symbol‌。
Object.groupBy 返回的对象 的键名返回非字符串/非 Symbol 类型(如数字、布尔值、对象)时,会被强制转换为字符串。
如果需要更复杂的键类型(如对象、未转换的数字、NaN 等作为独立键),应使用 Map.groupBy,它返回一个 Map 对象,支持任意类型的键。
// ==========================================
// Object.groupBy‌() 方法详解与示例
// ==========================================
// Object.groupBy‌() 方法根据回调函数返回值对可迭代对象的元素分组。
// 语法: Object.groupBy(iterable, callbackFn)
// 参数:iterable:类似 Array、Map 或者其它实现了可迭代协议的可迭代对象。
//		 callbackFn‌:对可迭代对象中的每个元素执行的函数。
// 返回值:返回一个普通对象

// 案例 1:基础字符串分组
// ------------------------------------------
const array = [1, 2, 3, 4, 5, 6];
const result = Object.groupBy(array, (num) => num % 2 === 0 ?  'even': 'odd');
result //=> { 'even': [2, 4, 6], 'odd': [1, 3, 5]}

// 案例 2:按动态计算的条件分组
// ------------------------------------------
// 使用模板字符串生成复合键
const array = [1, 2, 3, 4, 5, 6];
const result = Object.groupBy(array, (num, index) =>  num % 2 === 0 ?  `even_mod${index%4}`: `odd_mod${index%4}`);
result //=>  { 'even_mod1': [2, 6], 'even_mod3': [4], 'odd_mod0': [1, 5],  'odd_mod2': [3]}

// 案例 3:使用 Symbol‌ 作为键进行分组
// ------------------------------------------
const array = [1, 2, 3, 4, 5, 6];
const even = Symbol('even'); 
const result = Object.groupBy(array, (num) => num % 2 === 0 ?  even: Symbol('odd'));
// 解析过程:
// 即使描述相同,Symbol('a') !== Symbol('a'),因此必须使用同一个 Symbol 变量引用才能分到同一组。
// Symbol('odd') 每次调用都会生成一个新的唯一值,(1 、 3 、5)各自单独成组。
// 使用同一个Symbol('even')变量引用 (2 、 4和 6)归为一组。
result //=> { Symbol('odd'): [1], Symbol('odd'): [3], Symbol('odd'): [5], Symbol('even'): [2, 4] }
groupBy 相似对比方法类型调用方式返回值
Object.groupByObject 静态方法Object.groupBy(iterable, callbackFn)普通对象
Map.groupByMap 静态方法Map.groupBy(iterable, callbackFn)Map 对象
Object.groupBy‌兼容性
ChromeChrome 117
EdgeEdge 117
FirefoxFirefox 119
SafariSafari 17.4
NodeNode.js 21

值比较

严格值比较
方法描述
Object.is返回一个布尔值,比较两个值是否严格相等,与 === 类似,但处理了 NaN 和 +0 、 -0 的特殊情况。
Object.is 接受两个参数
严格接受且仅处理前两个参数。
参数传入 ≥2 个:只会生效前两个参数,其余参数会被忽略。
参数传入 <2 个:缺失的参数会被视为 undefined。0 个参数时,相当于 undefined 相互比较;1个参数时,相当于参数与 undefined 相比较。
Object.is 方法不接受回调函数
Object.is 返回一个布尔值
若参数都是NaN,则两个值相同。返回 true。
若参数一个+0,一个-0,则两个值不同。返回 false。
若参数都是symbol,即使描述相同,Symbol(‘a’) !== Symbol(‘a’) ,因此必须是同一个 Symbol 变量引用,两个值才相同,返回 true,否则返回 false。
若参数是引用类型,不同数组/对象即使内容相同,若不是同一个变量引用 ,返回 false。
// ==========================================
// Object.is() 方法详解与示例
// ==========================================
// Object.is() 方法用于判断两个值是否为同一个值,返回一个布尔值表示判断结果。
// 语法: Object.is(value1, value2)
// 参数:value1:第一个需要比较的值。
//		 value2:第二个需要比较的值。
// 返回值:返回一个布尔值,若两个值为同一个值则返回 true,否则返回 false。

// 案例1: 引用类型比较 (与 === 行为一致)
// ------------------------------------------
// Object.is 比较的是内存地址,不同数组/对象即使内容相同,地址也不同
Object.is([], []); // false: 两个不同的空数组实例,内存地址不同

const foo = { at: '不服你不说' },  bar = { at: '不服你不说' };
const sameFoo = foo;

Object.is(foo, foo); // true: 同一个引用,内存地址相同
Object.is(foo, bar); // false: 虽然内容相同,但是两个不同的对象实例
Object.is(foo, sameFoo); // true: sameFoo 指向 foo 的同一内存地址


// 案例2: 带符号的零 (+0 和 -0)
// ------------------------------------------
// 这是 Object.is 与 === 的主要区别之一
Object.is(+0, -0); // false: Object.is 能区分正零和负零
Object.is(-0, -0); // true: 相同的负零

+0 === -0; // true: 严格相等运算符认为 +0 和 -0 相等


// 案例3: NaN 的比较
// ------------------------------------------
// 这是 Object.is 与 === 的另一个主要区别
Object.is(NaN, NaN); // true: Object.is 认为 NaN 等于自身
Object.is(NaN, 0 / 0); // true: 0/0 的结果是 NaN,Object.is 能正确识别
Object.is(NaN, Number.NaN); // true: 标准 NaN 常量比较

NaN === NaN; // false: 根据 IEEE 754 标准,NaN 不等于任何值,包括它自己


应用与注意事项

应用场景

  • 配置合并:使用 Object.assign() 合并默认配置和用户配置
  • 数据转换:使用 Object.entries() + Object.fromEntries() 进行对象转换
  • 数据分组:使用 Object.groupBy() 对数组数据进行分类统计
  • 严格比较:使用 Object.is() 进行包含 NaN 和 ±0 的精确比较

注意事项

  1. 性能考虑:Object.assign() 是浅拷贝,嵌套对象需递归处理
  2. Symbol 处理:Symbol 键属性在遍历和转换时需特殊处理
  3. 兼容性:Object.groupBy() 需要较新浏览器/Node.js 版本支持
  4. 类型转换:注意基本类型参数的自动转换行为
  5. 错误处理:了解各方法对 undefined/null 的不同处理方式

知识题

题目答案
Object.values会保留属性名为 Symbol 值的属性么不保留 ,Object.values 不保留 Symbol 类型的属性名
Object.fromEntries会保留属性名为 Symbol 值的属性么能保留 ,Object.fromEntries 能保留 Symbol 类型的属性名
Object.fromEntries 是 Object.entries() 的逆操作,Object.entries 能完整恢复 Object.fromEntries 处理的数据不能,Object.fromEntries 创建的 Symbol 键属性无法通过 Object.entries 完整恢复。
new Boolean(false ) / Object(false ) / Boolean(false)的typeof 的结果是否一致一致,都是 object
new String(‘266’) / Object(‘266’) / String(‘266’)的typeof 的结果是否一致一致,都是 object
BigInt(266n) / Object(266n ) 的typeof 的结果是否一致不一致,BigInt(45n) 为 bigint, Object(45n ) 为 object
new Number(266) / Object(266) /Number(266) 的typeof 的结果是否一致一致,都是 object
Symbol(“test”) / Object(Symbol(“test”)) 的typeof 的结果是否一致不一致,Symbol(“test”) 为 symbol, Object(Symbol(“test”)) 为 object
new Function() / Object(function(){}) 的typeof 的结果是否一致一致,都是 function
Object.assign(45n) 的typeof 的结果 与 BigInt(45n) / Object(45n ) 的typeof 的结果 哪个是一致的Object.assign(45n) 的typeof 的结果是 object, 与 Object(45n )的 结果一致
new Boolean(false) / Object(false) 与 false 在 if 语句中的区别new Boolean(false) / Object(false) 是一个对象,在 if 语句中会被判定为 true(因为所有对象都是真值),这与原始值 false 的行为截然不同
别再手动调参了!用MATLAB+改进PSO算法,5步搞定机械臂轨迹优化(附完整代码) 本文介绍如何利用MATLAB和改进PSO算法快速优化机械臂轨迹规划,仅需5步即可完成传统耗时的手动调参过程。通过混沌初始化、自适应权重等创新方法,改进PSO算法显著提升优化效率,实现全局最优解搜索,适用于工业自动化中的机械臂控制。文章包含完整MATLAB代码实现,帮助工程师轻松应用于实际生产场景。 阅读详情

相关推荐

比较器和运算放大器-2

今天继续了解输入阻抗问题,观察下图:首先考虑在我们没有接运放时,A点输出电压为6V,当接入如图所示的阻抗时电压还是6V吗?共模电阻和红框内对地电阻并联,阻值变小,相当于5k,通过计算可以求得A点电压变为4V,这样A的值发生了改变,试想一下这样的信号接入到运放的两端是不是相当于比较的两端信号发生了改变,那结果一定会发生偏离。信号源一般内阻是不确定的,一般也不是很小,如果不想改变输入阻抗,那唯一的办法就是改变运放的内阻了,比如内阻改为100K,1M等,越大越好,是不是A点电压就会无限接近6V。

weixin_42855218的博客 1312

平凡前端之路_14.ES与ES6

JavaScript一种动态类型、弱类型、基于原型的客户端脚本语言,用来给HTML网页增加动态功能。 ES 全称ECMAScript,以JavaScript为基础制定的一种脚本语言标准规范。 ES6是ECMAScript第六个版本,在保证向下兼容的前提下,在ES5之后的下一代标准。 ES6在ES5的基础上扩展了丰富的特性:let和const;解构赋值;展开操作符/剩余参数;字符串、函数、数组、对象的扩展;Promise;类;模块;Symbol;Set和Map数据。

jun266a的博客 889

ESP8266 进行HDLC解码,AX.25,APRS

/************************************************************** 函数名:aprs_wait_begin() 参 数:无 返回值:bool true=得到合法脉冲,false=未得到 说 明:等待第1个833us高脉冲,判断范围 730-930,其他忽略 ***************************************************************/ bool aprs_wait_begin(){ stati

蓝蓝的博客 1634

从原型污染漏洞看前端供应链安全:以Lodash为例的实战攻防

在JavaScript开发中,原型链是对象间继承机制的核心,它允许对象访问其原型上的属性和方法。然而,这一特性也带来了原型污染的安全风险,即攻击者通过操纵__proto__等属性,向基础原型注入恶意代码,从而影响所有继承该原型的对象。这种漏洞的技术价值在于揭示了即使广泛使用的工具库也可能存在深层安全隐患,对应用安全构成严重威胁。在工程实践中,原型污染常出现在对象合并、克隆等操作中,特别是当处理用户可控的输入数据时。例如,Lodash库的_.defaultsDeep等函数在旧版本中曾因此类问题成为攻击突破口,

weixin_30883311的博客 453

深入解析Flex NOC总线驱动的实时带宽与延迟优化策略

本文深入解析了Flex NOC总线驱动的核心价值与优化策略。通过解读`/proc/noc/real_time`中的实时带宽与延迟数据,并结合`sysfs`接口进行动态QoS调优,可以有效解决芯片内部数据拥堵问题。文章以智能摄像头和算力盒子的实际案例,详细说明了如何通过优先级调整、带宽限制和参数优化,提升系统在复杂任务下的实时性与稳定性。

weixin_29289821的博客 284

海康机器人ID5000 系列智能读码器(三)

又過了兩個月,漸漸的對這個攝像頭的功能更加熟悉了,而實際上,我要做的功能也越來越複雜,從一開始的讀碼,到後來的通過讀二維碼控制設備,再到未讀到二維碼控制設備等,下面就對具體的細項做一個總結。了解完這些就能對ID5000這個設備,乃至很多海康的設備都能做一個二次開發。

qq_54359036的博客 3074

binance-trading-bot 贡献者指南:架构脉络、插件扩展点与 CI 质量闸门全解析

本文是 binance-trading-bot 仓库(`gh_mirrors/bi/binance-trading-bot`)的贡献者参考导航,面向想读懂架构、扩展功能或提交 Pull Request 的开发者。文章以 `docs/contributing/index.md` 为骨架,结合仓库源码与配置,讲解"从哪开始读代码""策略与通知器两个插件扩展点怎么加""Renovate 依赖更新为何是双

gitblog_00556的博客 150

LaTeX公式转Word竟这么简单?Python三行代码实现学术论文格式无忧

本文介绍如何利用Python的latex2word库,仅需三行代码即可将LaTeX数学公式精准转换为Word原生Office Math对象,解决学术写作中LaTeX与Word格式割裂的难题。该方法支持批量处理、格式保真,并能与Markdown、Jupyter Notebook等工具集成,构建自动化写作流程,实现学术论文格式无忧。

qsc90123456的博客 297

CPython `re` 模块完整指南:正则表达式语法、模块级 API、Pattern/Match 对象与源码实现

> 本文基于 CPython 官方库参考 [Doc/library/re.rst](https://link.gitcode.com/i/0ca85e4e9d749f161884addb2da0596b) 整理而成,当前仓库代码版本为 CPython 3.16.0a0(见 [Include/patchlevel.h](https://link.gitcode.com/i/079b7ff277590

gitblog_00309的博客 496

保姆级教程:用Unity为麒麟系统打包Linux应用(含路径权限全攻略)

本文提供了一份详细的Unity跨平台开发指南,重点介绍如何在麒麟系统上打包和部署Linux应用。从开发环境配置、路径权限处理到性能优化和常见问题解决,全面解析了Unity项目在国产操作系统上的适配流程,帮助开发者高效完成跨平台应用开发。

weixin_28692867的博客 506

PIMPL 模式 以及Q_DECLARE_PUBLIC 与 Q_DECLARE_PRIVATE

在 C++ 中,PIMPL 模式通常通过将类的私有数据和实现放在一个单独的类中,然后在类的公共接口中使用指向该私有实现类的指针来实现。宏可以帮助在 Qt 的 PIMPL 模式中实现类的私有实现和公共接口的分离,提高代码的封装性和可维护性。宏的结合使用,我们可以实现类的私有性和封装,避免暴露私有实现的细节,同时提高类的可维护性和灵活性。:这一行声明了一个友元类,使得类的公共接口可以访问私有实现类的私有成员。:这一行声明了一个友元类,使得类的私有实现可以访问类的私有成员。是两个宏,用于实现 PIMPL 模式。

追赶时代的博客 853

【课程设计】(附源码)springboot自习室座位预约系统 毕业设计674156

在社会快速发展的影响下,教育事业蓬勃发展,大大增加了学校的数量、多样性、教育质量等要求,使教育的管理和运营比过去更加困难。依照这一现实为基础,设计一个快捷而又方便的自习室座位预约系统是一项十分重要并且有价值的事情。对于传统的自习室座位预约系统来说,自习室座位预约系统具有许多不可比拟的优势,首先是快速更新校园资讯,其次是大量信息的管理,最后是高度安全,以及使用简单等特性,这使得自习室座位预约系统的管理和运营非常方便。进入21世纪,因为科技和经济的迅速发展,人民普遍对非物质层面的精神需求变得越来越多元化。

Biye_Design的博客 3062

SAP FICO CBS接口-银企直连付款平台功能开发说明书(包括测试样例、FS)

SAP FICO CBS接口-银企直连付款平台功能开发说明书(包括测试样例、FS)

我好像病了的博客 2449

Fountain JIT 里程碑 M2 规格深度解析:宿主闭包、HostObject 通道与成员访问增量的互操作设计

本文围绕 Fountain 项目 JIT 子系统的第二篇专项规格 [docs/jit/jit-bytecode-m2.md](https://link.gitcode.com/i/c1832f1e7c5bcd0a901fcff758ee4d4b)(M2-draft v0.8.27)展开,系统讲解字节码世界与宿主仓颉之间**双向互操作**的技术方案:从接收并调用宿主闭包(HostClosure)、不

gitblog_00171的博客 1033

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【课程设计】(附源码)python+mysql+基于python的学生成绩管理系统 毕业设计071143

本论文系统地描绘了整个学生成绩管理系统的设计与实现,主要实现的功能有以下几点:首页、站点管理(轮播图、公告栏)用户管理(管理员、学院秘书、任课老师、学生)内容管理(新闻列表、新闻分类)更多管理(删除申请管理、学生成绩管理、核对申请管理)等功能,其具有简单的接口,方便的应用,强大的互动,完全基于互联网的特点。

Biye_Design的博客 4403

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

PyCaret 4.0 工程重构全记录:从 3.4.0 到 sklearn 原生引擎与控制平面的完整演进

本篇技术指南以当前仓库中的权威工程变更日志 [release_notes_pycaret4.md](https://link.gitcode.com/i/bc07d12a5b7de68e8b8810a63dfc8f88)(共 2889 行,覆盖 Session 1–57)为核心骨架,结合 `packages/engine` 引擎源码与 `services/api`、`apps/web` 平台代码,

gitblog_00657的博客 293

You Don‘t Know JS(俄语仓库版)第 8 章深度解读:async/await、Object.observe、SIMD 与 WebAssembly——“超越 ES6“的前沿特性全景

> 本指南以 [es6 & beyond/ch8.md](https://link.gitcode.com/i/454e41e7efd006b5237d8552ebb64f3b) 为骨架,系统梳理 ECMAScript 2015 定稿前后 TC39 委员会正在酝酿的下一代语言特性:`async function`(异步函数)、`Object.observe(..)`(对象变更观察)、幂运算符 `*

gitblog_00294的博客 191

(附源码)spring boot考试系统-毕业设计 课程设计 191015

(1)考试系统,考试信息维护,用户维护和个人信息维护管理员可以往题中添加考题,修改错误试题和删除无用试题,考试系统包括单选题管理(单选题添加、删除、修改)、判断题管理(判断题添加、删除、修改)、多选题管理(多选题添加、删除、修改)。 (2)考试信息的维护 考试信息的维护主要是对于考试设置信息进行维护,这些信息主要是考试总时间,试题数量,各试题分值的分布等。 (3)用户维护 系统管理员可以对用户信息(包括考生信息)进行增,删,改查操作。 (4)个人信息维护 管理员也可以对自己的基本信息的维护。

Q_3461074420的博客 4136

(附源码)ssm学生管理系统-毕业设计 课程设计 141543

本设计主要实现集人性化、高效率、便捷等优点于一身的学生管理系统,完成首页、用户管理(管理员、学生)更多管理(学院管理、专业管理、班级管理、课程安排、学生选课、课程成绩、学生请假、健康申报、通知公告)系统通过浏览器与服务器进行通信,实现数据的交互与变更。只需通过一台电脑,动动手指就可以操作系统,实现数据通信管理。整个系统的设计过程都充分考虑了数据的安全、稳定及可靠等问题,而且操作过程简单。本系统通过科学的管理方式、便捷的服务提高了工作效率,减少了数据存储上的错误和遗漏。...

Q_3461074420的博客 1659

大语言模型 - 提示词(Prompt)工程入门

提示词工程,或称Prompt Engineering,是一种专门针对语言模型进行优化的方法。它的目标是通过设计和调整输入的提示词(prompt),来引导这些模型生成更准确、更有针对性的输出文本。在与大型预训练语言模型如GPT-3、BERT等交互时,给定的提示词会极大地影响模型的响应内容和质量。提示词工程关注于如何创建最有效的提示词,以便让模型能够理解和满足用户的需求。这可能涉及到对不同场景的理解、使用正确的词汇和语法结构,以及尝试不同的提示策略以观察哪种效果最佳。1、明确具体:加入场景要求、具体任务。

秃了也弱了 4万+

Buck 内置 PEX 发行史详解:解读 third-party/py/pex/CHANGES.rst 从 0.1.0 到 1.1.1 的完整演进与 Buck 构建链中的集成方式

本文以 Buck 仓库中 vendor 的第三方 Python 依赖 pex 的变更记录 [third-party/py/pex/CHANGES.rst](https://link.gitcode.com/i/56a1398290b7ada51bf1ddd52b8b092e) 为主体,完整梳理其从 0.1.0 到 1.1.1 全部版本的特性演进与缺陷修复历史;并结合 [third-party/py

gitblog_00904的博客 300

GLM-5.1稳定接入指南:绕过抢购,用百炼API实现工程化编程协作

大语言模型(LLM)在编程场景中的落地,核心在于从‘体验式调用’转向‘可编排、可监控、可集成’的工程实践。GLM-5.1作为智谱新一代代码生成模型,其真实价值不在于前端抢购入口,而在于标准化API接口所提供的稳定性、参数可控性与DevOps兼容性。通过阿里云百炼平台,开发者可获得免抢、免审核、按量计费的工业级接入通道,并结合temperature/top_p等关键参数优化生成确定性,无缝嵌入GitLab CI、Slack机器人、VS Code插件等真实开发工作流。本文聚焦GLM-5.1 API工程化实践,覆

weixin_34055787的博客 381

Slang 编译期性能基准套件设计解析:tools/compile-perf 的架构、工作负载与 CI 漂移检测

本篇技术指南以 [tools/compile-perf/DESIGN.md](https://link.gitcode.com/i/1010dfd0025abb001d2183a5d30ce117) 为核心骨架,结合 [tools/compile-perf/README.md](https://link.gitcode.com/i/3af670269a3ba2225e211d7bf776a12f)

gitblog_06899的博客 235

全文 - Building AI Coding Agents for the Terminal: Scaffolding, Harness, Context Engineering, and Less

AI 编程辅助的格局正在经历一场根本性转变:从复杂的 IDE 插件转向通用的、终端原生的智能体(agent)。直接在开发者管理源代码版本控制、执行构建和部署环境的终端中运行,基于 CLI 的智能体为长程开发任务提供了前所未有的自主性。本文介绍OpenDev——一个专为这一新范式打造的开源命令行编程智能体。有效的自主辅助需要严格的安全控制和高效的上下文管理,以防止上下文膨胀和推理退化。

eloudy的专栏 455

JAX 的 AOT 提前编译:从 Lower 到 Compile 的显式编译管线实战指南

> **导读**:本指南以 JAX 官方文档 [docs/aot.md](https://link.gitcode.com/i/578478a3ffcc3ce9a5751d54a977f69a) 为核心,系统讲解 Ahead-of-Time(AOT)提前编译的完整工作流——将 `jax.jit`/`jax.pmap`/`pjit`/`xmap` 的编译过程拆解为可显式控制的 **Lowering(

gitblog_00557的博客 439

【技术人的思维:角色思维】5、程序员思维修炼:抽象、防御、幂等与编码法则

本文系统阐述了程序员思维的核心心智模型,包括六大关键维度: 抽象与封装:通过隐藏复杂实现、暴露简洁接口来管理复杂度,同时理解抽象泄漏定律的必要性。 分层与解耦:运用关注点分离原则构建正交系统,使变更影响局部化,典型模式包括MVC/DDD/微服务。 SOLID原则:遵循面向对象设计的五大核心法则(单一职责、开闭原则等)和DRY/YAGNI实践,编写可维护代码。 防御性编程:以"不信任输入"为前提设计健壮系统,建立边界检查、异常处理和校验机制。 分布式契约:在分布式系统中确保幂等性、原子性等关键特性,通过契约思

2025博客之星Top81。专注AI工程化与架构实战。从分布式思维到模型部署,用工程化视角为你厘清AI落地的真实路径。 492

Wolfcha识人术:8个看穿AI对手谎言的终极技巧

**Wolfcha 是一款 AI 狼人杀游戏**:你占一个座位,其余 8~12 个座位全部由 AI 玩家填充。它们会发言、会伪装、会撒谎——想赢下对局,你必须掌握这套看穿 AI 对手谎言的识人术。下面 8 个技巧从记录、验查到心态复盘,帮你把每一次发言和投票都变成推理证据。 [![Wolfcha AI狼人杀游戏界面,玩家与AI对手对局](https://raw.gitcode.com/gh_mi

gitblog_00899的博客 211
上一篇: 平凡前端之路_20.函数的扩展
jun266a
博客等级 码龄10年 2粉丝 37原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值