JS---进阶

news2026/3/18 16:49:32
作用域作用域(scope)规定了变量能够被访问的“范围”离开了这个“范围”变量便不能被访问作用域分为局部作用域全局作用域局部作用域局部作用域分为函数作用域和块作用域。1.函数作用域在函数内部声明的变量只能在函数内部被访问外部无法直接访问。总结1.函数内部声明的变量在函数外部无法被访问2.函数的参数也是函数内部的局部变量3.不同函数内部声明的变量无法互相访问4.函数执行完毕后函数内部的变量实际被清空了2.块作用域在JavaScript中使用{}包裹的代码称为代码块代码块内部声明的变量外部将【有可能】无法被访问。1.let声明的变量会产生块作用域var不会产生块作用域2.const声明的常量也会产生块作用域3.不同代码块之间的变量无法互相访问4.推荐使用let或const全局作用域script标签和.jS文件的【最外层】就是所谓的全局作用域在此声明的变量在函数内部也可以被访问。全局作用域中声明的变量任何其它作用域都可以被访问注意1.为window对象动态添加的属性默认也是全局的不推荐2.函数中未使用任何关键字声明的变量为全局变量不推荐3.尽可能少的声明全局变量防止全局变量被污染作用域链作用域链本质上是底层的变量查找机制。在函数被执行时会优先查找当前函数作用域中查找变量如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域总结1.嵌套关系的作用域串联起来形成了作用域链2.相同作用域链中按着从小到大的规则查找变量3.子作用域能够访问父作用域父级作用域无法访问子级作用域JS垃圾回收机制垃圾回收机制(Garbage Collection)简称GCJS中内存的分配和回收都是自动完成的内存在不使用的时候会被垃圾回收器自动回收内存的生命周期JS环境中分配的内存一般有如下生命周期1.内存分配当我们声明变量、函数、对象的时候系统会自动为他们分配内存2.内存使用即读写内存也就是使用变量、函数等3.内存回收使用完毕由垃圾回收器自动回收不再使用的内存说明全局变量一般不会回收关闭页面回收一般情况下局部变量的值不用了会被自动回收掉4.内存泄漏程序中分配的内存由于某种原因程序未释放或无法释放叫做内存泄漏拓展—JS垃圾回收机制—算法说明堆栈空间分配区别1.栈操作系统由操作系统自动分配释放函数的参数值、局部变量等基本数据类型放到栈里面。2.堆操作系统一般由程序员分配释放若程序员不释放由垃圾回收机制回收。复杂数据类型放到堆里面。下面介绍两种常见的浏览器垃圾回收算法引用计数法和标记清除法引用计数IE采用的引用计数算法定义“内存不再使用”就是看一个对象是否有指向它的引用没有引用了就回收对象算法1.跟踪记录被引用的次数2.如果被引用了一次那么就记录次数1多次引用会累加3.如果减少一个引用就减1-4.如果引用次数是0则释放内存但它却存在一个致命的问题嵌套引用循环引用)如果两个对象相互引用尽管他们已不再使用垃圾回收器不会进行回收导致内存泄露。因为他们的引用次数永远不会是0。这样的相互引用如果说很大量的存在就会导致大量的内存泄露标记清除法现代的浏览器已经不再使用引用计数算法了。现代浏览器通用的大多是基于标记清除算法的某些改进算法总体思想都是一致的。核心1.标记清除算法将“不再使用的对象”定义为“无法达到的对象”。2.就是从根部在JS中就是全局对象出发定时扫描内存中的对象。凡是能从根部到达的对象都是还需要使用的。3.那些无法由根部出发触及到的对象被标记为不再使用稍后进行回收。闭包概念一个函数对周围状态的引用捆绑在一起内层函数中访问到其外层函数的作用域简单理解闭包内层函数外层函数的变量先看个简单的代码闭包作用封闭数据提供操作外部也可以访问函数内部的变量闭包的基本格式闭包应用实现数据的私有比如我们要做个统计函数调用次数函数调用一次就变量提升变量提升是JavaScript中比较“奇怪”的现象它允许在变量声明之前即被访问仅存在于var声明变量注意1.变量在未声明即被访问时会报语法错误2.变量在var声明之前即被访问变量的值为undefined3.let/const声明的变量不存在变量提升4.变量提升出现在相同作用域当中5.实际开发中推荐先声明再访问变量函数进阶函数提升函数提升与变量提升比较类似是指函数在声明之前即可被调用。总结1.函数提升能够使函数的声明调用更灵活2.函数表达式不存在提升的现象3.函数提升出现在相同作用域当中函数参数1.动态参数arguments是函数内部内置的伪数组变量它包含了调用函数时传入的所有实参总结1.arguments是一个伪数组只存在于函数中2.arguments的作用是动态获取函数的实参3.可以通过f和循环依次得到传递过来的实参2.剩余参数目标能够使用剩余参数剩余参数允许我们将一个不定数量的参数表示为一个数组总结1.是语法符号置于最末函数形参之前用于获取多余的实参2.借助.…获取的剩余实参是个真数组开发中还是提倡多使用剩余参数。展开运算符展开运算符(…)将一个数组进行展开特点不会修改原数组箭头函数重要基本语法语法1基本写法语法2只有一个参数可以省略小括号语法3如果函数体只有一行代码可以写到一行上并且无需写return直接返回值语法4加括号的函数体返回对象字面量表达式箭头函数参数1.普通函数有arguments动态参数2.箭头函数没有arguments动态参数但是有剩余参数…args箭头函数this在箭头函数出现之前每一个新函数根据它是被如何调用的来定义这个函数的thS值非常令人讨厌箭头函数不会创建自己的this,它只会从自己的作用域链的上一层沿用this。箭头函数不会创建自己的this,它只会从自己的作用域链的上一层沿用this。解构赋值数组解构数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法。基本语法1.赋值运算符左侧的[]用于批量声明变量右侧数组的单元值将被赋值给左侧的变量2.变量的顺序对应数组单元值的位置依次进行赋值操作基本语法典型应用交互2个变量对象解构对象解构是将对象属性和方法快速批量赋值给一系列变量的简洁语法基本语法1.赋值运算符左侧的{}用于批量声明变量右侧对象的属性值将被赋值给左侧的变量2.对象属性的值将被赋值给与属性名相同的变量3.注意解构的变量名不要和外面的变量名冲突否则报错普通对象4.对象中找不到与变量名一致的属性时变量值为undefined给新的变量名赋值可以从一个对象中提取变量并同时修改新的变量名数组对象解构多级对象解构遍历数组forEach方法重点forEach()方法用于调用数组的每个元素并将元素传递给回调函数主要使用场景遍历数组的每个元素语法深入对象创建对象三种方式1.利用对象字面量创建对象2.利用new Object创建对象3.利用构造函数创建对象构造函数构造函数是一种特殊的函数主要用来初始化对象使用场景常规的{…}语法允许创建一个对象。比如我们创建了佩奇的对象继续创建乔治的对象还需要重新写一遍此时可以通过构造函数来快速创建多个类似的对象。构造函数语法大写字母开头的函数创建构造函数说明1.使用new关键字调用函数的行为被称为实例化2.实例化构造函数时没有参数时可以省略()3.构造函数内部无需写return,返回值即为新创建的对象4.构造函数内部的return返回的值无效所以不要写return5.new Object() new Date()也是实例化构造函数实例成员与静态成员实例成员通过构造函数创建的对象称为实例对象实例对象中的属性和方法称为实例成员实例属性和实例方法静态成员构造函数的属性和方法被称为静态成员静态属性和静态方法)说明1.静态成员只能构造函数来访问2.静态方法中的this指向构造函数比如Date.now() Math.PI Math.random()内置构造函数ObjectObject是内置的构造函数用于创建普通对象。推荐使用字面量方式声明对象而不是Object构造函数学习三个常用静态方法静态方法就是只有构造函数Objecti可以调用的作用Object.values静态方法获取对象中所有属性值语法注意返回的是一个数组作用Object.assign静态方法常用于对象拷贝语法使用经常使用的场景给对象添加属性ArrayArray是内置的构造函数用于创建数组创建数组建议使用字面量创建不用Array构造函数创建方法作用说明forEach遍历数组不返回数组经常用于查找遍历数组元素filter过滤数组返回新数组返回的是筛选满足条件的数组元素map迭代数组返回新数组返回的是处理之后的数组元素想要使用返回的新数组reduce累计器返回累计处理的结果经常用于求和等reduce基本语法reduce执行过程1.如果没有起始值则上一次值以数组的第一个数组元素的2.每一次循环把返回值给做为下一次循环的上一次值3.如果有起始值则起始值做为上一次值常见的方法的形象的解释补充Array.from()将伪数组转换为真数组String在JavaScript中的字符串、数值、布尔具有对象的使用特征如具有属性和方法之所以具有对象特征的原因是字符串、数值、布尔类型数据是JavaScript底层使用Object构造函数“包装”来的被称为包装类型。补充数字型转化为字符串String()直接转化为字符串num.toString()转化为字符串NumberNumber是内置的构造函数用于创建数值常用方法toFixed()设置保留小数位的长度()括号里面写要保留的位数面向对象编程思想面向过程介绍面向过程就是分析出解决问题所需要的步骤然后用函数把这些步骤一步一步实现使用的时候再一个一个的依次调用就可以了。面向过程就是按照我们分析好了的步骤按照步骤解决问题。面向对象介绍面向对象是把事务分解成为一个个对象然后由对象之间分工与合作。面向对象是以对象功能来划分问题而不是步骤。在面向对象程序开发思想中每一个对象都是功能中心具有明确分工。面向对象编程具有灵话、代码可复用、容易维护和开发的优点更适合多人合作的大型软件项目。面向对象的特性封装性继承性多态性构造函数封装是面向对象思想中比较重要的一部分S面向对象可以通过构造函数实现的封装。同样的将变量和函数组合到了一起并能通过thS实现数据的共享所不同的是借助构造函数创建出来的实例对象之间是彼此不影响的总结1.构造函数体现了面向对象的封装特性2.构造函数实例创建的对象彼此独立、互不影响面向对象编程的特性比如封装性、继承性等可以借助于构造函数来实现前面我们学过的构造函数方法很好用但是存在浪费内存的问题原型原型####原型的相关概念构造函数通过原型分配的函数是所有对象所共享的。JavaScript规定每一个构造函数都有一个prototype属性指向另一个对象所以我们也称为原型对象这个对象可以挂载函数对象实例化不会多次创建原型上函数节约内存我们可以把那些不变的方法直接定义在prototype对象上这样所有对象的实例就可以共享这些方法。构造函数和原型对象中的ths都指向实例化的对象####原型-this指向构造函数和原型对象中的ths都指向实例化的对象constructor属性在哪里每个原型对象里面都有个constructor属性constructor构造函数)作用该属性指向该原型对象的构造函数简单理解就是指向我的爸爸我是有爸爸的孩子对象原型对象都会有一个属性_proto_指向构造函数的prototype原型对象之所以我们对象可以使用构造函数proto原型对象的属性和方原型的存在。三者之间的关系原型对象原型继承继承是面向对象编程的另一个特征通过继承进一步提升代码封装的程度JavaScript中大多是借助原型对象实现继承的特性。原型链基于原型对象的继承使得不同构造函数的原型对象关联在一起并且这种关联的关系是一种链状的结构我们将原型对象的链状结构关系称为原型链原型链-查找规则①当访问一个对象的属性包括方法)时首先查找这个对象自身有没有该属性。②如果没有就查找它的原型也就是_proto指向的prototype原型对象③如果还没有就查找原型对象的原型Object的原型对象)④依此类推一直找到Object为止null)⑤proto_对象原型的意义就在于为对象成员查找机制提供一个方向或者说一条路线⑥可以使用instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上深浅拷贝浅拷贝首先浅拷贝和深拷贝只针对引用类型浅拷贝拷贝的是地址常见方法1.拷贝对象Object.assgin/展开运算符{…obj}拷贝对象2.拷贝数组Array.prototype.concat(或者[..arr]直接赋值和浅拷贝有什么区别直接赋值的方法只要是对象都会相互影响因为是直接拷贝对象栈里面的地址浅拷贝如果是一层对象不相互影响如果出现多层对象拷贝还会相互影响深拷贝首先浅拷贝和深拷贝只针对引用类型深拷贝拷贝的是对象不是地址常见方法1.通过递归实现深拷贝2.lodash/cloneDeep3.通过JSON.stringify()实现函数递归如果一个函数在内部可以调用其本身那么这个函数就是递归函数简单理解函数内部自己调用自己这个函数就是递归函数递归函数的作用和循环效果类似由于递归很容易发生“栈溢出”错误stackoverflow所以必须要加退出条件return.lodash/_.cloneDeep通过JSON.stringify()实现异常处理异常处理是指预估代码执行过程中可能发生的错误然后最大程度的避免错误的发生导致整个程序无法继续运行throw抛异常1.throw抛出异常信息程序也会终止执行2.throw后面跟的是错误提示信息3.Error对象配合throw使用能够设置更详细的错误信息try/catch捕获异常我们可以通过try/catch捕获错误信息浏览器提供的错误信息try试试catch拦住finally最后1.try…catch用于捕获错误信息2.将预估可能发生错误的代码写在try代码段中3.如果try代码段中出现错误后会执行catch代码段并截获到错误信息4.finally不管是否有错误都会执行debugger帮助进行打断点处理thisthis指向普通函数普通函数的调用方式决定了this的值即【谁调用this的值指向谁】普通函数没有明确调用者时this值为window,严格模式下没有调用者时this的值为undefined箭头函数箭头函数中的this与普通函数完全不同也不受调用方式的影响事实上箭头函数中并不存在this!1.箭头函数会默认帮我们绑定外层this的值所以在箭头函数中this的值和外层的this是一样的2.箭头函数中的this引用的就是最近作用域中的this3.向外层作用域中一层一层查找this,直到有this的定义注意情况1在开发中【使用箭头函数前需要考虑函数中this的值】事件回调函数使用箭头函数时this为全局的window因此DOM事件回调函数如果里面需要DOM对象的this,则不推荐使用箭头函数注意情况2同样由于箭头函数this的原因基于原型的面向对象也不推荐采用箭头函数总结1.函数内不存在this,沿用上一级的2.不适用构造函数原型函数dom事件函数等等3.适用需要使用上层this的地方4.使用正确的话它会在很多地方带来方便后面我们会大量使用慢慢体会公改变thisJavaScript中还允许指定函数中this的指向有3个方法可以动态指定普通函数中this的指向call()apply()bind()call()-了解使用call方法调用函数同时指定被调用函数中this的值语法fun.call(thisArg,arg1,arg2,…)thisArg:在fun函数运行时指定的this值arg1,arg2:传递的其他参数返回值就是函数的返回值因为它就是调用函数apply()-理解使用apply方法调用函数同时指定被调用函数中this的值语法fun.apply(thisArg,[argsArray])thisArg:在fun函数运行时指定的this值argsArray:传递的值必须包含在数组里面返回值就是函数的返回值因为它就是调用函数因此apply主要跟数组有关系比如使用Math.ma()求数组的最大值求数组最大值bind()-重点bind()方法不会调用函数。但是能改变函数内部this指向语法fun.bind (thsArg,argl,arg2,…)thisArg:在fun函数运行时指定的this值arg1,arg2:传递的其他参数返回由指定的ths值和初始化参数改造的原函数拷贝(新函数)因此当我们只是想改变this指向并且不想调用这个函数的时候可以使用bid,比如改变定时器内部的this指向.call apply bind总结相同点都可以改变函数内部的this指向.区别点call和apply会调用函数并且改变函数内部this指向.call和apply传递的参数不一样call传递参数aru1,aru2形式apply必须数组形式[arg]bind不会调用函数可以改变函数内部this指向.主要应用场景call调用函数并且可以传递参数appy经常跟数组有关系.比如借助于数学对象实现数组最大值最小值bind不调用函数但是还想改变this指向.比如改变定时器内部的this指向.防抖(debounce防抖单位时间内频繁触发事件只执行最后一次使用场景搜索框搜索输入。只需用户最后一次输入完再发送请求手机号、邮箱验证输入检测防抖的实现方式1.lodash提供的防抖来处理2.手写一个防抖函数来处理节流-throttle节流单位时间内频繁触发事件只执行一次高频事件鼠标移动mousemove、页面尺寸缩放resize、滚动条滚动scroll等等实现方式1.lodash提供的节流函数来处理2.手写一个节流函数来处理核心思路节流的核心就是利用定时器(setTimeout)来实现①声明一个定时器变量②当鼠标每次滑动都先判断是否有定时器了如果有定时器则不开启新定时器③如果没有定时器则开启定时器记得存到变量里面定时器里面调用执行的函数定时器里面要把定时器清空防抖和节流的区别

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

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

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…