首页 文章 精选 留言 我的

精选列表

搜索[解耦化],共10020篇文章
优秀的个人博客,低调大师

从算法到落地:AI个人形象分析系统技术全解

最近两年,AI形象分析类小程序在C端市场增长迅速。用户上传一张自拍,系统自动输出脸型诊断、肤色分析、发型匹配、穿搭建议,甚至附带一段幽默犀利的“颜值锐评”。作为开发者,我在复现这条技术链路的过程中,拆解了市面上几款主流产品的实现方案。本文将以腾讯云架构为基础,从算法选型到工程部署,完整还原一套AI个人形象分析系统的搭建过程。

优秀的个人博客,低调大师

5G手机的“n”烦恼,全频段支持何时解

【金融特辑】光大银行科技部DBA女神带你从0到1揭秘MGR 关于5G手机在频段上的烦恼,最被人们记忆深刻的可能莫过于雷军的n79频段论,从而掀起了部分手机厂商在互联网上“恨人有,笑人无”的舆论战。然而,时至今日,5G手机确实仍在遭遇频段不全的烦恼,全球各品牌就算在自己各个产品中的频段支持选择也各不相同。这也造成了一些潜在5G手机消费者的“n”烦恼。 5G手机用户的“n”烦恼 目前,在国际市场中,一些手机最明显的频段缺失在于对毫米波频段支持的不足。近期新发布的新品中,厂商普遍选择顶尖旗舰支持毫米波,标准旗舰不支持的策略。例如最新推出的三星Galaxy S20系列,其中的S20 5G就不支持毫米波频段,而S20 Plus 5G、S20 Ultra 5G却支持n260、n261。索尼的Xperia Pro支持毫米波n260、n261,但Sony Xperia 1 II却不支持。 但有意思的是,2019年在美国首批发售的部分5G手机却选择支持毫米波n260、n261频段,不支持Sub-6GHz频段,最具代表性的是Verizon发售的LG V50 ThinQ 5G、三星Galaxy Note 10 5G,另外还有在美国市场中具有5G开路先锋作用的Moto 5G Mod(5G手机壳)与三星Galaxy S10 5G。 对于国内市场而言,由于目前多数国际版手机对于中国移动的n41、n79还未提供支持,所以中国移动的5G用户在选择5G手机时还只能选择国内版本的手机。相反,已经有中国联通、中国电信的5G用户开始购买韩国版的三星Galaxy S20来使用5G。 另外,国产手机品牌的产品目前也不约而同的暂不支持毫米波频段,这不会对国内的销售产生任何影响,毕竟2021年国内才有可能部署毫米波。但对于欧美日韩地区而言,由于美国已在2019年开始部署毫米波,欧日韩在2020年将部署毫米波,不支持毫米波频段,显然会对于产品在国际市场中的竞争力产生影响。 也就是说,如果消费者想在当下购买一台对各频段完美支持,能够支持未来2年运营商5G网络建设步伐,或走遍天下5G网络都不怕的手机,暂时还并不存在。 硬件支持已无问题 对于这一问题,首先可以确定的是硬件技术上的支持已经不成问题。 目前已经发布的主流机型中,无论是2020年年初发布的小米10系列、三星Galaxy S20系列、索尼Xperia系列,都采用了高通骁龙865+X55的组合。2019年12月份开始陆续发布的红米K30 5G、OPPO Reno 3 Pro 5G、Realme X50 5G这批手机则采用了骁龙765G+X52的组合。无论是X55、X52均可支持2020及2021年运营商5G网络下的Sub-6GHz与毫米波频段。 2019年的骁龙技术峰会上,高通高级副总裁兼移动业务总经理阿力克斯·卡图赞在骁龙865移动平台的发布中就专门强调称:“新发布的骁龙5G移动平台是真正面向全球的5G解决方案。”实际上,与骁龙865移动平台配合的骁龙X55调制解调器及射频系统在发布之初就是一款面向全球所有5G频段及地区的产品。而X52在后来也已被官方证实,同样支持目前全球所有5G频段。 此外,目前与三星Exynos 990相配合的Exynos 5123基带同样支持Sub-6GHz与毫米波频段。 甚至对于未来,2月份刚刚发布的骁龙X60已经开始着眼于如何更好的利用各种各样的5G频段,主打的一大特性就在于支持Sub-6GHz与毫米波频段的载波聚合,并在Sub-6GHz频段下,也可以支持TDD与FDD的载波聚合。从而大大提升5G终端的日常使用速率。 显然,手机支持的频段自然越多越好,硬件技术上也可以实现,那么手机的“n”烦恼到底卡在了哪呢? 产生“n”烦恼的三个原因 也许三星Galaxy S20系列在不同地区版本间的区别上已经给出了第一个原因:运营商。上文中提到的支持n260、n261 的S20 Plus 5G、S20 Ultra 5G为在美国发售的版本,但在韩国版中目前暂未支持毫米波频段,由于去除了毫米波模块的关系,当地的这两款手机也均比美国版轻2g。三星给出的说法为毫米波的选择是根据各国5G网络情况来决定的,这是三星与韩国运营商商议后的结果。 实际上,从上文中列举出的一批仅支持毫米波的频段也不难看出,美国运营商在其中的决定作用同样明显,Verizon清一色的让手机仅支持毫米波,同时也不断在宣传中展示该频段下的超高峰值速率。无独有偶,目前德国电信在美国市场中就在大力推销三星Galaxy S20系列中的S20 5G机型,该机型仅支持Sub-6GHz的特性与德国电信当下的低频段5G策略恰好契合。 不过,这也引出了当下5G手机暂还不能支持全部频段的第二个原因:设计上的取舍。Galaxy S20 5G未支持毫米波频段的最大原因可能来自于较小尺寸和厚度的情况下,毫米波天线不好塞进去。手机的内部空间正在变得寸土寸金,边框更是如此。也许在2021年,当有了更小面积的天线模组供货后,5G手机也能塞下更多,频段支持的更多。 第三个原因也许能从韩国版S20 Plus 5G、S20 Ultra 5G轻的那2g中找到答案,那就是成本。既然当地运营商没有需求,白白装上无疑也是徒增成本,不如干脆不装。 那么,5G手机的“n”烦恼何时才能解呢?也许全球运营商的部署进度将给出答案,2020年,美欧中日韩澳都将建设Sub-6GHz中FDD的5G网络(此前多为TDD)。除了欧日韩将在2020年部署毫米波外,2022年北京冬奥会也将给毫米波的商用形成助推,超高的峰值速率也很利于赛场中新技术的应用。届时,一方面全球运营商将自身的5G网络构建的更加完整,另一方面相关部件在制程、功耗、体积上的技术发展,5G手机的“n”烦恼将有望彻底解决。

优秀的个人博客,低调大师

解DBA之惑:数据库承载能力评估及优化手段

作为DBA,有时会被挑战类似这样的问题: 如果现有业务规模增加10倍、100倍,数据库是否能够支撑? 下个月我们搞大促,数据库这边没问题吧? 计划进行去O工作,代码逻辑不变,数据库从Oracle切换到MySQL,MySQL能支撑业务吗? 服务器采购选型,到底哪款服务器更适合我们呢? 面对诸如上面的这些质疑,DBA应该如何面对? 身为DBA该如何评估现有资源使用情况? 如果现有数据库资源确实无法支撑,又该本着什么原则进行改造呢? 本文是针对上面问题的一些经验总结,供大家参考。 一、评估工作 面对这样的问题,首先要进行评估工作,可遵循下面的步骤: 1、建立性能基线 针对系统运行现状,建立性能基线。将业务指标与性能指标建立起对应关系。这里所说的性能指标包括CPU、MEM、DISK、NET等。在诸多资源中,肯定存在不均衡的情况,短板的资源最有可能成为业务增长后的瓶颈。在具体操作上,可首先确定一个业务高峰时间段,通过监控平台或监控工具收集系统各资源的使用情况。然后依据收集的信息,分析可能的性能短板在哪里。 对于DBA来说,对自己掌管系统的性能使用情况要了然于胸。通过对业务的了解,将业务指标映射到性能指标上,就可以很容易地推断出现有系统可承载的最大业务量。此外,对于可能影响承载业务增长的短板,也会有比较清晰的认识。 一般来说,数据库类的应用是重资源消耗类的应用。对CPU、MEM、DISK、NET等,均有较大的消耗。但由于不同硬件发展水平不均衡,各数据库资源消耗特点也不同,因此需要具体问题具体分析。 下面谈谈我对硬件发展及与数据库关系的一点个人观点: CPU 相对于其他硬件而言,CPU技术发展较快。随着CPU主频提高及多核CPU技术的发展,CPU提供的计算能力往往不会成为系统的性能瓶颈。但我们需要注意的是,有些数据库是无法完全利用CPU的能力(例如MySQL就是这样)。此时,为了充分利用CPU的资源,可以考虑诸如"多实例混跑"的方案,提高CPU利用率。 MEM 随着内存技术的发挥,内存的价格越来越便宜。现在我们在生产环境中,可以见到128、256GB,甚至TB级的内存也不罕见。一般来说,数据库通常会利用内存作为缓冲区,大内存的配置对数据库的性能有着比较明显的提升。此外,数据库自身技术也在适应着大内存的场景,通常采用的策略是划分子池。将管理的单位进一步细分,例如Oracle中的Sub Pool、MySQL中的多instance buffer pool。 NET 随着GigE、10GbE、InfiniBand技术的飞速发展,低延迟、高带宽的服务品质给数据库乃至整个IT系统带来了很多变化。常见的应用领域有: 加速分布式数据库,例如Oracle RAC。 加速大数据处理,例如提升Hadoop MapReduce处理。 存储架构的变革,从Scale-Up向Scale-Out演变。 容灾方案,主备策略… DISK 相对于其他硬件技术发展而言,传统的机械式磁盘是相对而言发展最慢的,其往往也是最容易成为数据库的性能瓶颈。随着闪存技术的横空出世,为存储技术带来的一种变革。下面我们来看看主要性能指标的对比: 从上述指标来看,使用闪存技术后,存储能力大大提高,消除了系统最大的瓶颈。这也是为什么很多DBA都在不同场合,大力推荐使用闪存,其对于数据库性能的提升会带来质的飞跃。但与此同时,我们也应该注意到,传统关系型数据库是按照磁盘IO模型设计的,没有考虑到闪存技术,现在属于软件落后于硬件的阶段;相对而言,闪存技术对于非关系型模型更有优势。 很多基于传统设计的优化理论发生了变化,例如: 索引聚簇因子的问题。这一点是需要我们在考虑数据库优化时,主要注意的。此外,NoSQL的性能优势因为传统数据库结合闪存技术,而变得不明显。需要在架构选择时加以分析。 2、建立业务压力模型 根据业务特征,建立业务压力模型。简单理解就是将业务模拟抽象出来,便于后面进行压力放大测试。要做到这一步,需要对业务有着充分的了解和评估。 下面通过一个小例子说明一下: 这个表格模拟了某个类电商的业务,其包含的主要模块及模块中的主要操作。针对不同的操作其交易复杂度不同 (交易复杂度可理解为执行SQL语句的个数)。根据不同的读写情况,区分是数据读还是数据写。在估算了业务总量(交易量)的情况下,很容易推算出数据操作的量。通过这种方式将业务压力模型转化为数据压力模型。此处的难点在于对业务逻辑的抽象能力及对模块业务量的比例评估。 有了上述概览的表格后,针对每一种业务操作,可细化其操作。最终将其抽象成SQL语句及对应的访问特征。其伪代码可描述为 可依据上述伪代码,编制压力测试代码。通过一些工具调用测试代码,产生模拟测试的压力。例如我经常使用的oradbtest/mydbtest(原阿里楼方鑫的一个测试工具)或sysbench等,都是不错的压力测试工具。 建议企业根据自身情况,整理出自己的业务压力模型。这在系统改造、升级、扩容评估、新硬件选型等多种场合都很有用处。它要比厂商提供的类似TPCC测试报告,更有意义。据我了解,很多规模较大的公司都有比较成熟的压力模型。 3、模拟压力测试 要想考察现有数据库能否承载增长后的业务压力,最好的方式就是模拟压力测试。观察在近似真实的压力下,数据库的表现。重点观察,数据库的承载力变化、主要性能瓶颈等。通常可以有两种方式,一种是从真实环境导流(并可根据需要放大流量,可利用类似TCPCOPY等工具);一种是根据前面整理的业务压力模型,通过压力工具模拟压力。前者适用于已有项目的扩容评估、系统改造评估等,后者适用于新上项目原型方案评估、性能基准测试等场景。 上述模拟压力测试结果中,暴露出的性能瓶颈点,就是我们后面需要着重改进、优化的方向。 二、优化层次及步骤 针对上面的评估结果,来确定后面的改进、优化方案。可遵循如下一些步骤: 1、分析瓶颈点 根据上面的评测结果,分析性能瓶颈点。针对不同瓶颈点,可采取不同的一些策略。有时候性能测试时全流程的,对于一个复杂系统来说,要明确定位到性能瓶颈点比较困难。此时,可借助一些APM工具,量化整个访问路径,协助找到瓶颈。也可以类似上面的做法,做好抽象工作,只对数据库端施加压力,观察数据库行为,判读数据库是否为瓶颈。如判断就是数据库的承载能力不够,可按照不同层次进行考虑。 在整个评估数据库承载能力中,这一步骤是最复杂的、也是最难的一部分。要区分清楚是否是数据库承载能力不足,还是其他组件的问题。即使明确是数据库的问题,也要分清楚是整体or局部的问题;是单一业务功能慢,还是整体都比较慢;是偶尔会慢,还是一直都很慢等等。这些问题的界定有助于后面明确问题层次,采取不同的策略进行解决。 针对数据库承载能力不足,我将常见出现问题进行了层次划分,可简单分为语句级、对象级、数据库级、数据库架构级、应用架构级、业务架构级。不同层次采取的方式也有所不同,下面分别描述一下。 2、层次-语句级 如性能核心问题,只是某条SQL语句的问题,可有针对性地进行优化。这种方式是侵入性比较小的一种优化方式,其影响范围也比较小。下面对比常见的语句级优化方法。说明一下,下面方法已经排除了诸如统计信息不准确等其他因素,仅从SQL语句本身优化方式考虑。 改写SQL 通过改写语句,达到调整执行计划,提高运行效率的目的。这种方式的缺点是需要研发人员修改原代码,然后再进行部署上线的过程。此外,有些使用O/R Mapping工具产生的SQL,无法直接修改语句,也无法使用此方法。 使用Hint 很多种数据库都提供了提示(Hint)的功能。通过这种方式来指定语句的执行过程。这种方式同样需要修改源代码,经历部署上线的过程。此外,这种修改方式还存在适应性较差的问题。因为其指定了特有的执行过程,随着数据规模、数据特征的变化,固化的执行过程可能不是最佳方式了。这种方式实际上是放弃了优化器可能产生的最优路径。 存储概要、SQL概要、计划基线 在Oracle中还内置了一些功能,它们可以固化某一条语句的执行方式,从本质上来讲,其原理和上面使用Hint差不多。其缺点也类似上面。 调整参数 有时也可通过调整某些参数,进而改变语句的执行计划。但是这种方式要注意适用范围,不要在全局使用,避免影响较多的语句。在会话级使用也要控制范围,避免产生较大影响。 3、层次-对象级 如性能核心问题,在SQL层面无法解决,需要考虑对象层面的调整。这种情况要比较慎重,需要充分评估可能带来的风险及收益。一个对象的结构修改,可以涉及到数百条、甚至数千条和此相关语句的执行计划变更。如不做充分测试的情况下,很难保证不出问题。如果是Oracle数据库,可考虑使用SPA评估一下。其他数据库的话,可提前手工收集一下相关语句,模拟修改后重放上述语句,评估性能变化。 1)影响因素 在对象级进行调整,除了考虑对其他语句的性能影响外,还需要考虑其他因素。常见的以下这些: 数据库维护成本 常见的例如索引。通过添加索引,往往可以起到加速查询的目的;但是增加索引,会导致数据DML成本的增加。 运维成本 常见的例如全局分区索引。全局分区索引在进行分区维护动作后,会导致索引失效,需要自动或手动进行维护索引动作。 存储成本 常见的索引,索引结构是数据库中真实占据空间的结构。在以往的一些案例中,甚至出现过索引总大小超过表大小的情况,因此新增时要评估其空间使用。 2)全生命周期管理 这里还有另外一个很重要的概念——“对象全生命周期管理”,简单来说就是对象的生老病死。在很多系统中,对象从新建开始,数据不断增加、膨胀,当数据规模达到一定量级后,各种性能问题就出现了。对一个百万级的表和亿万级的表,其查询性能肯定不能同日而语。因此,在对象设计初期,就要考虑相关的归档、清理、转储、压缩策略,将存储空间的评估与生命周期管理一起考虑。 很多性能问题,在做了数据清理后都迎刃而解。但数据清理往往是需要代价的,必须在设计之初就考虑这个问题。在做数据库评审的时候,除了常规的结构评审、语句评审外,也要考虑这部分因素。 4、层次-数据库级 到了这个层面,问题往往已经比较严重了。一般情况下,数据库的初始配置都是基于其上面运行系统的负载类型进行专门配置的。如果运行一段时间后,出现性能问题,经评估是属于全局性问题的,可以考虑进行数据库级别的调整。但是这种配置往往代价也比较大,例如需要专门的停机窗口操作等。而且这种操作的风险性也比较大,有可能会带来很多不确定因素,因此要慎而又慎。 5、层次-数据库架构级 如性能核心问题,无法在上述层面解决,可能就需要调整数据库架构。常见的例如采取读写分离的访问方式、分库分表存储方式等。这种对应用的侵入性很强了,有些情况下甚至不亚于重构整个系统。 例如,随着业务的发展,系统的数据量或访问量超出了预期,通过单一数据库无法满足空间或性能要求。此时,可能就需要考虑采用一种分库分表策略,来满足这部分的需求。但其改造难度,往往比重新开发一套系统还要大。 比如,我们可能需要一个数据中间层,来屏蔽后面的分库分表细节。这个中间层可能需要完成语句解析、访问路由、数据聚合、事务处理等一系列功能。即使使用了中间层产品,对于应用来说,数据库的功能也会相对“弱化”,应用级代码不得不进行很多的调整来适应这种变化。此外,如何把一个线上正在运行的系统,顺利平稳地迁移到新的结构下,这无疑又是一个给飞驰的跑车换轮胎的问题等等。 如果项目在运行中,出现了数据库架构级的调整,很有可能说明在前期项目设计规划阶段出现了失误,或者对项目的业务预期出现了偏差。因此,这两点一定在初始阶段进行充分的评估,并在设计上保留有充分的“弹性”。 6、层次-应用架构级 有些情况下,单纯依靠数据库是无法解决的,需要综合考虑整个应用架构。在整个系统架构中,数据库往往处于系统的最末端,其扩展性是最差的。因此,在应用架构设计初期,就应该本着尽量不要对数据库产生压力的原则进行设计。或者即使有大的压力,系统可以采取自动降级等方式保证数据库的平稳运行。 常见的例如增加缓存、通过MQ实现削峰填谷等。通过增加缓存,可以大幅度减少对数据库的访问压力,提高整体系统的吞吐能力。引入MQ,则可以将对数据库的压力以“稳态”的形式,向数据库持续施压,而不至于被某个异常高峰压死。 7、层次-业务架构级 最后一种情况是从业务角度进行一些调整。这往往是一种妥协,通过做适当的减法保证系统的整体运行。甚至不排除牺牲一部分用户体验等方式,来满足大部分用户的可用性。这就需要我们的架构师对系统能提供的能力要很清楚,对业务也要有充分的了解。对于承载什么样的业务,及为了承载业务所需要花费的代价成本有充分的认知,才可以做出一些取舍。 这里要避免一些误区,认为技术是“万能”的。技术可以解决一定的问题,但不能解决所有问题,或者解决所有问题的成本代价是难以接受的。这个时候,从业务角度稍作调整,就可以达到“退一步海阔天空”的结果。 作者:韩锋 来源:宜信技术学院

优秀的个人博客,低调大师

面向视频的全新AI架构 —— 阿里云智能视觉技术全解

我们都知道,AI技术正在以可见的速度被应用于各行各业,然而绝大部分业务场景想应用AI技术,都需要算法工程师根据自身业务的标注数据,来进行单独训练,才能打磨出合适的AI模型。如此一来,如何以最低的门槛和成本,实现AI技术落地变成了行业急需解决的问题。 市场上的AI服务非常多,但是在视觉领域,通用的AI服务主要是基于图像的架构来做的,视频时代已经到来,基于图像的AI架构是否还能被广泛应用?阿里云视频云团队专注于视频领域,所以在针对视频的AI处理方面也有独特的思考和实践。3月27日下午,第51期阿里云产品发布会-智能视觉产品隆重发布,阿里云高级计算专场周源针对图像和视频的AI处理有什么不同?团队是如何基于视频构建全新的AI架构?针对AI大量的数据、训练效果不够好、时间与成本消耗大等痛点,他们如何解决等以上问题做了悉数解答。 一、市场上通用的

优秀的个人博客,低调大师

javascript变量对象 函数调用栈 作用域 闭包等细解!

说明 下面代码演示基于window系统chrome浏览器环境,版本号为63.0.3239.132,32位!相关结果可能会有一点出入,请也实际为准! 相关代码调试的过程中查看结果的步骤: 打开浏览器控制台,切换到sources板块,并选择相应的源文件; 在对应的源文件代码左边的行号上打上断点; 然后刷新浏览器,浏览器会在对应打断点的代码出停止执行,此时我们根据需要按f11键一步一步的运行代码,并同时查看代码的调用栈,作用域等情况,主要查看source板块下最右边子板块的Call Stack和Scope项。 相关概念梳理 其实从我自身出发,我觉的如果需要更好地理解变量对象的话,那么需要对以下概念有一个比较基本的理解会更方便些! 函数调用栈 为了理解函数调用栈,我们先写一段代码: function fn1(){ console.log('fn1'); fn2(); }; function fn2(){ console.log('fn2'); }; fn1(); 我们在fn2函数调用的地方打上断点,然后刷新浏览器,查看Call Stack选项,会看到下面的结果: fn1 (anonymous) 此时再按一次f11键,此时Call Stack显示结果如下: fn2 fn1 (anonymous) 这里说明一下,anonymous指代全局匿名调用函数环境,而fn1和fn2分别指代fn1函数作用域和fn2作用域环境。 我们梳理一下浏览器的调用过程:1 js进入全局匿名函数环境,把这个所谓的匿名函数推入调用栈;2 发现此时又调用了fn1,于是把fn1函数推入调用栈,此时fn1在anonymous的上面; 3 紧接着,发现调用了fn2,于是把fn2推入调用栈,于是得到了上面的结果。 如果后续我们继续按f11键调试,会发现Call Stack会依次出现先面的结果: fn2 fn1 (anonymous) fn1 (anonymous) (anonymous) 也就是说最后只剩下了全局匿名函数环境,这里强调一下,anonymous环境将会伴随着程序运行一直存在,除非你关闭了浏览器。 于是我们总结得到这样的结果:存在这样一个调用栈,默认推入一个全局匿名函数在栈底,当此时再调用其它全局函数的时候,会把该函数推入栈,并在anonymous上面,如果该函数内部继续调用了其它函数,那么同样道理,会把其它函数推入栈,放在该函数上面,最后当函数在调用完成的过程中,会依次退出该调用栈,退出的过程中会把权限交给上一层函数,最后又回归了只剩下全局匿名函数环境。于是我们说了这么多,其实这就是函数调用栈! 函数调用栈你可以理解为函数调用前后包含关系:先进后出,后进先出!它描述了代码执行的先后顺序以及当前代码执行控制权限的拥有者关系等。 函数作用域 我们都知道javascript是没有块级作用域的,只有函数作用域,怎么理解?我们看下面的代码: 代码1 for(var k = 0;k<10;k++){ //... }; console.log(k);//输出10 我们发现for循环代码块执行完了之后,依然能得到k的值。再看下面的代码: 代码2 function fn3(){ var a = 'a'; }; fn3(); console.log(a);//报错 a is not defined 我们发现在函数里面定义的变量a,在函数外面是拿不到的,这就是函数作用域能做到的。 函数作用域能让我们定义一些函数内部使用的与外部环境同名的变量而不会跟外部环境冲突,我们用的较多的地方就是即时函数,如下: var a = 'outer'; (function(){ var a = 'inner'; conosle.log(a);//输出inner })(); console.log(a);//输出outer 当然了在es6及后续版本javascript中,我们可以使用let和const标志符来定义块级变量,这里不作讨论! 这里再做一下扩展,作用域中涉及到最多的一个概念就是作用域链,这个是什么意思呢!看下面的代码: let a = 'a'; function fn4(){ let b = 'b'; return a+b; }; let c = fn4(); console.log(c);//输出'ab' 作用域链描述的是一种函数在执行的过程中查找变量的方式,具体来说:函数执行,如果遇到某变量,会首先在自身作用域环境查找改变量,如果不存在,会向上一层作用域查找变量,也就是函数调用栈中当前执行函数的下一层函数环境查找变量,依次类推,直到到全局环境中查找,如果在全局中都没有找到变量的话,那么就会报错! 其实原型链也是一种描述实例属性查找的过程,跟作用域链类似! 闭包 恐怕接触过javascript的开发者,听到最多与其有关的概念就是闭包了。而且网上有很多文章和书籍都对闭包进行了说明,其实我觉的理解闭包并不难哈!我们来看段代码吧: function fn5(){ let a = 0; return function(){ a++; console.log(a); }; }; let fn = fn5(); fn(); 我们在fn调用的地方打一个断点,随后按一次f11键进入fn执行环境,看下Scope项结果,会发现Scope下有一项子项: Closure(fn5) |_ a 我可以明确的告诉你,此时的fn5对于fn来说就是一个闭包(你可以理解是一个环境概念,该环境维护了一些内部返回的匿名函数用到的一些外部变量)! 梳理一下,闭包指得是某个函数调用之后,自身执行环境已不复存在,但返回了一个函数,由于该返回函数内部用到了外部函数里面的一些变量,并又该内部函数又赋值给了其它变量,导致虽然外部函数不存在了,但是它引用的那些外部变量却不能回收的一个环境(闭包)。 闭包用好了,可以保证好多变更的作用域周期得以提升,减少变量命名冲突,但是过多的使用闭包,也会存在内存泄漏的问题,因为你的很多变量都没有被垃圾回收器回收。 进入正题,变量对象 为了让你对变量对象整体有个最初的概念。在详细介绍之前,我对变量对象概念作如此表述:变量对象指函数执行过程中,函数自身用到数据从哪里来的,函数怎么管理这些数据的等等,其实变量对象里面保存了函数在执行过程中所有用到的数据以及某个时刻值等! 时间仓促,后续待更新…… 原文发布时间为:2018年06月21日 原文作者: 掘金 本文来源:掘金如需转载请联系原作者

优秀的个人博客,低调大师

Android Design Support Library全解:Part 1 Floating Action Button 悬浮按钮

Android Design Support Library系列第一弹,悬浮按钮 悬浮按钮(Floating action button ,FAB) 简单来说是一种圆形按钮,其悬浮于UI之上,四周有阴影环绕,可以用于实现一些高级操作,比如添加新的条目,或是为邮件添加附件等等。 FAB1 FAB2 就本质而言,FAB其实就是继承于ImageView的控件,其支持所有ImageView和ImageButton的属性。 FAB继承自ImageView 要使用FAB,首先要添加依赖包: //本文撰写时,最新版本是25.3.1 compile 'com.android.support:design:25.3.1' 第一步: 在layout文件中加入FAB,我们假设已经声明了命名空间xmlns:app=”http://schemas.android.com/apk/res-auto。 <FrameLayout android:id="@+id/layoutInner" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.FloatingActionButton android:id="@+id/btnFloatingAction" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|right" /> </FrameLayout> 需要说明的是,因为经常需要FAB悬浮于整个UI界面,所以一般将其单独放入一个FrameLayout中,FrameLayout会覆盖下面的UI界面,这样便于FAB位置的设置。 FAB属性介绍 背景填充色: 默认情况下,FAB的填充色为style.xml中colorAccent定义的颜色,如有需要可以设置属性**app:backgroundTint **来自定义背景填充色; 尺寸大小:FAB设有三种尺寸,标准尺寸(Normal 56dp),迷你尺寸(Mini 40dp),以及自适应尺寸(基于屏幕大小而变化),用户通过app:fabSize来设定; fabSize 波纹颜色:app:rippleColor属性用来控制当FAB按下后,产生波纹效果的颜色; 阴影尺寸:app:elevation属性用来控制FAB在正常状态下阴影的尺寸,默认6dp; 按下阴影:app:pressedTranslationZ属性用来控制FAB在按下时阴影的打下,默认12dp; 第二步 根据属性的介绍,完善FAB的设置: android:id="@+id/btnFloatingAction" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|right" android:src="@drawable/ic_plus" app:fabSize="normal" app:rippleColor="@android:color/background_dark"/> 第三步 在Activity中设置点击事件: FloatingActionButton btnFab = (FloatingActionButton) findViewById(R.id.btnFloatingAction); btnFab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "Hello FAB!", Toast.LENGTH_SHORT).show(); } }); 和一般的Button的设置点击事件是一样的,使用起来很方面。 需要注意问题 FAB的呈现的效果在Android 4.4 和4.4以上的设备并不相同: Android 5 Android 4.4 通过上面的对比图可以看出来效果的差异,Android 4.4上 FAB会有边距,而起有默认的阴影,但是4.4+设备没有边框和设备。 解决边距 为了结局边框的问题,可以为4.4+设备设置边框距离,而4.4及之前的设备,边距设为0。 values/dimens.xml <dimen name="fab_margin_right">0dp</dimen> <dimen name="fab_margin_bottom">0dp</dimen> values-v21/dimens.xml <dimen name="fab_margin_right">16dp</dimen> <dimen name="fab_margin_bottom">16dp</dimen> 在布局文件中就可以这样设置FAB的边距 <android.support.design.widget.FloatingActionButton ...... ...... android:layout_marginBottom="@dimen/fab_margin_bottom" android:layout_marginRight="@dimen/fab_margin_right"/> 这样设备就会选取符合系统版本的边距值来设置。 解决阴影 为了统一阴影的大小,可以在布局文件中利用app:borderWidth属性,统一设置阴影大小。 <android.support.design.widget.FloatingActionButton ...... ...... app:fabSize="normal" app:borderWidth="0dp" android:layout_marginBottom="@dimen/fab_margin_bottom" android:layout_marginRight="@dimen/fab_margin_right"/> 动画问题 在最初,旋转动画RotateAnimation无法应用在FAB上,但是属性动画出现之后解决了这个问题。 btnFab = (FloatingActionButton) findViewById(R.id.btnFloatingAction); btnFab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(FloatingActionButtonActivity.this, "Hello FAB!", Toast.LENGTH_SHORT).show(); //设置属性动画,旋转 ObjectAnimator animator = ObjectAnimator.ofFloat(btnFab,"rotation",0f,360f); animator.setInterpolator(new FastOutLinearInInterpolator()); animator.setDuration(1000).start(); } }); 更多关于属性动画对内容,请阅读这里 相关参考 https://developer.android.com/reference/android/support/design/widget/FloatingActionButton.html

优秀的个人博客,低调大师

那些年,我们一起用SkyDrive解的那些“急”

冷兵器时代,一封从中国长城到欧洲古堡的信,需要人们花上长达一年左右的时间,历经艰苦、翻山越岭才能送达;“贝尔时代”这种传递速度被提升到了短短的数秒;而如今,一种云存储的工具出现,让我们仅仅需要花上1/10秒的时间点击一下屏幕上的按钮,就能立马和这个星球上任何一个角落的朋友“共享”一切。不仅如此,我们甚至还可以用古人书写《资治通鉴》的万分之一时间,邀约世界上的各种朋友一起用“协作”的方式完成一部历史史诗,而这就是未来云存储的力量! 记者眼中,透过空气传播的照片 实际上,在很多“达人”眼里,个人云存储就像是空气中无线电波,能随时随地将自己所需要的文档送到你面前,或者分享给你需要分享的人。在他们眼里,这个世界早就不应该存在U盘了,更不应该存在存储文件的地理限制。从撰写文案到提交给上司,从抓拍新闻到第一时间传送给报社,从想法诞生到协同完成设计方案,他们都用自己的方式来透过“空气”传递、分享彼此最新创造的价值! 这就像是那些日夜奔波在外的这路名“记”们,在接到爆料后的第一时间里,他们总是出于职业反应地抓上相机,奔向事发地点,并在拍到照片后再奔回公司,将照片拷贝给编辑部的同事。 特别是一旦遇到一些及时性的大展之时,由于需要为正在直播的网站送去自己最新拍摄的大量照片,以往避免不了背水一战的忙碌。但如今,各路名“记”们在出差前,又有了新选择,通过和同事使用微软网盘SkyDrive这种来自微软的个人云存储服务的产品,他们能够极大提升自己的工作效率。 当在会展开幕后,经验老道的记者会在第一时间抓拍到了最值得报道展台。而通常来说,会场会有公共电脑供记者第一时间上传这些照片。实际上,对于他们来说,大可不必繁杂的重复上传照片。用自己的MSN帐号登录上SkyDrive,并将照片统统上传到SkyDrive上之后,仅仅需要点击一个“共享”按钮,文件就能被用不到1/10秒的时间中瞬间共享给同事。由于最近更新的微软网盘SkyDrive还带有了“照片幻灯放映”功能,远在地球另一端的同事,能够像访问Windows文件夹一样,通过“照片幻灯放映”浏览自己需要的照片。 不仅如此,这个神奇的家伙——微软网盘SkyDrive甚至还可以支持摄影记者常用单反相机拍摄的RAW格式照片。这些RAW照片,可以通过SkyDrive上传和浏览,大大方便了正在焦急等待排版的编辑、照排部同事,他们可以流畅的通过SkyDrive筛选到最适合做封面的照片。 除此之外,据说微软网盘SkyDrive还新增加了Internet Explorer 10、Mobile Safari等浏览器对触摸API的支持。对于数码控来说,他们甚至可以在自己的手机或各种Pad之上,用手指滑动来浏览存在SkyDrive上的照片。 分析师恋上,指尖上的“权限分配” 如果你觉得这就是这种革新工具带来的生活便捷,那么你就太“小看”微软网盘SkyDrive了。它的另类“新玩法”必定能让你感到,科技创造的新生活效率。以忙碌著称的投行分析师,就算是和家人渡假时也常会收到同事索要材料的追魂夺命CALL。其实遭遇这种情况也大可不必将老婆和孩子暂时扔到一旁,冲回办公室或者求救其他同事代发文件。 试试使用新版微软网盘SkyDrive中的文件共享功能,它会“自动”帮助你解决这些“烦恼”。这一功能可以将存入SkyDrive文件夹的文档分为私人文档(Documents)和共享文档(Class documents),并允许用户自由的设置文件权限,用自己喜欢的方式共享文件。 更神奇的是,就算是你正在路上,或者没有插上网线的电脑,你也可以使用手机来远程将自己需要递交的文档,指定共享给需要的同事。对于大部分时间都会奔波在机场和机场路上的分析师,只要手机信号尤在,你就可以用Windows Phone或iPhone手机登录SkyDrive,将文件生成链接,并用短信发给指定的同事。出于文件共享的需要,你还可以为接收人设定“只能查看”或“查看并编辑”等权限。 学生酷玩,超市途中的“协同作业” 实际上,微软网盘SkyDrive的酷功能,不仅仅适合与忙碌工作的“白领”,还适合咱们正在读书的大学生。灵感来自于“瞬间”,如果你是在准备自己大四毕业设计的应届生,除了随身携带着一个笔记本用于记录这些来自“瞬间”的灵感之外,你其实还有更好的选择——使用手机访问SkyDrive。很多时候,毕业设计是由多人一组的同学共同完成,所以在获得这些灵感之后,你还需要回到寝室和朋友分享。但现在你和同学有了更加时髦的方法来高效的完成自己的毕业设计。 利用微软网盘SkyDrive中的Office Web App功能,小组内的任何同学能够随时随地的编辑自己毕业设计文档,并可以通过“分享按钮”立马和同学分享自己最新的想法。你甚至还可以给予收到“链接”的同学,在应用程序内部对单个文档进行编辑的权限,一同来完善这份设计。由于SkyDrive还可以与自己经常用的LinkedIn、Facebook、Gmail、Office家族软件应用程序实现无缝连接,你甚至还可以在整个协作中,获得更多志同道合的朋友帮助。 即便是你走在路上,突然灵感到来,你也能通过手机登录SkyDrive,并把自己的灵感“固化”成文字,甚至图片。 实际上,个人云存储这种正在改变我们生活方式的服务,不仅我们生活带来了众多意想不到的方便,它甚至已经开始改变了我们原有的创造能力。在这种毫无限制的“分享世界”中,我们将会以史无前例的速度分享、协作完成任何以往需要多年才能完成的“任务”! 本文如需转载,请用以下方式联系,并注明出自科幻星系 QQ:102927545 MSN:wangk1026@hotmail.com 个人新浪微博欢迎关注:http://weibo.com/sfw科幻星系官方微博:http://weibo.com/khxx

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册