JS new操作符原理、手写myNew与面试边界全解析

发布时间:2026/11/2 5:10:05

JS new操作符原理、手写myNew与面试边界全解析 聊到JS面试题new操作符几乎是绕不开的一道。这道题看着简单四个步骤背下来好像就完事了但我带过不少同学真让他手写一个myNew出来或者在class、箭头函数、返回值判断这些边角上追问两句能答利索的人并不多。new操作符是JS里少数几个语法糖背后藏着一整套对象创建机制的东西它把创建对象、绑定原型、执行构造函数、处理返回值这四件事打包成了一个关键字。搞懂它你顺手就能把原型链、this绑定、instanceof、constructor属性这几块知识串起来形成一张网。这篇文章不谈空理论我按自己平时带新人、看简历、面别人的路子把new从“面试能答”讲到“代码能写”再到“边界不翻车”准备面试的同学能直接用工作几年但一直没细究过这块的开发者也能补上认知缺口。1. 先搞明白new操作符到底在解决什么问题1.1 从工厂模式说起为什么需要new早年间没有class语法的时候大家创建一批结构相同的对象最朴素的做法是工厂函数写一个函数里面手动建一个空对象往上面挂属性最后return出去。这种写法能跑但有两个明显的毛病。第一个是每创建一个对象都得重新走一遍“建对象、挂属性”的流程函数内部的逻辑和对象本身的类型没有建立任何关系第二个更关键工厂函数返回的对象你没法判断它到底属于哪一类它只有一个模糊的Object身份。假设页面里同时有用户对象、订单对象、商品对象你拿到一个引用想区分它是哪一类工厂模式基本帮不上忙。构造函数加new的组合解决的正是“批量创建”和“类型识别”这两件事。JS设计者把创建对象的固定流程收进new这个关键字里你只需要写一个构造函数描述“这类对象应该有哪些属性和方法”剩下的搭建工作交给引擎。这就像盖房子工厂模式是你每次亲手搬砖、和泥、砌墙而new相当于给你一套标准化的施工流程地基自动打好图纸自动贴上你只管往房间里摆家具。这里有个容易被忽略的点构造函数本质上就是普通函数没有任何特殊语法。它之所以叫构造函数仅仅是因为你用了new去调用它。同一个函数你直接调用它就是普通函数this指向取决于调用方式你用new调用它才进入“构造”模式this指向一个全新的对象。理解这一点后面讲this绑定和返回值判断时就不会乱。1.2 面试官真正想听到的四步答案面试时被问到new干了什么最稳妥的答法是按执行顺序说清楚四件事创建一个全新的空对象。把这个空对象的内部原型指向构造函数的prototype属性。把构造函数内部的this绑定到这个新对象上执行构造函数体。判断构造函数的返回值如果返回的是一个对象就用这个返回值否则返回第一步创建的新对象。这四步不是背口诀每一步都有它存在的理由。第一步保证每次new都得到一个独立的实例实例之间互不干扰第二步是原型链的入口决定了实例能访问哪些共享方法第三步让构造函数里的this.name xxx这类赋值真正落到新对象上第四步是很多人栽跟头的地方它解释了为什么构造函数里写return {a:1}会覆盖掉新对象而写return 123却毫无影响。面试官问这道题表层是考记忆深层是考你对对象创建机制的理解。他接下来大概率会追问手写一个new、new.target是什么、箭头函数能不能new、class和普通构造函数在new的时候有什么区别。这些问题都建立在上面四步之上四步答得清楚追问才有得聊四步都说不利索后面的问题基本就是送分变送命。2. 拆解new操作符的四个核心动作2.1 第一步创建空对象同时接上原型链第一步创建的空对象不是随便一个{}就完事。引擎在内部创建的是一个普通对象但紧接着第二步会做一件关键的事把这个对象的[[Prototype]]也就是我们常说的__proto__指向构造函数的prototype属性。这两步在实际效果上几乎同时发生拆开讲是为了让你看清因果。为什么原型绑定这么重要因为构造函数里通常只放实例独有的属性比如姓名、年龄、id而方法一般挂在prototype上共享。实例创建出来之后你调用p.sayHello()引擎会先在p自身找sayHello找不到就沿着__proto__往上找找到Person.prototype上命中后执行。这条查找路径就是原型链。如果new的时候没做这层绑定实例和prototype就是两张皮共享方法全部失效内存里每个实例都得自己存一份方法浪费空间不说改一个方法要改所有实例。我见过有同学手写myNew时用Object.create(null)创建对象想着“空对象嘛干净”结果实例的__proto__是null原型链直接断了instanceof判断全挂。正确的做法是让新对象的原型指向构造函数的prototype最直白的写法是Object.create(Constructor.prototype)这句本身就完成了“创建对象绑定原型”两件事比先建对象再改__proto__更干净。2.2 第二步绑定this执行构造函数体原型接好之后引擎会把构造函数当成一个普通函数调用但this被强行指定为新创建的那个对象。这里用apply或者Reflect.construct都能实现手写实现里常见的是Constructor.apply(obj, args)。这一步执行完构造函数里所有this.xxx yyy的赋值都落到了新对象上实例的私有属性就有了。有个细节值得留意this的绑定发生在函数执行之前而不是执行过程中。这意味着构造函数体里无论你怎么折腾this始终指向那个新对象除非你手动用call/apply改但那属于自己给自己挖坑。另外构造函数执行过程中如果抛异常new表达式会直接把异常往外抛不会返回半成品对象。这一点在排查“为什么new完拿到的是undefined”时很有用先看看构造函数里是不是某一行报错了。参数传递也发生在这一步。new Person(A同学, 20)里的参数会原封不动地传给构造函数。手写实现时参数要用arguments或者剩余参数收集再展开传给apply别漏了。我见过最冤的一种写法是只传了第一个参数测试用例里构造函数刚好只用第一个参数跑起来没问题换个用例立刻暴露。2.3 第三步返回值判断对象与原始值的分水岭第四步的判断规则是这道题区分“背过”和“懂了”的分界线。规则本身不复杂构造函数如果显式返回一个对象包括数组、函数、日期等new表达式就返回这个对象如果返回的是原始值字符串、数字、布尔、null、undefined、Symbol或者干脆没写returnnew表达式就返回第一步创建的新对象。为什么这么设计因为构造函数的本职工作是初始化this返回值是附加能力。如果允许返回原始值覆盖新对象那new Person()拿到一个数字就很荒谬后续所有基于实例的操作全废。允许返回对象是为了支持一种少见但合法的场景构造函数内部想复用已有对象或者想返回一个代理对象。比如某些库会在构造函数里判断参数命中缓存就直接返回缓存里的实例这种情况下返回对象的能力就派上用场了。判断“是不是对象”时有个坑typeof null object但null不是对象不能当成有效返回值。手写实现里常见写法是result ! null typeof result object或者更严谨一点用typeof result object result ! null || typeof result function把函数也纳入对象的范畴。函数虽然typeof是function但它确实是对象可以被返回。这块细节面试官很爱抠写代码时别偷懒。2.4 四步串起来伪代码长什么样把四个动作翻译成代码骨架大概是这样function myNew(Constructor, ...args) { // 1 2创建对象并绑定原型 const obj Object.create(Constructor.prototype); // 3绑定 this 并执行构造函数 const result Constructor.apply(obj, args); // 4判断返回值 if (result ! null (typeof result object || typeof result function)) { return result; } return obj; }这段代码不到十行但每一行都对应一个明确的设计意图。Object.create那一行同时完成了建对象和接原型比手动obj.proto ...更规范因为直接操作__proto__在性能和可读性上都不占优。apply那一行负责执行和传参result接住构造函数的返回值。最后那个if是返回值判断的守门员把null和原始值挡在外面。当然这只是面试场景下的简化版真实的new还要处理new.target、class构造函数不能直接apply调用等限制。手写版的意义在于让你把机制吃透而不是替代原生new。实际项目里老老实实用new或者Reflect.construct别自己造轮子。3. 从规范和运行机制看new的执行细节3.1 [[Construct]]内部方法与new.target从语言规范的角度看new表达式触发的是对象的[[Construct]]内部方法。普通函数、class、内置构造函数都拥有这个方法但箭头函数没有所以箭头函数不能new用了直接抛TypeError。这个报错信息在不同引擎里措辞不同但本质都是“你没有[[Construct]]别硬来”。[[Construct]]执行时会创建一个执行上下文里面有一个特殊的东西叫new.target。它指向被new调用的那个构造函数本身。普通调用时new.target是undefined用new调用时它指向构造函数。这个机制最常见的用途是在构造函数里判断“我是不是被new调用的”如果不是就抛出错误或者自动补一个new。比如function Person(name) { if (!new.target) { throw new Error(Person 必须用 new 调用); } this.name name; }这段代码在面试里是加分项。它说明你知道new不只影响this还影响函数执行上下文里的元信息。另外class构造函数默认就有类似保护你不加new直接调用class会直接报错这是class和普通构造函数在调用约束上的显著差异。3.2 原型、constructor与instanceof的真实关系很多人把constructor属性当成“指向构造函数”的权威标识其实它只是prototype上的一个普通属性默认由引擎在创建函数时挂上去指向函数自身。它是可写的、可改的甚至可以被删掉。真正决定instanceof结果的是原型链上有没有出现构造函数的prototype。instanceof的判断逻辑是拿到右侧构造函数的prototype沿着左侧对象的__proto__一路往上找找到就返回true。所以如果你手写myNew时原型接错了或者中途改了Constructor.prototype的指向instanceof的结果就会和你预期不一致。我在排查这类问题时有个固定套路先打印obj.proto Constructor.prototype再打印Constructor.prototype.constructor Constructor两个都为true原型关系才是健康的。还有一个容易混淆的点实例的constructor属性是从原型上继承来的不是自己身上有的。你访问p.constructor引擎先找p自身没有顺着原型找到Person.prototype.constructor得到Person。如果你把Person.prototype整个替换成一个新对象记得手动把constructor补回去否则p.constructor会变成Object调试时看着很迷惑。3.3 参数传递与this绑定发生在哪个时刻参数求值发生在new表达式执行之前。也就是说new Person(getName(), getAge())里getName和getAge会先执行拿到结果再进入[[Construct]]。这个顺序在参数有副作用时能观察到比如参数里打日志日志会先于构造函数体里的日志输出。this绑定发生在构造函数执行上下文中绑定对象就是第一步创建的新实例。这里有个反直觉的地方构造函数里如果返回了一个对象this绑定的那个实例并不会被销毁只是new表达式不返回它了。它成了一个没有引用的孤儿对象等着被垃圾回收。这也是为什么“返回对象覆盖实例”的写法要慎用你辛苦初始化的属性可能全白干了。理解这些时序细节在手写实现和排查诡异bug时特别有用。比如你发现构造函数里的this指向不对先确认调用方式是不是new再确认有没有在构造函数里用箭头函数包了一层导致this丢失最后看返回值有没有把实例顶掉。按这个顺序查基本不会绕远路。4. 手写一个经得起追问的myNew4.1 第一版先让主流程跑通面试现场时间有限先写一版能跑的主流程再根据面试官反馈打磨这个节奏比较稳。第一版就按前面伪代码来function myNew(Constructor, ...args) { if (typeof Constructor ! function) { throw new TypeError(第一个参数必须是函数); } const obj Object.create(Constructor.prototype); const result Constructor.apply(obj, args); return result ! null (typeof result object || typeof result function) ? result : obj; }这版已经覆盖了四步核心逻辑还顺手加了参数类型校验防止有人传个对象进来直接崩。写完之后拿几个用例跑一下无返回值的构造函数、返回对象的构造函数、返回数字的构造函数、带参数的构造函数。四个用例全过主流程就算立住了。这里提醒一句有些面试官会让你手写时不借助Object.create纯手工模拟。那就得用中间函数做原型桥接function createObj(proto) { function F() {} F.prototype proto; return new F(); }这种写法在Object.create出现之前是标准做法现在写出来主要是展示你理解原型继承的底层手段实际项目里没必要这么绕。4.2 第二版补上new.target与边界校验第一版有个隐患如果Constructor本身是个箭头函数apply能执行但箭头函数没有自己的this绑定会失效结果不符合预期。更严谨的做法是提前拦截或者在文档里注明限制。面试场景下主动说出“箭头函数没有[[Construct]]原生new会直接报错我这个简化版无法完全模拟这个报错”反而是加分项说明你知道自己实现的边界在哪。另一个可以补的点是new.target的模拟。原生new在构造函数里能拿到new.target手写版用apply调用new.target是undefined。想模拟的话得用Reflect.construct它是专门为“用指定参数和new.target调用构造函数”设计的function myNew(Constructor, ...args) { if (typeof Constructor ! function) { throw new TypeError(Constructor must be a function); } const obj Object.create(Constructor.prototype); const result Reflect.construct(Constructor, args, Constructor); return result ! null (typeof result object || typeof result function) ? result : obj; }用Reflect.construct之后构造函数内部能正确拿到new.targetclass也能正常处理。不过要注意Reflect.construct本身就会创建实例所以前面的Object.create在返回值判断为原始值时会有点冗余。更贴近原生行为的写法是直接返回Reflect.construct的结果function myNew(Constructor, ...args) { if (typeof Constructor ! function) { throw new TypeError(Constructor must be a function); } return Reflect.construct(Constructor, args); }这版最短也最接近原生。面试时先写apply版展示你对四步的理解再补一句“生产环境直接Reflect.construct更稳”层次就出来了。4.3 测试用例清单别只测happy path手写完代码一定要主动跑测试这是很多同学忽略的环节。下面这张表是我常用的用例清单覆盖正常和异常路径用例构造函数写法预期结果无返回值function A(){ this.x 1; }实例含x原型指向A.prototype返回对象function A(){ return { y: 2 }; }返回{ y: 2 }不是实例返回数组function A(){ return [1,2]; }返回数组返回函数function A(){ return function(){}; }返回该函数返回数字function A(){ return 1; }返回实例返回nullfunction A(){ return null; }返回实例返回undefinedfunction A(){ return undefined; }返回实例带参数function A(a,b){ this.sum ab; }实例sum为参数和原型方法A.prototype.say function(){}实例能调用sayinstanceof上述实例obj instanceof A true跑完这张表基本能覆盖面试官会追问的八成场景。剩下两成是class、内置构造函数、Symbol等偏门情况能说清楚原理即可不必全部手写实现。5. 常见翻车点与排查实录5.1 返回值判断的三种错误写法第一种错误是只看typeof不排除nullif (typeof result object) return result;。构造函数返回null时这句会把null当成有效返回值返回调用方拿到null去访问属性直接崩。修法很简单加一个result ! null的判断。第二种错误是漏掉函数只判断typeof result object构造函数返回一个函数时会被当成原始值忽略返回的仍然是实例。这在实际业务里不常见但面试官拿这个考你“对象包含哪些类型”答不上来就是知识盲区。修法是把typeof function也纳入判断。第三种错误是最隐蔽的把判断写反了返回对象时返回实例返回原始值时返回result。这种错误跑简单用例可能发现不了因为常见的构造函数大多不写return两种写法结果一样一旦遇到显式返回对象的场景立刻暴露。排查时直接对比规范规则别凭感觉。5.2 instanceof失效的三条排查路径实例instanceof判断为false问题通常出在原型链上。我一般按三条路径排查第一条检查手写myNew有没有绑定原型Object.create那一步是不是漏了或者传错了参数第二条检查构造函数执行过程中有没有替换prototype如果在new之前改了Constructor.prototype实例指向的是旧原型而instanceof用的是新原型两边对不上第三条检查有没有用Object.setPrototypeOf之类的操作中途改写了实例的原型。还有一种情况是跨iframe或者跨执行上下文两个上下文的Array不是同一个构造函数用instanceof判断数组会失败。这种场景得用Array.isArray或者Object.prototype.toString.call属于环境问题不是new的锅但面试聊到instanceof时顺嘴提一句能体现你踩过坑。5.3 箭头函数、class和内置构造函数的特殊表现箭头函数不能new原因是没有[[Construct]]和prototype。你写const f () {}; new f()直接抛TypeError。这个知识点经常和this绑定一起考记住结论箭头函数的this在定义时确定没有自己的this也不能作为构造函数。class用new调用时行为和普通构造函数大体一致但有两条额外约束class必须用new调用直接调用报错class内部的constructor里如果返回原始值同样会被忽略返回对象则覆盖实例。另外class的方法定义在prototype上且不可枚举这点和手动挂的方法不同用for...in遍历实例时能看出差异。内置构造函数如Date、Array、Error用new调用和直接调用行为不同。Date()不带new返回字符串带new返回日期对象Array()带不带new都返回数组但语义上略有区别。这些差异不需要死记理解“new触发[[Construct]]”这个总原则遇到具体类型查文档即可。6. 面试现场怎么答才能稳住6.1 分层表达从一句话到四步再到代码回答这道题建议分三层递进。第一层用一句话定调“new的核心是创建一个对象绑定原型和this再根据返回值决定最终返回什么。”这句话让面试官知道你抓住了主干。第二层展开四步按执行顺序讲每步配一句为什么。第三层如果面试官有兴趣主动提出可以手写实现把代码写出来再讲一遍关键行。这个分层的好处是可控。面试官只想要个概述你第一层就够他想深入你有第二层第三层接着。最怕的是一上来就背四步背完冷场面试官不知道你是真懂还是死记。分层表达配合主动引导节奏就掌握在你手里了。另外讲的时候多用“因为所以”的连接。比如“因为构造函数的返回值可能是原始值所以new在最后要做一次判断”这种因果链能体现理解深度比干巴巴列步骤强很多。6.2 高频追问预判与应答思路追问一new和Object.create有什么区别应答思路是Object.create只做原型绑定不执行构造函数不初始化属性new是原型绑定加执行构造函数加返回值判断一套完整流程。两者不是替代关系Object.create常被用来实现继承。追问二不用new能不能创建实例能用Object.create(Constructor.prototype)建对象再Constructor.apply(obj, args)执行构造函数最后手动处理返回值。这正是手写myNew的思路答出来等于把知识串起来了。追问三new的性能怎么样这个问法比较开放稳妥的答法是new本身开销很小主要成本在构造函数体执行和原型链查找真正影响性能的是构造函数里做了多少事而不是new这个关键字本身。避免把话题带到没有数据支撑的猜测上。追问四class和function在new时行为差异抓住三点class必须new、class方法不可枚举、class内部严格模式。其余行为在实例创建层面基本一致。6.3 一个容易忽略的表达细节最后分享一个表达上的小技巧。讲四步的时候把“创建对象”和“绑定原型”合并成一步说很多资料是拆开写的但实际执行上这两件事紧密相连合并讲更符合直觉也少一个被追问“这两步到底谁先谁后”的风险。合并后变成三步建对象并接原型、绑this执行、判断返回值。三步比四步好记讲的时候再补一句“拆细了就是创建、接原型、绑this、判返回值四件事”两种说法都覆盖到面试官怎么问都能接。这道题我面过不下几十次真正拉开差距的不是背没背下四步而是能不能在手写实现时把返回值判断写对、能不能说清楚原型绑定为什么重要、能不能主动指出自己实现的边界。把这几个点吃透new这道题就从“送分题”变成“加分题”了。
延伸阅读

更多相关文章

2026/11/2 5:10:05

JavaScript new 操作符:原型链、this 绑定与手写实现

new这个操作符,写 JavaScript 的人几乎每天都在敲,可一旦面试官把它单独拎出来问"你说说 new 到底干了什么",能答利索的人反而不多。多数人的答案停在那套背了无数遍的四个步骤上:创建空对象、绑定原型、执行构造函数、…

2026/11/2 5:10:05

导师退回问题清单:文献综述从选题到定稿,工具该怎么选

从导师审稿和答辩把关的视角看,文献综述最容易被退回的,通常不是“句子不够华丽”,而是下面三类问题: 文献来源与引用问题:参考文献太旧、太偏、真伪难辨;引文和原文观点对不上;综述写成了“观点…

2026/11/2 5:10:05

从后见之明到行动项:一套可复用的项目复盘流程

“hindsight”这个词第一次出现在我工作笔记里,是在一次上线事故复盘之后。我们开了三个小时总结会,最后的结论只有四个字:“下次注意”。散会之后我坐在工位上发呆,突然意识到,过去半年我写过不少复盘文档&#xff0c…

2026/11/2 6:05:08

FPGA+STM32相控阵雷达原型:PLFM_RADAR系统设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/2 6:05:08

扫地机器人回充座通信报文解析与回充定位全链路实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/2 6:05:08

工业SPI隔离通信设计:容性隔离器与MCU协同实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/2 6:05:08

以太网温湿度变送器双协议批量配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/2 6:05:08

STM32 SPI隔离设计:MAX14431容耦方案实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/2 6:00:07

Golang 实战:微信公众号接入 DeepSeek API 智能回复

简介:这份资源是面向 Golang 后端开发者与微信公众号运营者的完整源码包,解决的是「不想装 App、想在微信里直接用 DeepSeek」的接入问题。它把 DeepSeek API 与微信公众号后台打通,涵盖消息接收、文本转换、请求响应封装、会话上下文维护以及…

2026/11/1 0:01:26

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/1 1:01:33

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/2 1:04:04

工业级SPI隔离设计:硬件抗扰与信号完整性实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/2 1:04:04

PLFM_RADAR:主动探测数据通道,构建低误报的数据感知系统

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/2 1:04:04

工业SPI隔离设计:MAX14431与STM32F746硬件抗干扰实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/1 0:01:26

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/1 1:01:33

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑