关于javascript:Fighting-Design-由个人开发的-Vue3-前端组件库上手使用简单灵活

一个新的 Vue3 组件库,应用简略,配置灵便,作者是一个集体开发者,值得关注。 对于 Fighting DesignFighting Design 是一款灵便、优质的前端组件库,基于以后风行的 Vue3 + TypeScript + Vite 开发,不便开发者在 Vue3 我的项目中疾速集成。和绝大多数开源的组件库不同,这个我的项目次要由来自杭州的开发者田同学 开发和保护,在最新的一期阮一峰科技周刊中还被举荐了,广受关注。 Fighting Design 的技术个性应用 Vue3 最新个性开发全面基于 Vite,速度够快没有第三方依赖,够纯正提供不同打包模式,兼容不同我的项目反对残缺引入和按需引入,缩小打包体积应用 TypeScript + Template 编写,严格的 TypeScript 类型,全局无 any 类型欠缺的单元测试Fighting Design 开发上手体验Fighting Design 目前提供了数十个前端开发罕用的根底组件,UI 设计颜值在线,设计格调中性耐看,也领有具体的应用文档,上手应用很简略。 反对 pnpm、npm 和 yarn 三种形式装置: 如果不是工程化我的项目,也反对像 Vue 一样,间接在 html 引入 js 的形式应用: Fighting Design 每一个组件都有代码示例,文档编写得也很好,应用非常简单。骨架屏、水印、日历这几个组件做得很不错,很实用。 不过目前的组件都很根底,像表格这种绝对简单的组件还没有,目前也还只是 Beta 版本,不过作者很怠惰,目前这个阶段代码提交很频繁,始终在更新,从往年4月份首次提交至今,曾经初具规模。作者在官网呐喊更多开发者参加保护,如果你也有志愿参加,能够分割作者退出,门槛不高。 收费开源阐明Fighting Design 是一个由集体开发者打造的 Vue3 UI 组件库,整个我的项目基于 MIT 开源协定,任何集体和公司都能够收费下载应用,自2022年4月首次提交代码以来,目前曾经有超过 200 star 了,十分值得关注。 因为 Fighting Design 目前还不是正式版本,不倡议用来作为生产我的项目应用,倡议作为学习进步应用。 ...

November 25, 2022 · 1 min · jiezi

关于javascript:webstorm-通过ssh远程连接另一台服务器开发

提前:1.首先创立一台服务器用户,集体开发集体的代码sudo useradd htl2.sudo usermod -aG sudo htl 给htl用户赋予sudo权限3.将代码上传到服务器4.通过webstorm ssh性能连贯另一台服务器,抉择代码。5.这样就能够在另一台服务器上的代码能够在本人电脑编辑器跑了。

November 24, 2022 · 1 min · jiezi

关于javascript:1121314…1n

转化 分母(1)1/1 1/1 (1)(2)1-1/2 1/2 (2)(3)1-1/2+1/3 1/2+1/3 (2,3)(4)1-1/2+1/3-1/4 1/3+1/4 (3,4)(5) 1/3+1/4+1/5 (3,4,5)(6) 1/4+1/5+1/6 (4,5,6)(7) 1/4+1/5+1/6+1/7 (4,5,6,7)(8) 1/5+1/6+1/7+1/8 (5,6,7,8)function f(n){ let res = 0; for (let i = n; i >= Math.floor(n / 2) + 1; i--) { res += (1 / i); } return res;}

November 24, 2022 · 1 min · jiezi

关于javascript:前端工程化二规范

前言本文属于《前端工程化系列》的规范&标准介绍,该系列次要介绍咱们一整套前端工程化解决方案。文章会由浅入深的来介绍如何实现前端工程化,以及一整套开箱即用的开源前端工程化解决方案。 文章次要面向中小型团队与老手,心愿咱们的这一整套工程化之路和解决思路能够帮忙团队与开发者提效。 Review 规范提交 review 前请务必仔细阅读本人批改的模块和设计到相干业务的影响,不要将未经开发者自查的代码提交 review如有必要请写分明正文,须要做到 review 审核者能清晰了解以后批改的水平如有必要请在 commit 中标注具体哪个需要的开发工作,参考 comment #issue_ident请保障在提交 review 之前运行测试,或实现自测,已缩小反复提交 review 的状况请不要抉择超过 4个 的评审员,过多的人员的评审相对弊大于利评审员的抉择如果能够尽量放弃 2资深 + 1高级,资深程序员能对你的代码提供倡议,高级程序员能从 review 中疾速失去成长和相熟我的项目Code review 相对优先,咱们提倡的准则是当团队中呈现 code review 的时候往往是团队成员实现某项性能须要公布或其余的紧急情况,请放弃在收到 review 的当天半天工夫内优先解决 reviewShow Code 咱们举荐每周在周会上抽出当周最佳 code review 和 bad case,直面问题会让团队中每一个成员疾速成长 分支治理版本治理前后端拆散公布master 分支受到爱护且仅来源于 release 分支release 作为公布分支,且仅承受 daily 分支代码 merge 公布hotfix 可作为紧急公布分支,须要在公布之后 review merge 进 release 分支daily 作为 日常/版本 性能开发应用,每次迭代须要从 master checkout 进去新版本,daily 分支代码来源于 dev 分支的 mergedev 分支从 daily 分支切出可作为迭代内性能多个开发者互相 review Commit 标准能够应用 one-cli 的 cz 命令针对我的项目进行 git-commitizen 的一键配置。手动提交倡议依照如下规定提供每次 commit 信息 ...

November 23, 2022 · 1 min · jiezi

关于javascript:React-为什么重新渲染

更新(从新渲染)是 React 的重要个性 —— 当用户与利用交互的时候,React 须要从新渲染、更新 UI,以响应用户的输出。然而,React 为什么会从新渲染呢?如果不晓得 React 为什么会从新渲染,咱们如何能力防止额定的从新渲染呢? TL; DR状态扭转是 React 树外部产生更新的唯二起因之一。 这句话是 React 更新的公理,不存在任何例外。本文也将会围绕解释这句话开展。为了防止有人抬杠,这句话引入了一些限度定语和关键词: 名词解释「更新」和「从新渲染」在 React 中,「更新」和「从新渲染」是关系严密,然而含意齐全不同的两个词。上面这句话能力正确表白这两个词的正确含意: React 的「更新」蕴含三个阶段:渲染(Render),应用 createElement 或 jsx-runtime 产生全新的 React Element 对象、组装出一颗 React 树;Reconcilation,React Reconciler 比拟 新生成的 React 树 和 以后的 React 树,判断如何用最高效的办法实现「更新」;Commit,操作 Host(如 DOM、Native 等),使新的 UI 出现在用户背后。 大部分开发者会把「更新」和「从新渲染」一概而论,因为在上述三个阶段中,只有「渲染」这一阶段是开发者能够管制的(「Reconcilation」和「Commit」别离由 react-reconciler 和 React Host 管制)。本文接下来的局部中,「从新渲染」一律指代 React 组件在「更新」时的「渲染」阶段,而「更新」则一律指代(从新)渲染、Reconcilation 和 Commit 整个过程。 「React 树」和「React 树外部」React Tree 自身能够在任意时候更新。实际上,如果你已经通过 React 文档学习 React,你在「Hello World」一章就曾经见过这个 Pattern 了: const root = ReactDOM.createRoot(document.getElementById('root'));function tick() { const element = ( <div> <h1>Hello, world!</h1> <h2>It is {new Date().toLocaleTimeString()}.</h2> </div> ); root.render(element); // 如果你是在 React 18 公布以前学习的 React,你可能会用 ReactDOM.render(): // ReactDOM.render(element, document.getElementById('root'));}setInterval(tick, 1000);每秒钟调用一次 ReactDOM 提供的 render 使一整颗 React 树进行了残缺的更新。然而绝大部分时候,你不会更新一整颗 React 树,而是 React 树内的一部分组件(在 React 利用中,你只会调用一次 createRoot().render 或者 hydrateRoot())。 ...

November 23, 2022 · 4 min · jiezi

关于javascript:elementui表单验证动态修改required并且实时更新是否展示报错提示

最近在开发一个性能,一个表单外面有输入框,每个输入框下面有一个switch开关,开启则必填,不开启的话则该输入框的值能够为空。我把校验规定写在了el-form-item下面: <el-form-item label="姓名" prop="name" :rules="[{ required: Number(temp.isName), message: '姓名不能为空'}]"> <el-input v-model.trim="temp.name" show-word-limit maxlength="45" type="text" placeholder="请输出姓名" /> </el-form-item>这样开启和敞开时能够解决表单校验的问题,然而当初会呈现一个问题,当switch开启的时候,我触发了校验,而后再敞开switch,点击确认,然而页面上的报红提醒仍旧存在。尽管这时候校验曾经去掉了,除非触发了输入框的blur事件,能力把报红提醒去掉。 起初查找了文档,发现了clearValidate办法。官网这样解释: 移除表单项的校验后果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验后果。我拿到这个办法监听switch的敞开事件,当switch敞开后去掉对应的表单校验,就能够实时更新页面上的报红提醒了: watch: { // 监听姓名开关敞开时,去掉 "姓名不能为空" 的校验 'temp.isName'(val) { if (val == '0') { this.$refs['dataForm'].clearValidate('name'); } }, },上面是残缺代码: <!DOCTYPE html><html><head> <meta charset="utf-8"> <title>element-ui开发: 选中赠品弹层中的数据并展现在页面上,弹层展现选中状态</title> <!--引入 element-ui 的款式,--> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script> <!-- 引入element 的组件库--> <script src="https://unpkg.com/element-ui/lib/index.js"></script> <style> * { margin: 0; padding: 0; } #app { margin: 100px; } .switch-wrap { position: relative; } .el-switch { position: absolute; top: 10px; left: 50px; } </style></head><body> <div id="app"> <el-form ref="dataForm" :inline="true" label-width="80px" :model="temp" label-position="top"> <div class="switch-wrap"> <el-switch v-model="temp.isName" active-value="1" inactive-value="0"></el-switch> <el-form-item label="姓名" prop="name" :rules="[{ required: Number(temp.isName), message: '姓名不能为空'}]"> <el-input v-model.trim="temp.name" show-word-limit maxlength="45" type="text" placeholder="请输出姓名" /> </el-form-item> </div> </el-form> <el-button type="primary" @click="submitFun">确认</el-button> </div> <script> new Vue({ el: '#app', data() { return { // 表单数据 temp: { isName: "1", name: '' }, } }, watch: { // 监听姓名开关敞开时,去掉 "姓名不能为空" 的校验 'temp.isName'(val) { if (val == '0') { this.$refs['dataForm'].clearValidate('name'); } }, }, methods: { // 赠品弹层点击确认 async submitFun() { await this.$refs.dataForm.validate() console.log(this.temp, '表单数据') }, } }) </script></body></html>

November 22, 2022 · 1 min · jiezi

关于javascript:教育行业数据可视化应用方案与实践

教育行业背景介绍随着信息技术倒退,教育领域中的学习形式、教学模式、教学内容均已产生重大改革,以云计算、人工智能、物联网、大数据等技术的联合,“智慧教育”的需要也变的紧迫,须要围绕“智慧教育”而产生的产品和解决方案也在迅猛发展。 (图片来源于网络) 智慧教育要以教育新基建促成线上线下教育交融倒退,推动教育数字转型、智能降级、交融翻新,撑持教育高质量倒退。教育数字化转型具备重大战略意义,继“施行教育数字化策略口头”被列入《教育部2022年工作要点》。《教育部2022年工作要点》明确提出施行教育数字化策略口头,建设国家智慧教育公共服务平台,须要达到以下指标: 欠缺国家智慧教育公共服务平台摸索数字化条件下的新型教学模式晋升教育大数据的治理能力施行信息技术反对的教育评估改革智慧教育指标要实现两大智慧+教育指标:智慧(数字化)教育,不仅要针对以后教育治理和服务平台提供数据分析和辅助决策,还应依赖“数据技术”的倒退为“数字化”“信息化”人才培养教育进行增强,教育的数字化转型也是职业教育应答数字化时代倒退与挑战的必然选择,更是职业教育全零碎与数字技术深度交融,重塑职业教育新生态的外在需要。 一是在培养目标上,强化对技能人才的数字能力造就二是数字化治理实质是以新兴技术为次要伎俩,以信息数据为外围因素,将数字技术、数字思维利用于职业教育治理全过程智慧教育大数据可视化解决方案是面向教育管理者、教育者、教学者三者参加的利用计划。实现教育治理服务平台:统计教学数据记录,经营数据监控剖析;教育资源服务平台:学校经营治理,数字化校园;智慧学习服务平台:扭转教学、学习、考试形式,造就大数据利用数据型人才。 (智慧教育零碎拆解) 智慧教育现存挑战数字化存在的痛点数据利用与后期规划设计开发脱节短少对立的数据规范与标准数据壁垒重大,跨零碎、跨业务数据获取难教学方式、服务治理不足数据撑持行政治理督办无奈无效落地短少一体化的数字化展现窗口以后教育治理平台存在挑战同时运行的软件品种繁多,对接服务企业更换频繁,造成利用割裂,各自为营,导致了数据鸿沟各个教育机构有本人的业务解决,定制开发耗时耗力,且保护老本大教育机构经营组织无奈获取每项工作进展,无奈实时把握机构的教管服的数据数据无奈实时可视化,智能剖析以后教育者教育对象的各项教育流动的状况,优化教育计划以后教育执行平台存在挑战不足造就大数据业余的课程和工具,未将数字技术与数字思维利用于职业教育过程中对联合职业教育的平台上手门槛高,不易于考生学习应用提供学习、练习、考试于一体的教考零碎开发成本高,性能简单,保护老本高教考零碎的高并发要求须要软件系统具备十分高的稳定性 教育行业数据可视化利用计划智慧教育解决方案目标,须要实现以下需要:1、对立平台,集成联动,可视化智慧,智能响应,进步管理效率2、标准流程,便捷治理实现全校对立治理3、实现教考一体治理4、通过数据可视化剖析,保障教育机构经营剖析5、实现与相干部门的数据共享 智慧教育可视化治理服务平台方案设计智慧教育治理服务平台实现可满足各级教育治理部门应用,实现学生到职工,到经营的全域数据分析和监控。智慧教育治理可视化平台-计划详情1.须要与多种利用零碎数据对接,如关系数据库,时序数据,文档数据等。 关系数据库时序数据库国产数据库文件数据Web JSON 2.智慧教育治理波及的人员应用数量庞杂,角色多样,层级划分明确。基于多级组织架构,实现用户文档拜访及数据权限管控,须要从登录认证、权限管制、数据隔离等多个维度晋升数据应用安全性。用户权限由所属组织与用户角色权限决定,更细粒度的权限管制保障信息安全。 反对单点登录(SSO)与利用零碎用户集成,满足更高的安全性反对动静配置连贯字符串标识符来辨别组织之间的数据库 3.智慧教育治理可视化平台须要满足在不同平台展现和剖析数据,实现多维度的数据监控辅助决策,须要实现在PC端,大屏端,挪动端,电视端的多终端集成与自适应能力。 基于校园物理场景,构建校园的全景精细化三维模型,以校园三维场景为交互核心,以统计列表或图表或曲线等仪表盘的模式,对学校的整体状况进行介绍,以领导视角展示校园重点统计信息,进步校园治理协同效率。Wyn商业智能通过接入3D模型,自定义地图的形式将更加直观地展现和剖析数据,并实现条件可视化 智慧教育测评服务平台数据分析性能-方案设计智慧教育测评服务平台,基于职业教育提供的软件产品和服务实现智慧教育业余认证、教学诊改等指标,实现业余认证、教学诊改大数据业余的课程和工具。实现与现有的教考零碎对立平台,对立用户身份验证。 智慧教育测评服务平台,可能进行大数据课程培训,与职业教育相结合进行数据分析,保障对立用户认证,将设计剖析能力,设计成绩与教考零碎齐全嵌入,可实现教、练、考一体化性能。 实现智慧教育测评服务,须要满足以下外围要点:1.对立用户认证和治理,反对对立的用户身份数据,角色治理,教育机构,根底信息保护。 2.反对集群部署满足高并发测评与考试需要。 3.一套零碎解决所有需要,无需多个利用零碎切换及不同操作和格调体验。 4.简略易用的报表及数据可视化大屏设计零碎,让学员可能轻松上手,实现数据分析,如财务报表,HR治理报表简略易用的数据可视化大屏设计,实现数据整合,指标创立,可视化数据分析展现,造就学生数据分析能力,适应大数据类目课程。 5.通过一套报表工具,实现满足教,考,练数据分析工具,可疾速拖拽实现考试零碎打分及问题报表。 教育行业数据可视化大屏利用场景智慧校园科研治理综合大屏业务介绍:通过3D可视化实现对教育科研综合监管,理解校园以后申请的科研项目、科研成果,参加科研人数,及与内部单干的科研项目类目等信息来掌控整个园区的科研数据,实现我的项目失常执行及时提供保障服务剖析指标:科研概述、科研队伍、科研名人堂、科研项目类目明细数量、科研人员数量、我的项目胜利、畛域胜利、明星院系人员剖析 智慧校园治理综合大屏业务介绍:基于校园物理场景,构建校园的全景三维模型,实现校园园区治理、平安治理、人员治理、科研治理、招生待业信息等综合治理大屏剖析指标:招生待业状况、师资教学质量、学生画像、科研估算、科研投入、我的项目停顿、能耗治理、平安治理 高校治理大数据平台业务介绍:治理高校各院校学生状况及业余学生散布,学生起源以及教务事件解决的综合治理大屏剖析指标:学生整体状况、各院校学生数量、、各学院业余数量、教职工人数、、学生人数、各院校党员数量、学科数量、学术会议、科研人员散布等 成绩表业务介绍:通过报表设计,批量生成学生成绩表,问题打印等表单 拓展浏览详解商业智能“前世今生”,“嵌入式BI”到底是如何产生的? 应用WIX进行商业智能OEM打包 数据可视化剖析工具如何在国内弯道超车迅速崛起百花齐放?

November 22, 2022 · 1 min · jiezi

关于javascript:javascript设计模式代理模式

代理模式在javascript中能够应用Proxy对象,能够更好的去管制一些对象的交互,既然谈到了Proxy,咱们先简略理解一下Proxy到底是干什么的 ProxyProxy是用来创立一个对象的代理,实现对对象的拦挡。比方对象属性的查找、赋值、枚举、函数调用等操作。语法如下 const p = new Proxy(target, handler)// target 要代理的指标对象// handler 对象,对象中定义了对target操作时要执行的一些操作根底应用事例 const handler = { get: function(obj, prop) { return prop in obj ? obj[prop] : 'FE情报局' }}const target = {}const p = new Proxy(target, handler)p.a = 1p.b = undefinedconsole.log(p.a, p.b) // 1, undefinedconsole.log('c' in p, p.c) // false, FE情报局原来的target上也有对应的属性a和b,然而要留神,从 target取值的时候并没有走代理,也就是target.c为undefined,target.a等于1这样咱们能够通过代理来对对象取值进行辨别,比方对于一些不存在的属性,在取值的时候返回null 代理模式其实Proxy就是一个代理模式,代理的是一个指标对象,下面的例子也表明它能够将对象的变动做一层代理,任何操作都须要通过此代理做一些额定的操作你能够将其设想成咱们的抓包工具,网络申请进来或者收回都要通过抓包,对其进行一些批改或者解决再给到服务器或者客户端,这种也被称为代理模式 例子这种模式在咱们的我的项目中具体有什么作用呢?下面咱们提到了,能够将不存在的属性设置为null const handler = { get: function(obj, prop) { return prop in obj ? obj[prop] : null }}const target = {}const p = new Proxy(target, handler)// p.a => null数据验证代理也可能帮咱们进行数据验证,可能让指标对象中的数据放弃纯正,不会有一些意外的状况 ...

November 22, 2022 · 2 min · jiezi

关于javascript:javascript设计模式单例模式

从明天开始,我将间断更新javascript的设计模式,材料起源次要是https://www.patterns.dev/ 这里涵盖了所有的设计模式,次要内容来自对这个网站的翻译加上本人的了解,也是自我学习的过程 前沿设计模式是软件开发的根本组成部分,因为在大型的软件设计过程中,常常会呈现一些设计模式,它能够用来优化咱们一些代码逻辑和解决形式过来的一段时间中,web整个开发体系产生了迅猛的变动,尽管一些设计模式可能曾经没有了对应的价值,然而也有其中的一些设计模式曾经倒退到了解决一些古代问题react置信大家都比拟相熟,在最近一段时间内取得了微小的关注,哦不对,始终以来react都备受关注,从npm包的下载量就能很显著的看进去,react始终稳居几大框架榜首也因为react的风行,传统的设计模式曾经被批改优化,并且创立了新的设计模式,以便于在古代web开发中提供对应的价值,比方react的hook个性,能够代替很多传统设计模式,所以才有了这个专题,心愿可能通过一起学习将设计模式的实现、益处、缺点以及面试通通拿下 单例模式单例示意的是能够实例化一次的类,并且能够全局拜访。这个繁多的实例能够在咱们的应用程序中共享,所以单例模式非常适合管理应用程序中的全局状态咱们看一下单例到底是一个什么样的内容,咱们能够构建一个Counter类,它有以下办法 返回实例(getInstance)返回计数器以后的值(getCount)count值加一(increment)count值减一(decrement) let counter = 0class Counter {getInstance() { return this}getCount() { return counter}increment() { return ++counter}decrement() { return --counter}}尽管上述的性能都实现了,然而这个类实际上是不符合标准的,标准规定的是这个类只能实例化一次,然而下面的代码咱们能够创立很多Counter实例 const counter1 = new Counter()const counter2 = new Counter()console.log(counter1.getInstance() == counter2.getInstance()) // false通过两次实例化的形式之后,获取到的实例并不相等,两个实例只是不同实例的援用 只能一个实例确保咱们只能创立一个实例的方法是创立一个名为instance的变量,在构造函数中,咱们能够在创立实例的时候将实例设置为对实例的援用,而后查看instantce变量是否曾经有值来避免反复实例化,如果曾经实例化,则抛出谬误让用户晓得曾经存在了实例 let counter = 0let instance = nullclass Counter {constructor() { if(instance) { throw new Error("只能有一个Counter实例") }}getInstance() { return this}getCount() { return counter}increment() { return ++counter}decrement() { return --counter}}const counter1 = new Counter();const counter2 = new Counter();// Error: You can only create one instance!这样就不能创立多个实例了 ...

November 21, 2022 · 1 min · jiezi

关于javascript:nodejs-rbac-权限验证匿名普通admin

//中间件 import jwt from "jsonwebtoken";import {resultFail} from "../common/utils";import {SECRET} from "./auth.controller";import {OPTION} from "./auth.controller";import {ADMIN, NORMAL} from "../common/constants";export let verifyAdmin = function (req, resp, next) { try { const token = req.get("authorization").slice("Bearer ".length); jwt.verify(token, SECRET, (error, res) => { if (error) { resp.status(401).json(resultFail(error) ); return; } console.log(OPTION.role) if (OPTION.role===ADMIN){ next(); }else{ return resp.status(401).json(resultFail(('No Permission'))); } }); } catch (e) { return resp.status(401).json(resultFail(e)); }};export let verifyNormal = function (req, resp, next) { try { const token = req.get("authorization").slice("Bearer ".length); jwt.verify(token, SECRET, (error, res) => { if (error) { res.status(401).json(resultFail(error) ); return; } if (OPTION.role===NORMAL){ next(); }else{ res.status(401).json(resultFail(('No Permission'))); } }); } catch (e) { return resp.status(401).json(resultFail(e)); }};管制层接口 ...

November 21, 2022 · 2 min · jiezi

关于javascript:nodejs-后端-token-权限问题

//登录接口 export default class AuthController { static async login(req, res) { try { const { name, password } = req.body; if (!name || typeof name !== "string") { res.status(400).json(resultFail("Bad name format, expected string.")); return; } if (!password || typeof password !== "string") { res.status(400).json(resultFail("Bad password format, expected string.")); return; } let userFromDB = await AuthDAO.getUser(name); if (!userFromDB) { res.status(401).json(resultFail("Make sure your name is correct.")); return; } const user = new AuthUser(userFromDB); if (!(await user.comparePassword(password))) { res.status(401).json(resultFail("Make sure your password is correct.")); return; } user.encoded().then((token) => { let option = { token: token, userName: userFromDB.name, role: userFromDB.privilege } userManager.setCurrentCacheToken(option); res.send(resultSuccess({ auth_token: token, ...user.toJson() })) }); } catch (e) { res.status(400).json(resultFail(e)); } }}//权限调配对应接口 ...

November 21, 2022 · 2 min · jiezi

关于javascript:精读维护好一个复杂项目

当初许多国内互联网公司的我的项目都继续了五年左右,美国老牌公司如 IBM 的我的项目甚至继续保护了十五年,然而这些我的项目却有着截然不同的保护老本,有的公司我的项目运作几年后保护老本仍然与初创期不大,能够放弃较为高效的迭代速度,但有的我的项目甚至改几个文案都会导致线上事变,研发效率变得越来越慢。 依据笔者的教训,尝试总结一些继续保护我的项目变得难以保护的起因,以及如何设计能力保持良好的可维护性。 精读心态如果不真心看待本人的我的项目,其实是很难做到良好可维护性的,所以第一点就是须要一个良好的心态。 作为我的项目管理者,一个我的项目一旦交给一位同学开发,那么就要齐全信赖这位同学的能力,因为实际上你曾经不可能实质性的影响到开发细节了。有人可能感觉好的流程或者预先 CodeReview 能发现一些问题,但这永远是无济于事,比方上面这个例子: 小张接到工作研发透视表,要求这个透视表具备良好的开发体验并做好单测。那怎么样做单测才算是无效的,如何同时保障开发体验呢?不同人会有不同的想法,也会有不同的后果。 有主人翁心态的小张对于一个有肯定教训,又对我的项目真正上心的小张来说,开发过程可能是这样的。 首先上来先写次要性能,比方思考数据模型、绘图技术计划后,决定采纳图形语法形式定义数据结构,在做了一系列高性能前置思考后,疾速做进去了一个原型,蕴含表格的渲染、操作、翻页、解冻等等性能。 但随着需要的深刻,小张发现做到下钻、排序时,不晓得为何影响到了列解冻的性能,而代码架构其实没什么大问题,形象的也很好,次要就是一些细节的代码调用漏掉了,只有补上就立马买通了任督二脉,整套性能再度行云流水了起来。但不晓得下次做树状展现构造时会不会又把之前的性能影响了,这始终是个隐患,于是小张开始思考先把单测加上再持续开发性能。 因为出问题的场景有很小局部是大量操作后偶尔引发的,一般的函数式单测也无奈保障笼罩的全面,因而小张决定做一个单测录制性能,他首先把对表格的所有操作 Action 化,让一套 json 能够形容所有用户操作,而后又在本地开发界面做了一个单测录制性能,即在页面上对表格性能拖拖拽拽时,就会实时生成这套用户操作 json,再把过后页面构造与外部状态记录下来作为比照根据,单测就还原这套 json 并与基准状态做比照就行了。 小张很快录制了很多原子操作的单测,比方表格的各种空数据状态、单行单列渲染、列解冻行解冻;而后又把一些性能混合的场景联合起来,比方列解冻时排序,翻页后进行下钻;最初又把一些随机简单的性能组合在一起,造成一些日常容易出问题的非凡单测 case,比方表格单页后忽然清空数据,再强制解冻第二列,再灌入3列数据并对第2行做排序,再勾销列解冻并翻到第4页。当前每当遇到一个边界 case 时,小张都会把这个问题 case 记录到单测,验证的确运行失败,再进行修复,直到蕴含这个单测在内的所有单测都验证通过后,才算开发实现。 打工人小张对于为了混口饭吃的小张来说,开发过程可能是这样的。 首先上来写次要性能,把各种表格性能做完后,也遇到了一样的边界 case 难题,此时小张原本想 case by case 修复,但又想到 leader 要求他写单测,感觉倒也不坏,就创立了单测目录。 怎么写单测呢?首先小张把遇到的问题修了,毕竟谁也不心愿本人手里的 bug 太多,但至于录到单测就太麻烦了,反正大家也不晓得这个 case,修掉了就再也不会进去了吧,那就只把 leader 要求的几个基本功能单测加上去,看下覆盖率也达到硬性指标就行了。 大团队代码总是容易走向凌乱假如你是 leader,你不晓得本人团队的小张到底是主人翁小张还是打工人小张,希图通过 code review 来对立晋升团队的代码品质,实际上可行吗? 如果可怜遇上了打工人小张,他在 code review 时展现的代码构造就不是能做整体单测的形象,你只能看着单测文件硬提一些比方 “多加一些单测,多思考一些状况” 的倡议,实际上齐全达不到主人翁小张做的成果。 这背地的起因是影响代码品质的因素太多,比方 Action 化,比方各种极其 case 的录入,比方全流程的单测模式,这些对代码来说都是量变,但 code review 时看到的代码就是不够形象,不够 Action 化的,不可能把代码颠覆重写一遍,只能在已有代码根底上提优化倡议,而到这个时候,神仙也没法让打工人小张的代码优化为主人翁小张的,除非颠覆重写。 这就是心态的影响力,能把我的项目做好的细节很多,而且细节之间还是环环相扣的,比方不把代码 Action 化就不不便做整体单测,但如果开发者打一开始就没想好好设计,code review 时又有多少人能想到这一点呢?想到了此时再提可能也为时太晚,所有都已成定局。 这些年笔者看过不少久经历史的代码,因为大公司有大量的开发者保护同一个我的项目,每个人开发时的心态都各有不同,会发现总能看到那些模块是用打工人心态做进去的,而你想彻底优化就只能彻底重写,但碍于我的项目体量太大工夫上不容许,只能沿着打工人思路洋洋洒洒的持续写下去。 ...

November 21, 2022 · 1 min · jiezi

关于javascript:2022我的前端面试总结

Webpack Proxy工作原理?为什么能解决跨域1. 是什么 webpack proxy,即webpack提供的代理服务 根本行为就是接管客户端发送的申请后转发给其余服务器 其目标是为了便于开发者在开发模式下解决跨域问题(浏览器安全策略限度) 想要实现代理首先须要一个两头服务器,webpack中提供服务器的工具为webpack-dev-server 2. webpack-dev-server webpack-dev-server是 webpack 官网推出的一款开发工具,将主动编译和主动刷新浏览器等一系列对开发敌对的性能全副集成在了一起 目标是为了进步开发者日常的开发效率,「只实用在开发阶段」 对于配置方面,在webpack配置对象属性中通过devServer属性提供,如下: // ./webpack.config.jsconst path = require('path')module.exports = { // ... devServer: { contentBase: path.join(__dirname, 'dist'), compress: true, port: 9000, proxy: { '/api': { target: 'https://api.github.com' } } // ... }}devServetr外面proxy则是对于代理的配置,该属性为对象的模式,对象中每一个属性就是一个代理的规定匹配 属性的名称是须要被代理的申请门路前缀,个别为了分别都会设置前缀为/api,值为对应的代理匹配规定,对应如下: target:示意的是代理到的指标地址pathRewrite:默认状况下,咱们的 /api-hy 也会被写入到URL中,如果心愿删除,能够应用pathRewritesecure:默认状况下不接管转发到https的服务器上,如果心愿反对,能够设置为falsechangeOrigin:它示意是否更新代理后申请的 headers 中host地址2. 工作原理 proxy工作原理本质上是利用http-proxy-middleware 这个http代理中间件,实现申请转发给其余服务器举个例子: 在开发阶段,本地地址为http://localhost:3000,该浏览器发送一个前缀带有/api标识的申请到服务端获取数据,但响应这个申请的服务器只是将申请转发到另一台服务器中 const express = require('express');const proxy = require('http-proxy-middleware');const app = express();app.use('/api', proxy({target: 'http://www.example.org', changeOrigin: true}));app.listen(3000);// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar3. 跨域 ...

November 21, 2022 · 8 min · jiezi

关于javascript:三次握手与四次挥的问题怎么回答

在面试中,三次握手和四次挥手能够说是问的最频繁的一个知识点了,我置信大家也都看过很多对于三次握手与四次挥手的文章,明天的这篇文章,重点是围绕着面试,咱们应该把握哪些比拟重要的点,哪些是比拟被面试官给问到的,我感觉如果你能把我上面列举的一些点都记住、了解,我想就差不多了。 三次握手因为在面试中,三次握手是被问的最频繁的面试题,所以本次咱们从面试的角度来解说三次握手当面试官问你为什么须要有三次握手、三次握手的作用、讲讲三次三次握手的时候,我想很多人会这样答复: 首先很多人会先讲下握手的过程: 1、第一次握手:客户端给服务器发送一个 SYN 报文。 2、第二次握手:服务器收到 SYN 报文之后,会应答一个 SYN+ACK 报文。 3、第三次握手:客户端收到 SYN+ACK 报文之后,会回应一个 ACK 报文。 4、服务器收到 ACK 报文之后,三次握手建设实现。 作用是为了确认单方的接管与发送能力是否失常。 这里我顺便解释一下为啥只有三次握手能力确认单方的承受与发送能力是否失常,而两次却不能够: 第一次握手:客户端发送网络包,服务端收到了。这样服务端就能得出结论:客户端的发送能力、服务端的接管能力是失常的。 第二次握手:服务端发包,客户端收到了。这样客户端就能得出结论:服务端的接管、发送能力,客户端的接管、发送能力是失常的。不过此时服务器并不能确认客户端的接管能力是否失常。 第三次握手:客户端发包,服务端收到了。这样服务端就能得出结论:客户端的接管、发送能力失常,服务器本人的发送、接管能力也失常。 因而,须要三次握手能力确认单方的接管与发送能力是否失常。 这样答复其实也是能够的,但我感觉,这个过程的咱们应该要形容的更具体一点,因为三次握手的过程中,单方是由很多状态的扭转的,而这些状态,也是面试官可能会问的点。所以我感觉在答复三次握手的时候,咱们应该要形容的具体一点,而且形容的具体一点意味着能够扯久一点。加分的形容我感觉应该是这样: 刚开始客户端处于 closed 的状态,服务端处于 listen 状态。而后 1、第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 SN(c)。此时客户端处于 SYN_Send 状态。 2、第二次握手:服务器收到客户端的 SYN 报文之后,会以本人的 SYN 报文作为应答,并且也是指定了本人的初始化序列号 ISN(s),同时会把客户端的 ISN + 1 作为 ACK 的值,示意本人曾经收到了客户端的 SYN,此时服务器处于 SYN_REVD 的状态。 3、第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,示意曾经收到了服务端的 SYN 报文,此时客户端处于 establised 状态。 4、服务器收到 ACK 报文之后,也处于 establised 状态,此时,单方以建设起了链接。 ...

November 21, 2022 · 2 min · jiezi

关于javascript:一年前端面试打怪升级之路

Promise是什么?Promise 是异步编程的一种解决方案:从语法上讲,promise是一个对象,从它能够获取异步操作的音讯;从本意上讲,它是承诺,承诺它过一段时间会给你一个后果。promise有三种状态: pending(期待态),fulfiled(胜利态),rejected(失败态) ;状态一旦扭转,就不会再变。发明promise实例后,它会立刻执行。 const PENDING = "pending";const RESOLVED = "resolved";const REJECTED = "rejected";function MyPromise(fn) { // 保留初始化状态 var self = this; // 初始化状态 this.state = PENDING; // 用于保留 resolve 或者 rejected 传入的值 this.value = null; // 用于保留 resolve 的回调函数 this.resolvedCallbacks = []; // 用于保留 reject 的回调函数 this.rejectedCallbacks = []; // 状态转变为 resolved 办法 function resolve(value) { // 判断传入元素是否为 Promise 值,如果是,则状态扭转必须期待前一个状态扭转后再进行扭转 if (value instanceof MyPromise) { return value.then(resolve, reject); } // 保障代码的执行程序为本轮事件循环的开端 setTimeout(() => { // 只有状态为 pending 时能力转变, if (self.state === PENDING) { // 批改状态 self.state = RESOLVED; // 设置传入的值 self.value = value; // 执行回调函数 self.resolvedCallbacks.forEach(callback => { callback(value); }); } }, 0); } // 状态转变为 rejected 办法 function reject(value) { // 保障代码的执行程序为本轮事件循环的开端 setTimeout(() => { // 只有状态为 pending 时能力转变 if (self.state === PENDING) { // 批改状态 self.state = REJECTED; // 设置传入的值 self.value = value; // 执行回调函数 self.rejectedCallbacks.forEach(callback => { callback(value); }); } }, 0); } // 将两个办法传入函数执行 try { fn(resolve, reject); } catch (e) { // 遇到谬误时,捕捉谬误,执行 reject 函数 reject(e); }}MyPromise.prototype.then = function(onResolved, onRejected) { // 首先判断两个参数是否为函数类型,因为这两个参数是可选参数 onResolved = typeof onResolved === "function" ? onResolved : function(value) { return value; }; onRejected = typeof onRejected === "function" ? onRejected : function(error) { throw error; }; // 如果是期待状态,则将函数退出对应列表中 if (this.state === PENDING) { this.resolvedCallbacks.push(onResolved); this.rejectedCallbacks.push(onRejected); } // 如果状态曾经凝固,则间接执行对应状态的函数 if (this.state === RESOLVED) { onResolved(this.value); } if (this.state === REJECTED) { onRejected(this.value); }};理解 this 嘛,bind,call,apply 具体指什么它们都是函数的办法 ...

November 21, 2022 · 10 min · jiezi

关于javascript:从URL输入到页面展现到底发生什么

从开发&运维角度方面来看,总体来说分为以下几个过程: DNS 解析:将域名解析成 IP 地址TCP 连贯:TCP 三次握手发送 HTTP 申请服务器解决申请并返回 HTTP 报文浏览器解析渲染页面断开连接:TCP 四次挥手一、什么是URL?URL(Uniform Resource Locator),对立资源定位符,用于定位互联网上资源,俗称网址。 scheme: // host.domain:port / path / filename ? abc = 123 # 456789 scheme - 定义因特网服务的类型。常见的协定有 http、https、ftp、file, 其中最常见的类型是 http,而 https 则是进行加密的网络传输。host - 定义域主机(http 的默认主机是 www)domain - 定义因特网域名,比方 baidu.comport - 定义主机上的端口号(http 的默认端口号是 80)path - 定义服务器上的门路(如果省略,则文档必须位于网站的根目录中)。filename - 定义文档/资源的名称query - 即查问参数fragment - 即 # 后的hash值,个别用来定位到某个地位二、DNS域名解析在浏览器输出网址后,首先要通过域名解析,因为浏览器并不能间接通过域名找到对应的服务器,而是要通过 IP 地址。 IP 地址IP 地址是指互联网协议地址,是 IP Address 的缩写。IP 地址是 IP 协定提供的一种对立的地址格局,它为互联网上的每一个网络和每一台主机调配一个逻辑地址,以此来屏蔽物理地址的差别。什么是域名解析DNS 协定提供通过域名查找 IP 地址,或逆向从 IP 地址反查域名的服务。DNS 是一个网络服务器,咱们的域名解析简略来说就是在 DNS 上记录一条信息记录。浏览器如何通过域名去查问 URL 对应的 IP 呢?DNS域名解析分为递归查问和迭代查问两种形式,现个别为迭代查问。 ...

November 21, 2022 · 2 min · jiezi

关于javascript:前端开发者也可以懂的基础-System-Design

微信搜寻 【大迁世界】, 我会第一工夫和你分享前端行业趋势,学习路径等等。本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。前阵子在与敌人一起策划的后端开发线上分享会 BESG 有成员分享了 TinyURL 的零碎设计 (System Design),刚好也看到了出名 YouTuber Terry 对于 Google 零碎设计面试的影片,理解到在美国的资讯业,不管你是前端、后端、材料工程师还是 DevOps,System Design 零碎设计简直都是面试时的必考题。 有人可能会感觉,反正那是国外的情况,我在国内找前端的工作,不须要会零碎设计也能够录取吧?是没错,以目前国内的前端业界来看,面试大多是不会考零碎设计的,然而其实学习零碎设计并不仅是为了应酬面试,更是学习如何应酬简单零碎的能力,也是从 Junior 开发者过渡到 Senior 开发者的要害。就算身为前端开发者,也会须要面对越来越简单的零碎,学会根本的零碎设计思维除了能让你更理解零碎的整体架构外,同时也增强在开发时和其余角色沟通与合作的能力。 我是一个刚要进入社会,筹备开始本人第一份正职的菜鸟工程师,次要 focus 在 Web 前端技术,但也热衷于学习后端开发与云端技术。我想透过这篇文章,以本人是前端开发者的角度登程,去介绍我认为前端开发者也该领有的根本零碎设计思维,也就是说次要会介绍零碎设计最表层的元素,而不会去深入探讨每一个技术的深刻实作,指标在广而不在深。 要晓得零碎设计是一门十分十分十分複杂的技术(说了三次,应该理解到底多複杂了),相对不是我这样的菜鸡能够精通的,因而这篇文应该会蛮入门也蛮浅的,次要目标是心愿和我一样刚入行的前端开发者在看完文章后,也能领有最根本的零碎设计思维,除了解决 UI 画面与浏览器相干的眉眉角角外,应该也要了解一个合格的零碎在背地是怎麽运作的。 本篇文章的流程会是这样的,首先我会把我认为零碎设计的重要元素列出来,并对每个元素进行更近一步的介绍,等读者有了大略的认知后,再分享我认为在面对零碎设计时能够採用的思维走向,最初再以一个理论的零碎设计范例依照先前介绍的思维走向来解决问题。 以分散式零碎为设计指标尽管咱们晓得分散式绝对于单机来说简单许多,在单机都解决不好的情况上来碰分散式零碎简直是死路一条,不过单机的 Vertical Scaling 是有侷限性的,并且 Single Point Of Failure 的问题也让零碎充斥危险,要建设一个“牢靠的大型零碎”,採用分散式架构仿佛是无奈防止了。况且在遇到零碎设计面试问题时,通常都会预设要设计的零碎是高流量的,毕竟设计一个只能接受低流量的零碎是毫无意义的,因而本篇文章探讨的零碎设计都会以分散式零碎为出发点。 咱们心愿设计进去的零碎能领有哪些个性?Scalability 可扩展性当零碎遇到的流量慢慢变大时,咱们会心愿零碎的服务器或贮存空间也可能跟著扩大,来防止无奈负荷的情况。 用文言一点的形式来比喻的话,想像明天你跟 4 个敌人约好要出去玩,你们租了 Toyota 的四人座 Vios,不过另外 2 集体看到你们要出去玩,就保持要你们带上他们,当然当初 6 集体是塞不下小小的 Vios 的,你们只好换租能够载 6 人的 Luxgen U6。 这就很像是零碎设计垂直扩大(Vertical Scaling) 的概念,藉由晋升单机 CPU 或内存来晋升效力。然而这样的晋升是有限度的,想像越来越多敌人想跟你们一起出去玩,你说到了 30 集体,你还能够换包游览车,那 300 个呢?(别跟我说包火车)这时可能就得放弃全副人都挤一台车的形式,改为租用多台游览车来载运所有人。这在零碎设计上称作程度扩大(Horizontal Scaling),用多台机器来分流解决单机可能无奈负荷的流量,达到零碎的可扩展性。 ...

November 21, 2022 · 4 min · jiezi

关于javascript:使用Vite搭建Chrome插件项目

前言写了个vite插件,用于构建Chrome Extension MV3我的项目。我的项目已放在github,详情请查看: vite-plugin-crx-mv3 如果对您有帮忙,star反对一下,谢谢~ 性能Chrome扩大页面和注入脚本反对应用vue、react等等;Content_scripts的css配置项反对.scss或.less文件;js配置项反对.js(x)或.ts(x)文件;background.service_worker配置项反对.js或.ts文件;在开发环境,批改content_scripts和background.service_worker之后,content_scripts注入的页面和Chrome扩大程序会主动重载;应用装置 # pnpmpnpm add vite-plugin-crx-mv3 -D# npmnpm install vite-plugin-crx-mv3 -D# yarnyarn add vite-plugin-crx-mv3 -Dvite配置 import { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue' //如果是应用vue开发的,引入相干的插件import crx from 'vite-plugin-crx-mv3'export default defineConfig({ plugins: [ vue(), crx({ manifest: './src/manifest.json' }), ],})demo:https://github.com/Jervis2049... 实现的整体思路先回顾一下,一个根本的Chrome插件我的项目个别有哪些内容: 目录构造 ├─assets //动态资源目录,寄存icon,css等等├─content.js //content_scripts,注入到页面的脚本├─background.js //service_worker, 这是个运行在后盾的脚本├─popup.html //popup弹框├─menifest.json //清单文件menifest.json { "name": "chrome-extension-demo", "description": "A Chrome extension demo.", "version": "1.0.0", "icons": { "16": "assets/icons/icon16.png", "48": "assets/icons/icon48.png", "128": "assets/icons/icon128.png" }, "action": { "default_title": "Hello World", "default_popup": "popup.html" }, "content_scripts": [{ "matches": [ "<all_urls>" ], "js": ["content.js"] }], "background": { "service_worker": "background.js" }, "manifest_version": 3}这其中version, manifest_version,name为必填项。 ...

November 20, 2022 · 1 min · jiezi

关于javascript:在普通对象的方法中使用React-Hooks写-Hook-的和写类组件的都沉默了

在界面编写方面,我十分喜爱 React Hooks + 函数组件的写法。然而在写简单利用的时候,我更喜爱应用面向对象的写法,所以当我用面向对象写法写了一大堆,因为我心愿利用与视图剥离,只在实现的时候才绑定视图,甚至可能把渲染办法换成 Vue 等其余计划,所以没有思考基于 React.Component 的计划来开发。然而等我终于打算渲染进去看成果的时候却犯了难:我不能在类的办法中应用 hooks ,而应用类组件又十分繁琐。1. 首次尝试:应用 React Hooks1.1 间接应用是行不通的最好能够间接在类的办法外面间接应用 Hook ,当然我本人会做一些 Hook 的绑定工作: // 留神这里的 ViewComponent 并非继承至 React.Componentclass Test extends Editor.ViewComponent { render() { const [{ count }, setCount] = useState(this.data); // 应用自定义的事件机制把 setState 和类的 .data 属性关联起来 // 之所以要这样做是因为 Editor.ViewComponent 有本人的属性治理 // 机制,包含大量不应间接影响渲染的货色 useEffect(() => { this.onDataChange(setCount); return () => this.offDataChange(setCount); }, []); return ( <button onClick={this.changeData({ count: this.data.count + 1 })}> 点击次数: {count} </button> ); }}然而任何一个相熟 React Hooks 的人都晓得,React Hooks 必须是在纯函数外面应用,而类组件的 this 自带状态,所以这段代码不能通过编译。 ...

November 20, 2022 · 2 min · jiezi

关于javascript:JavaScript学习笔记一-promise和asyncwait

前言最近我在学习前端相干的常识,没有意识到的一个问题是我用的Ajax是异步的,如上面代码所示: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body><div id = "app"> <h2>{{ product }} X are in stock .</h2> <ul v-for = "product in products" > <li> <input type="number" v-model.number="product.quantity"> {{product.name}} <span v-if = "product.quantity === 0"> 曾经售空 </span> <button @click = "product.quantity += 1"> 增加 </button> </li> </ul> <h2> 总库存 {{ totalProducts}}</h2></div><div> app.products.pop();</div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script> const app = new Vue({ el:'#app', data:{ product:'Boots', products:[ 'Boots', 'Jacket' ] }, computed:{ totalProducts(){ return this.products.reduce((sum,product) => { return sum + product.quantity; },0); } }, created(){ fetch('http://localhost:8080/hello').then(response=> response.json()).then(json => { console.log("0"); this.products = json.products; }) fetch('http://localhost:8080/hello').then(response=> response.json()).then(json => { console.log("1"); }) } })</script></body></html>依照我的了解是应该先输入0,后输入1。但事实上并非如此,因为fetch是异步的,这里的异步咱们能够简略的了解为执行fetch的执行者并不会马上执行,所以会呈现1先在控制台输入这样的状况: ...

November 20, 2022 · 4 min · jiezi

关于javascript:uni-app-H5接入钉钉单点登录

因为最近有一个业务在做钉钉H5的单点登录,遂记录下来1.根底配置1.须要在钉钉后盾配置我的项目2.配置实现之后须要由钉钉开发人员进行审核通过 2.uni app具体实现过程1.引入钉钉JSSDK npm i dingtalk-jsapi --save2.main.js引入 import * as dd from 'dingtalk-jsapi'; // 此形式为整体加载,也可按需进行加载import { isApp } from '@/utils.js';const inDD = isApp()Vue.prototype.indd = inDD;if (inDD) {Vue.prototype.dd = dd;// 禁用iOS Webview弹性成果dd.ready(function () { dd.ui.webViewBounce.disable()})}因为钉钉H5是局部页面// isApp 办法export function isApp () { if (userAgent.includes("DingTalk")) { return true; } else { return false; }}// authorization.vue JS局部 import * as dd from 'dingtalk-jsapi';function getQueryVariable(variable) { let href = window.location.search; let query = href.substring(href.indexOf('?') + 1); let vars = query.split('&'); for (var i = 0; i < vars.length; i++) { let pair = vars[i].split('='); if (pair[0] == variable) { return pair[1]; } } return false;}onShow() { const indd = this.indd; if (indd) { dd.ready(function () { const corpId = getQueryVariable('corpId'); // console.log(corpId, 'corpId'); // console.log(location.href, 'href'); dd.runtime.permission.requestAuthCode({ corpId, // 企业id onSuccess: async (info) => { try { // console.log(info, 'info') // 拿到code之后获取token,而后拿到用户用户信息等 const res = await Api.loginRequest(info.code); // console.log(res, 'res') const token = res?.data; } catch (err) { that.showPage = true; } }, onFail: () => { that.showPage = true; }, }); }); } else { that.showPage = true; } },### 写在最初 ...

November 20, 2022 · 1 min · jiezi

关于javascript:抖音视频去水印小程序

先看成绩演示,间接复制抖音视频到抖抖来去水印小程序上下载无水印视频 本示例接口次要是通过node开发,但剖析思路是相通的。 如何获取无水印视频下载地址? 1、从抖音上复制链接5.15 bAT:/ 复制关上抖音,看看【程序员Jack的作品】世界上最反人类的设计,为什么键盘上字母不是依照AB... https://v.douyin.com/MnB9FVr/ 2、https://v.douyin.com/MnB9FVr/ 复制这个链接在浏览器手机浏览模式下关上 会重定向到另一个地址 将地址中的红色框字符串取出 3、调用抖音获取视频信息的接口,将获取到的字符串传递给接口获取视频信息https://www.iesdouyin.com/web... 4、将返回的视频地址中的playwm改成play就是无水印视频https://aweme.snssdk.com/awem...改成https://aweme.snssdk.com/awem... 5、批改后的url依然会进行重定向,重定向后的url才是最终无水印视频下载地址。 那么开发过程中存在哪些难点呢? 1、Node如何模仿http申请获取信息通过request来模仿http申请1.1 装置和引入依赖 npm install request@2.88.2 --saveconst request = require('request');1.2 发动http申请 static getNoWatermarkUrl(itemId) { return new Promise((resolve, reject)=>{ const api = `${videoInfoApi}${itemId}`; request.get(api, async (err, res) => { if(JSON.parse(res.body).item_list.length) { const noWatermarkUrl = JSON.parse(res.body).item_list[0].video.play_addr.url_list[0]; const linkStr = noWatermarkUrl.replace('playwm', 'play'); const link = await this.getRealNoWatermarkLink(linkStr); resolve({ link, originLink: linkStr }); } else { resolve(''); } }) });}2、Node如何获取重定向后的url通过puppeteer抓取最终重定向后的无水印视频下载地址 ...

November 20, 2022 · 1 min · jiezi

关于javascript:个人记录JS的事件循环机制

js是单线程非阻塞的单线程因为js的主要用途是进行用户交互操做和dom的解决,如果多线程不利于dom解决,会导致dom不晓得解决哪个线程的工作非梗塞应用了event loop事件循环机制执行栈与事件队列执行栈进行工作的解决都是单线程按程序进行的同步解决,如果遇到异步就会先挂起,等执行栈中的工作都执行实现,主线程处于闲暇状态就会来事件队列中进行查看是否有工作,如果有就把第一个放入执行栈中,并执行其中的同步代码宏工作和微工作每次执行栈执行的代码就是一个宏工作(包含每次从事件队列中获取一个事件回调并放到执行栈中执行)

November 20, 2022 · 1 min · jiezi

关于javascript:js原型链图解

参考《你不晓得的JavaScript(上卷)》,依照本人了解做的对象关联关系图解,不保真。 细节重申对象通过原型链(__proto__)查找属性,始终到找到为止;new 的次要作用是创立新对象,其__proto__指向函数的 prototype,以及关联this到新对象;Object.create 创立新对象,并将其__proto__指向旧对象。依图校验function Foo(){}a = new Foo()b = new Foo()c = Object.create(Foo)d = {}Foo.__proto__ === Foo.prototype // falseFoo.prototype === Foo.__proto__ // falseFoo.prototype === a.__proto__ // trueFoo.prototype === b.__proto__ // truea.constructor === Foo // truea.constructor === Foo.prototype // false ,通过原型链找到constructorc.prototype === Foo.prototype // true ,通过原型链找到prototypec.__proto__ === Foo // trueFoo.__proto__ === Function.prototype // trueFoo.__proto__ === Function.__proto__ // trueFoo.__proto__.constructor === Function // trueFunction.prototype === Object.__proto__ // trueFunction.prototype === Object.prototype // falseObject.prototype === d.__proto__ // trueObject.prototype.__proto__ === null // true ...

November 19, 2022 · 1 min · jiezi

关于javascript:明道云在山东移动的落地与应用

本文来自山东挪动项目经理谭孟元,在明道云2022年秋季搭档大会流动演讲,经校对编辑后整顿为演讲精髓。 大家好,我是山东挪动网络部的谭孟元,首先非常感谢明道云提供这个分享平台。明天我分享的主题是《明道云在山东挪动的落地与利用》。 业务详情与IT治理痛点首先讲一下山东挪动的详情,山东挪动是目前山东省内规模最大的通信企业。近年来,山东挪动全力推动国家政策和团体策略落地落实,强抓时机,把握先机,前瞻性推动5G算力新型基础设施的布局,激发算力引擎赋能效应,推动技术创新、利用孵化以及产业单干。咱们从能力利用、成绩、生态等方面,鼎力推动算力资源布局,为千行百业提供规模大、品质高、能能力强、服务优的算力服务。 截止目前,山东挪动的手机用户的规模超过7000万,家庭宽带用户超过1800万,政企物联网连接数超过5800万。山东挪动当初已建成了基站35万座,其中5G基站建成8.3万站,4G基站建成22万站。山东挪动也承当了全省一半以上的5G建设工作,行业领先地位也继续巩固。 去年咱们网络核心负责人赵总给大家分享过,山东挪动在人员转型以及软件开发层面遇到的艰难,咱们这次也简略回顾一下。 四步引进,继续推广去年七月份,山东挪动正式引入明道云,建设了以明道云为外围的无代码的自研开发生态,并造成了一套人员与利用成绩的造就体系。要建设这套体系不容易,咱们分了环境筹备、外部治理、人才培养和成绩推广四步走。 首先是环境方面,咱们在公司资源池中集群部署了一套无代码开发平台。数据不出公司,确保数据安全。治理方面,咱们由省公司对立牵头治理,省公司的各个科室以及分公司各自建设无代码开发小组,每个开发小组外部再由一名组长牵头,进行组内治理。 在人才培养方面,咱们额定器重人员培训的持续性。从去年7月份开始,山东挪动对立发展了十几次培训,总计培训1300余人次;各个分公司也在小范畴发展培训。从上面的图表中能够看出,去年刚引入明道云的时候,咱们就发展了七次培训。到了往年,咱们就重点发展高级开发技巧的培训。除了培训以外,省公司还建设专门的群沟通机制。在日常的利用施行过程中,咱们遇到任何问题、发现的所有开发技巧,都会在群内分享。目前咱们已建成两个群,总人数靠近1000人。 为了坚固造就成绩,省公司也会在每个月和每次培训后发展优良利用成绩评比,从翻新度、成熟度、残缺度三个方面评估。优秀成果会在省公司外部推广,以此激励大家继续欠缺、迭代利用,精益求精。这些数字是咱们平台目前的数据,可见明道云无代码平台在山东挪动外部的应用频率和用户活跃度很高,利用范畴也很广。 接下来,我给大家分享一下山东挪动分公司做的几个优良利用。 家客综合调度平台咱们的家宽保护人员常常须要上门解决用户的故障问题,而故障的起因也形形色色。因为无奈立即把握用户ONU弱光、质差终端等影响宽带应用的信息,员工就难以精准定位用户家宽问题,只能重复上门调试。 用户被频繁打搅,宽带体验没有改善,很容易产生腻烦情绪,在客服平台上反复投诉。而且因为派单规定不够智能化,将同一个小区的工单派发给不同培修人员解决,导致小区用户的问题无奈由一位员工一次性处理完毕。 那么,聊城公司开发的家客综合调度平台是怎么解决这个问题的呢? 首先,在平台建设投诉用户的家宽画像。通过工作流主动整合所有投诉数据、终端设备等信息,造成迷信的大数据画像。下一步,将家宽投诉详细信息主动派发给一线人员。员工即便在路上,也能够间接在手机上接管残缺信息。 第三是对投诉、装机等各类工单进行区域化整合,不便一线人员在同区域内进行集中的解决。最初,零碎会实时主动统计数据,督办工单响应的相干指标。 通过上述工作的落地,咱们分公司优化了装维人员的工作线路,晋升装维效率,一次性解决了同区域的用户问题,让人均日工作量由7.6件晋升到10件。同时咱们也开释了调度人员的人力,进步了用户的投诉满意度。 能力开放平台下面的案例就是一个十分典型的,通过无代码灵便实现数据处理和推送的示范。那么,方才提到投诉工单的设施信息、资源性能以及告警数据,都是如何实时同步到明道云的呢?其实就是利用了咱们打造的能力开放平台。能力开放平台依靠于咱们底层的网管零碎,将网管零碎的能力进行准则化、标准化。通过能力的封装、接入和编排,解决零碎之间网状对接能力复用水平低的问题,达到“能力一点提供,服务全网”的目标。也就是说,咱们能够通过能力开放平台去对接和调用各个底层网管零碎的能力,来实现跨零碎的数据获取和能力生产。目前能力开放平台总共凋谢了四百四十一个能力,包含故障域、资源域、品质域、运维域、编排域、公共根底域。明道云的月均调用量达到了2000万次,是能力开放平台中生产能力最强的平台。咱们当初经常说的研发体系,往往说的就是“无代码+能力凋谢”。因而,能力开放平台也在帮忙明道云疾速融入山东挪动,实现各类利用的落地。 有人会问,针对能力开放平台中临时没有凋谢数据源的数据,明道云是如何获取的呢?咱们看下一个利用。 IDC治理风控资源零碎这个利用是潍坊公司开发的IDC治理风控溯源零碎。互联网数据中心简称IDC,是指电信部门利用已有的标准化的电信专业级的机房环境,向各类团体客户提供大规模、高质量、安全可靠的机柜、机位、端口带宽、IP地址等根底资源租用服务。 IDC的根底管理工作波及的内容面十分宽泛,信息梳理费时费力。咱们通过明道云以及RPA机器人搭建了IDC治理风控溯源零碎之后,实现了IDC明确且规范化的治理。 为什么要用RPA机器人呢?那是因为IDC的一部分数据在另一个零碎里保护,而这个零碎目前还没有凋谢能力到能力开放平台中。所以咱们只能通过RPA机器人,定时从该零碎获取数据,同步到明道云中,实现数据主动获取。 5G垂直行业撑持平台这是咱们烟台公司开发的5G垂直行业撑持平台。以后山东挪动的网络业务次要分为ToC的ToH的网络和面向行业利用的ToB网络。5G垂直行业也是5G专网是基于5G网络衰亡的,面向行业用户的一种网络业务模式。 在开明5G专网的业务的过程中,咱们须要进行业务数据的制作。以前这项工作齐全依赖于人工,准确性难以保障,而且工作量大。同时,因为咱们的MEC主设施均下沉至客户的园区,所以日常很难间接实时治理和监控设施运行状态以及要害性能指标。因而,如何为客户提供定制化的网络撑持计划成为了亟待解决的问题。 那么咱们依靠于明道云,开发了自动化平台。自动化方面,咱们通过工作流实现了全流程自动化,包含客户单的提交、IP地址端口的调配等一系列的性能。同时,数据配置的脚本也通过预置的模板以及业务数据主动生成。 那么智能化方面,咱们通过工作流实现了业务场景的智能辨认。针对用户侧MEC设施的性能指标,咱们也通过能力开放平台,实现了数据实时提取、智能剖析、告诉预警的能力。 目前这个5G垂直行业撑持平台曾经全面利用于烟台公司的5G行业专网建设以及MEC的撑持工作中。累计撑持专网我的项目11个,MEC我的项目3个,推动工作效率、网络品质、经济效益等方面的晋升。 局数据管理平台接下来是菏泽公司开发的局数据管理平台。咱们CMNET(中国移动互联网)日常常常要对数100G、1000G的设施做配置备份、信息提取和数据制作。工作十分繁冗,耗费着大量人力。那么咱们急需一些系统化的工具来解决问题,开释劳动力。 那咱们通过明道云建设了局数据管理平台,实现了实时全量设施的配置备份、批量设施指标的提取、局数据脚本的制作等性能。并且,它能依据这个平台的管制,主动下发局数据配置,那就简直齐全代替了人力。局数据管理平台也是一个十分典型的,明道云加自研的网络运维利用。咱们分公司的开发人员将明道云作为利用数据中心以及控制中心,实现了简单的业务逻辑。那么明道云在山东挪动网络外部推广后,它的开发便捷性、灵活性也吸引着其余的一些部门、公司来应用。 将来瞻望方才分享的几个利用仅仅是冰山一角,咱们还有很多优秀成果,真正带来了生产力的改革。因为工夫关系,咱们临时分享这么多。最初一个局部,咱们讲一下对将来的瞻望。 山东挪动自从去年引入明道云当前,除了翻新利用百花齐放之外,咱们还有更加贵重的播种,就是明道云带来了凋谢翻新的人才生机。尤其是对于近几年入职的新员工,无代码开发平台,带给他们十分好的职场机会。通过无代码开发,他们可能疾速理解咱们的业务流程、痛点,丰盛专业知识,建设起与共事沟通的桥梁,疾速融入个体,播种个体荣誉感,实现自我价值。 最初,我也谈一谈我对平台能力的将来冀望。随着咱们平台内的利用越来越多,因而也期待后续明道云在工作流的并发能力、工作流的隔离能力以及数据批量解决能力等方面逐渐优化。 其次,咱们期待明道云可能加强跨平台数据源的抉择能力,可能给咱们自研能力比拟强的公司更加灵便凋谢的开发体验。第三个,咱们也心愿平台的监控能力继续晋升,可能细化监控的力度,比方在工作流层面提供分钟级的监控能力,对利用、工作流的资源消耗量的监控。 总而言之,咱们期待明道云在将来,可能带来更加稳固、灵便、凋谢的无代码开发体验。以上就是我的分享。感激大家!

November 19, 2022 · 1 min · jiezi

关于javascript:ES6中setTimeout函数的this

ES6中setTimeout函数的this在编程的过程中有同学遇到不太分明ES6中this指向的问题,代码形象如下: function myFunction(){ var mthis = this; setTimeout(()=>{ // this=mthis console.log('setTimeout中的this:', this) },100)}this是什么,是全局上下文window吗?这里须要跟ES5辨别一下。 ES6中箭头函数外部并没有 this,this 会作为变量始终向下级词法作用域查找,直至找到为止。 先看一下几个相干的常识 函数的调用function myFunction(a, b){ return a * b;}myFunction(2, 3)输入后果的是6 以上myFunction函数不属于任何对象。然而在 JavaScript 中,始终存在一种默认的全局对象。 在 HTML 中,默认全局对象是 HTML 页面自身,所有下面的函数“属于”HTML 页面。 在浏览器中,这个页面对象就是浏览器窗口。下面的函数主动成为一个窗口函数。 myFunction() 和 window.myFunction() 是同一个函数。 这是调用函数的常见办法,但并不是一个好习惯。 全局变量、办法或函数很容易在全局对象中产生命名抵触和破绽。 this 关键词在 JavaScript 中,被称为 this 的事物,指的是“领有”以后代码的对象。 this 的值,在函数中应用时,是“领有”该函数的对象。 请留神 this 并不是变量。它属于关键词。您无奈扭转 this 的值。 全局对象作为函数调用函数当不带拥有者对象调用对象时,this 的值成为全局对象。 在 web 浏览器中,全局对象就是浏览器对象。 本例以 this 的值返回这个 window 对象: 示例 var x = myFunction(); // x 将成为 window 对象function myFunction() { return this;}调用一个函数作为一个全局函数,会导致 this 的值成为全局对象。 ...

November 19, 2022 · 2 min · jiezi

关于javascript:明道云在艾默生数字化实践的新进展

本文来自艾默生电气IT经理丁元才,在明道云2022年秋季搭档大会流动演讲,经校对编辑后整顿为演讲精髓。 大家早上好,明天我讲的主题叫《明道云在艾默生数字化实际的新进展》。这个“新进展”刚好符合明道云明天的大会主题——新力量、新心愿。尽管往年中国整体的经济环境如同很乐观,然而我还是心愿大家通过这场大会或者我明天的分享,可能感触到2023年可能会更好。 艾默生的背景我来自于艾默生苏州工厂。艾默生的存在感不像其余美国企业那么强,像可口可乐或者通用电气。因为艾默生产的产品都是面向上游供应商的,就是工业产品的原材料或者核心部件。它并不是针对民用行业的。 艾默生在美国曾经成立了100多年,大略在1970年代进入中国,是改革开放投资中国的第一家美资企业。目前艾默生在中国曾经倒退出二十几家子公司,苏州工厂就是其中之一。苏州工厂就是艾默生在寰球投资中最大的一家海内工厂。艾默生苏州工厂详情 从信息化到数字化作为外企来讲,艾默生在IT方面的投资还是很舍得的,始终在一直地投资。目前苏州工厂的信息化根底建设曾经打得很好,实现ERP全笼罩,所有外围业务都在ERP里运行。 与此同时,咱们的ERP施行老本十分高。2017年之前,咱们还是用老ERP。2017年之后就启用新的ERP。在上新的Oracle ERP之前,咱们曾经建设了各种各样的零碎,还在老ERP上打了很多外围补丁。咱们面临的最大挑战就是大量的信息孤岛造成零碎复杂度很高,难以为继。 上完Oracle之后,咱们的IT建设重点就是以Oracle为ERP外围,逐步完善外围零碎,建设残缺的信息化零碎。只管有了这样的打算,咱们的生产还是面临微小的挑战。 这个跟中国市场有特地大的关系。因为中国市场倒退得特地快,所以咱们要适应变动来一直调整计划。有时候做进去的打算基本赶不上变动,咱们不得不把更多的变量放在打算外面,让打算更灵便,不过这对打算零碎的要求就更高了。 另外咱们在苏州建设了一个很大的研发核心,这个研发核心就有六百多人。这六百多人被分成很多的团队,同时发展很多新产品的研发。那么这十几个团队如何治理研发我的项目呢? 像这样的问题还有很多,咱们认为光讲信息化是不够的。实际上,信息化下一步应该是走数字化。因而,咱们的观点从信息化转变为数字化。 用平台思维解决问题咱们要解决各种各样的IT需要问题,最终解决方案不是去买一个产品或者买一个工具,而是平台建设。因为只有平台能力应答这些挑战,只有平台外面形象进去的货色能力应答咱们在业务上面临的简单问题。所以,咱们缓缓地把明道云当作一个数字化平台来用。也因而,明道云在艾默生的数字化建设中表演了很重要的角色。 咱们正式应用明道云曾经两年,到往年咱们做了一次降级,把它降级为集群版。到目前为止,苏州工厂外部曾经有超过100个利用,咱们也把明道云用在更加深度、有价值的场景里,包含面向外部合作伙伴和上下游供应商凋谢数据共享入口。通过API,让他们给咱们提供数据,实现产业链上下游信息同步。 这是一个路线图,左边是咱们近期倒退的状况。咱们的利用数量在减少,利用的应用成熟度也在进步,利用面在不停推广。 接下来,我跟大家分享三个例子。 车辆预约与离场护送零碎艾默生苏州工厂每天要生产一万多台压缩机,为此每天都有80到100辆供应商卡车送货入厂,还有20多辆专门运输成品的车辆要出厂。要安顿这么多车辆卸货装货,是个十分大的工程。 为此,咱们在明道云上做了一套预约零碎。司机通过明道云预约进场,扫码注销,零碎会通知他在什么时候到哪个卸货平台。对于咱们来讲,明道云搭的车辆预约零碎,只能让司机预约进场,缓解卸货工夫。但在往年四月疫情暴发当前,苏州工厂园区下达政策,要求企业对进入园区的外来车辆做全程跟踪,跟踪的过程要拍照上传到政府网站。政府把信息系统推出来了,随之要求企业必须把数据填上去。 这时候,明道云作为低代码平台的灵活性就体现进去了。咱们收到园区要求后,认真钻研防疫政策的各要点,而后依照要求迅速调整。咱们搭建这套车辆进场预约零碎大略花了三天工夫,再用一天调整零碎,从第四天开始上传数据。咱们能看到,每一步流程都在零碎里有监控,所有现场照片、驾驶员信息、车辆起源地、核酸后果都用明道云采集,再上交到政府网站。 再到起初,园区政府要求所有车辆进园区必须持有通行证。过后全园区一天大略发放4000票,其中2000票车辆是保民生的,只剩下2000辆货车是保生产的,但园区有二万多家企业。艾默生是园区里大量能申请到20张左右通行证的企业,因为咱们每一辆车都监管得十分好。 从四月到六月的整个疫情期间,咱们每天大略有20多辆当地车和60多辆本地车。产能没有因为货运物流问题而受影响,反而放弃全负荷运行。这就是流程迅速变动显著带来的益处。 物流费用自动化核查零碎艾默生作为大规模制造业,物流运输体量特地大,因而外包了物流公司,均匀每天发三四十个单子,提供上百辆货车的货运量。每天的运费在三万到五万元之间,一个月下来就是100万的结算运费。 以前,这些运输环节都靠纸质单据来对接。每到月底,运输公司盘点账单,让咱们付款。咱们要专门派一个人,要花大略一个月的工夫去核查账单,核查无误能力付钱,并且两头过程往往会呈现很多争议。 针对这块问题,咱们就请了明道云的合作伙伴跟咱们单干,搭建了一个物流费用自动化核查零碎。 运输公司每次交付货物给客户后,通过明道云内部门户进入零碎,将签收单回执拍照上传,填写运输费用、收货地址、运输员等信息。随后,零碎会主动依据运输协定里约定的价格,疾速计算运输费用,过程和后果明细都通明清晰。 费用计算的环节搞定了,还有核查工作。咱们的工作人员会将Oracle里的运费运输打算数据导入明道云,由明道云依据预置规定,主动生成核查报表。员工只需查看报表数据即可。这个零碎很受欢迎,不仅是咱们很分明要付多少运费,运输公司也分明,运输公司的老板也十分分明。因为他在运输派单时也怕赔本,放心本人给艾默生的报价是不是低了,所以他也须要失去十分通明的数据。 这套零碎在往年7月份上线,当初曾经运行了两个多月。这一张就是运行以来的效果图,能够显著看到,员工的工作量加重了,数据透明度减少了。 外部开发者的“二次滋生”艾默生外部的第一次培训在2020年。过后咱们刚上线明道云,就立刻请明道云的搭档来做外部培训。应用明道云的两年以来,艾默生外部逐步造就了少量开发者。往年咱们做第二次外部培训,也是为了实现外部开发者的“二次滋生”,造就更弱小的数字化力量。 第一次培训的时候,明道云搭档给咱们上了八节课。这次,咱们先针对性理解外部用户想学什么,再请外部讲师把它精简为五节课。大量的零代码开发者产出大量利用成绩。咱们在开发了100多个利用之后,造成了一套规范的开发流程。这个流程比较简单,但当中最重要、也有争议的一点就是设计开发。任何一个流程都能够依照这个过程走,然而设计开发是个无底洞,因为这外面存在“不通明”——技术人员可能不理解业务,业务人员不理解技术。 当咱们把零代码这个概念通知用户,并告知大家能够本人去开发了。用户的第一反馈是——你不想干活了,对不对?你让我干了,你就能偷懒。 因而,晚期业务人员都比拟回绝学习零代码利用搭建,他们认为这是IT的责任。不过,当咱们做了大量培训和开发出这么多利用之后,有些人开始沉迷进去,并发现:我学会零代码之后,不找IT开发,反而会更快。 我原本有一个做报表工具要找IT做,可能几个月过来了,IT还没交付。要是我下个星期就要用它了呢?怎么办?我只能排队等。然而要是我学会了,就能够迅速把报表做进去,而且成绩能让本人称心。所以,当大家明确“设计开发”不是写代码而是“搭积木”之后,再去亲自体验,就会比拟认可零代码。在“设计开发”里,IT能帮我实现我无奈实现的那局部工作,而个别数据处理的工作我能够本人搞定,效率就进步了。 对于IT而言也有益处。业务人员先用工作表去积淀业务模型,并按需批改到肯定水平后,他们所提交的需要就绝对稳固和清晰了,那么IT接手解决也更间接,防止业务的奇葩想法导致开发失败。 持续开辟明道云的利用边界借助明道云,艾默生外部曾经开发了100多个利用,然而咱们还想持续开辟明道云的利用边界。 对于业务来说,第一个是跟内部合作伙伴持续推动单干。咱们跟物流公司买通的物流运费就是一个胜利案例,有了这个案例作为根底,咱们能够做更多尝试。第二个是向经营部门推广明道云,包含销售、市场部门。 技术方面,咱们想推动明道云与数据仓库的对接,因为咱们曾经在明道云上积攒了大量有价值的数据,期待咱们去整合、利用。把数据推到数据仓库之后,明道云就能够跟ERP分庭抗礼,进行数据分析了。 我的分享就到此结束,谢谢。

November 19, 2022 · 1 min · jiezi

关于javascript:身份证精准校验方法

function checkIdcard(personnumber) { personnumber = personnumber.toUpperCase() // 身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最初一位是校验位,可能为数字或字符X。 if (!(/(^\d{15}$)|(^\d{17}([0-9]|X)$)/.test(personnumber))) { return false } // 校验位依照ISO 7064:1983.MOD 11-2的规定生成,X能够认为是数字10。 // 上面别离剖析出生日期和校验位 var len, re len = personnumber.length if (len == 15) { re = new RegExp(/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/) var arrSplit = personnumber.match(re) // 查看生日日期是否正确 var dtmBirth = new Date('19' + arrSplit[2] + '/' + arrSplit[3] + '/' + arrSplit[4]) var bGoodDay bGoodDay = (dtmBirth.getFullYear() == Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) == Number(arrSplit[3])) && (dtmBirth.getDate() == Number(arrSplit[4])) if (!bGoodDay) { return false } else { // 将15位身份证转成18位 // 校验位依照ISO 7064:1983.MOD 11-2的规定生成,X能够认为是数字10。 var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2) var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2') var nTemp = 0; var i personnumber = personnumber.substr(0, 6) + '19' + personnumber.substr(6, personnumber.length - 6) for (i = 0; i < 17; i++) { nTemp += personnumber.substr(i, 1) * arrInt[i] } personnumber += arrCh[nTemp % 11] return true } } if (len == 18) { re = new RegExp(/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/) var arrSplit = personnumber.match(re) // 查看生日日期是否正确 var dtmBirth = new Date(arrSplit[2] + '/' + arrSplit[3] + '/' + arrSplit[4]) var bGoodDay bGoodDay = (dtmBirth.getFullYear() == Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) == Number(arrSplit[3])) && (dtmBirth.getDate() == Number(arrSplit[4])) if (!bGoodDay) { return false } else { // 测验18位身份证的校验码是否正确。 // 校验位依照ISO 7064:1983.MOD 11-2的规定生成,X能够认为是数字10。 var valnum var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2) var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2') var nTemp = 0; var i for (i = 0; i < 17; i++) { nTemp += personnumber.substr(i, 1) * arrInt[i] } valnum = arrCh[nTemp % 11] if (valnum != personnumber.substr(17, 1)) { return false } return true } } return false}

November 19, 2022 · 2 min · jiezi

关于javascript:vue30ts项目中的组件通讯

以下将依据理论业务场景进行剖析,梳理vue3.0+ts我的项目中的父子组件通信。 一、父组件咱们假设咱们有一个这样的父组件Parent.vue,在咱们点击编辑按钮之后弹出咱们的子组件弹窗Model.vue。在应用子组件时,咱们应用了双向绑定visible、参数rowInfo、以及更新办法getSystemList,接下来咱们看下在子组件中咱们怎么做来放弃与父组件的通信。 <template> <a class="ant-btn-link" @click="edit(record)">编辑</a> <system-modal v-model:visible="showAdd" :rowInfo="rowInfo" @getSystemList="getSystemList"></system-modal></template><script setup lang="ts">import { ref, onMounted } from 'vue'import SystemModal from './modal.vue'const showAdd = ref(false)type rowInfoKeys = | 'isOther' | 'appOnlyId' | 'backAddress' | 'connectGateway' | 'secretGateway' | 'zeroTrustGateway'type rowInfoType = Partial<Record<rowInfoKeys, any>>const rowInfo: { value: rowInfoType } = ref({ appOnlyId: '', backAddress: '', connectGateway: [], secretGateway: false, zeroTrustGateway: false,})const edit = (row: any): void => { rowInfo.value = { ...row } showAdd.value = true}//数据更新const getSystemList = () => { //在这里编写你的数据更新代码}</script>咱们的父组件大略长这个样子: ...

November 18, 2022 · 1 min · jiezi

关于javascript:js-把数字用含两位小数位的百分比展示

场景:后端给的是比率值,页面应用百分比展现(蕴含两位小数),保留时再转换成比值,1.展现前*100转换 //把int 型改成了含两位小数的百分比字符型 let rate = (parseFloat(item.rate) *100).toFixed(2) 2.保留时/100 //库中理论存的是:最多含四位小数位的float 型let tmp = (parseFloat(others.rate)/100).toFixed(4)let rate = parseFloat(tmp)

November 18, 2022 · 1 min · jiezi

关于javascript:为什么vue3要选用proxy好处是什么

发问Object.defineProperty()和proxy的区别?为什么vue3要选用proxy,益处是什么?proxyProxy 对象用于创立一个对象的代理,从而实现基本操作的拦挡和自定义(如属性查找、赋值、枚举、函数调用等)。 Proxy的用法,这个大家都晓得 const p = new Proxy(target, handler)分析一下外部实现 ECMAScript 2017 (ECMA-262) 能够看到接管两个参数(target,handler) 如果target是undefined,报错运行ProxyCreate(target, handler)上面是ProxyCreate的实现 排除一下错误处理,外围代码从5开始先创立一个新的空对象p, 设置p对象的外部办法(除了[call]]和[[Construct]])设置为[9.5指定的定义, 而后设置p的call和Construct办法, 再设置外部属性[[ProxyTarget]]和[[ProxyHandler]] 返回对象p 咱们能够用它们拦挡什么?对于对象的大多数操作,JavaScript 标准中有一个所谓的“外部办法”,它形容了最底层的工作形式。例如 [[Get]],用于读取属性的外部办法,[[Set]],用于写入属性的外部办法,等等。这些办法仅在标准中应用,咱们不能间接通过办法名调用它们。 Proxy 捕获器会拦挡这些办法的调用。它们在 proxy 标准 和下表中被列出。 对于每个外部办法,此表中都有一个捕获器:可用于增加到 new Proxy 的 handler 参数中以拦挡操作的办法名称: 对于对象的大多数操作,JavaScript 标准中有一个所谓的“外部办法”,它形容了最底层的工作形式。例如 [[Get]],用于读取属性的外部办法,[[Set]],用于写入属性的外部办法,等等。这些办法仅在标准中应用,咱们不能间接通过办法名调用它们。 Proxy 捕获器会拦挡这些办法的调用。它们在 proxy 标准 和下表中被列出。 对于每个外部办法,此表中都有一个捕获器:可用于增加到 new Proxy 的 handler 参数中以拦挡操作的办法名称: 外部办法Handler 办法何时触发[[Get]]get读取属性[[Set]]set写入属性[[HasProperty]]hasin 操作符[[Delete]]deletePropertydelete 操作符[[Call]]apply函数调用[[Construct]]constructnew 操作符[GetPrototypeOf]]getPrototypeOf[Object.getPrototypeOf[SetPrototypeOf]]setPrototypeOf[Object.setPrototypeOf[IsExtensible]]isExtensible[Object.isExtensible[PreventExtensions]]preventExtensions[Object.preventExtensions[DefineOwnProperty]]defineProperty[Object.defineProperty, Object.defineProperties[GetOwnProperty]]getOwnPropertyDescriptor[Object.getOwnPropertyDescriptor, for..in, Object.keys/values/entries[OwnPropertyKeys]]ownKeys[Object.getOwnPropertyNames, Object.getOwnPropertySymbols, for..in, Object.keys/values/entriesReflectReflect 是一个内建对象,可简化 Proxy 的创立。 后面所讲过的外部办法,例如 [[Get]] 和 [[Set]] 等,都只是规范性的,不能间接调用。 Reflect 对象使调用这些外部办法成为了可能。它的办法是外部办法的最小包装。 ...

November 18, 2022 · 1 min · jiezi

关于javascript:令人头疼的Javascript隐式强制转换

Javascript 的隐式强制只是指 Javascript 试图将意外的值类型强制为预期的类型。因而,您能够在须要数字的中央传递一个字符串,在须要字符串的中央传递一个对象等,它会尝试将其转换为正确的类型。这是最好防止的 Javascript 性能。 3 * "3" //91 + "2" + 1 //121true + true //210 - true //9const foo = { valueOf: () => 2}3 + foo // 54 * foo // 8const bar = { toString: () => " promise is a boy :)"}1 + bar // "1 promise is a boy :)"4 * [] // 04 * [2] // 84 + [2] // "42"4 + [1, 2] // "41,2"4 * [1, 2] // NaN"string" ? 4 : 1 // 4undefined ? 4 : 1 // 1数字表达式中的非数字值字符串每当您在波及以下任一运算符的数字表达式中将字符串作为操作数传递时:-, *, /, %,数字的转换过程相似于对值调用内置Number函数。这非常简单,任何仅蕴含数字字符的字符串都将转换为其等效的数字,但蕴含非数字字符的字符串将返回NaN. 如下图, ...

November 18, 2022 · 3 min · jiezi

关于javascript:前端懒加载和预加载

懒加载和预加载的目标都是为了进步用户的体验,二者行为是相同的,一个是提早加载,另一个是提前加载。懒加载对缓解服务器压力有肯定作用,预加载则会增长服务器前端压力缓存。 懒加载 lazyload懒加载:又叫提早加载、按需加载,当咱们关上一个网页,优先展现的首屏图片就先加载,而其余的图片,等到须要去展现的时候再去申请图片资源。 目标:更好的加载页面的首屏内容,对于含有不少图片的比拟长的网页来讲,可能加载的更快,防止了首次关上时,一次性加载过多图片资源,是对网页性能的一种优化形式。 原理:浏览器解析到img标签的src有值,才会去发动申请,那么就能够让图片须要展现时,才对其src赋值真正的图片地址。 实现代码<!DOCTYPE html><html lang="en"> <head> <meta charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>图片懒加载</title> <style> * { margin: 0; padding: 0; } img { margin: 50px; width: 400px; height: 200px; } </style> </head> <body> <div class="img-container"> <img src="loading.gif" alt="" data-src="1.jpg" class="lazyload" /> </div> <div class="img-container"> <img src="loading.gif" alt="" data-src="2.jpg" class="lazyload" /> </div> <div class="img-container"> <img src="loading.gif" alt="" data-src="3.jpg" class="lazyload" /> </div> <div class="img-container"> <img src="loading.gif" alt="" data-src="4.jpg" class="lazyload" /> </div> <div class="img-container"> <img src="loading.gif" alt="" data-src="5.jpg" class="lazyload" /> </div> <script> const imgs = [...document.querySelectorAll(".lazyload")]; //img元素转换成数组 lazyload(); //初始调用一次 window.addEventListener("scroll", lazyload, false); //监听滚动时也调用lazyload函数,冒泡阶段 //懒加载 function lazyload() { for (let i = 0; i < imgs.length; i++) { const $img = imgs[i]; //每次循环拿到每一个img元素 if (isInVisibleArea($img)) { //判断img元素是否在可视区域内 $img.src = $img.dataset.src; //用data-src替换src属性 imgs.splice(i, 1); //对应该索引的元素删掉 i--; } } } // 判断DOM元素是否在可视区域内,返回true/false function isInVisibleArea($el) { const rect = $el.getBoundingClientRect(); console.log(rect); return rect.bottom > 0 && rect.top < window.innerHeight && rect.right > 0 && rect.left < window.innerWidth; } </script> </body></html>实现细节1 如何加载图片用img的data-src属性寄存真正须要显示的图片的门路,当页面滚动直到图片呈现在可视区域时,将data-src中的图片地址值赋值给src属性值。 ...

November 18, 2022 · 3 min · jiezi

关于javascript:KingDesign-金山云出品的设计系统包含一套支持-vue3-的前端-ui-组件库

金山云的开源组件库更新版本了,设计零碎和开发工具都更欠缺,前端组件库反对 Vue2、Vue3 和 React 。 对于 KingDesign早在两年前,我就介绍了金山云出品的 kpc 这套组件库,当初这套组件库迎来了全新的 2.0 版本,名字也更改为 KingDesign ,整体品质有了很大的晋升,更靠近于 element UI 或 Ant design 这种残缺的设计零碎,在产品研发中,个别用于搭建中后盾管理系统。 KingDesign 由组件、开发、设计资源、⼯具、解决⽅案、设计指南组成,咱们能够用来疾速构建⼀致性强的产品。 全新版本 KingDesign 的个性全新的前端 UI 组件库,交互动效粗疏,蕴含多个罕用的业务组件,反对 Vue2 / Vue3 和 React对立、残缺的设计指南,可用于产品对立设计规范,也提供了实用于 sketch / figma 等设计资源文件,不便设计师和产品经理调用全新公布的收费商用字体:金山云技术体,充斥科技感 KingDesign 上手体验作为国产老牌的软件开发公司,金山云推出的前端组件库这次的品质迎来了很大的晋升,如果要构建的产品设计格调靠近金山云的格调,齐全能够应用这一套设计零碎来疾速搭建。 在设计方面,KingDesign 除了提供 UI 的设计源文件供疾速调用外,官网还搭建了一个以图标、图片为主的资源库 KingVision,一起公布的还有一个金山云技术体这款字体,目测往后资源会越来越多,值得设计师们关注。 KingDesign 的组件格调是金山云的格调,这是一套中性格调的组件,反对主题定制,我很喜爱这些组件的点击动效,可点击的组件再点击后,会有一个淡淡的水波纹成果,反馈十分难受。 KingDesign 还提供了代码编辑器、可编辑文本等不常见但很实用的组件,特地是可编辑文本组件,操作便捷,体验很好。 KingDesign 反对 Vue2 / Vue3 和 React,官网文档有具体的应用办法,比方在Vue3 中应用: 通过 npm 装置 引入 KingDesign 按需引入 收费商用阐明和 1.0 版本的 KPC 一样,KingDesign 同样是基于 MIT 开源协定,任何公司和集体都能够收费下载应用,而金山云技术体也是一款全社会收费商用的艺术字体,下次会重点介绍这一款字体。总的来说,这是一款品质在线的研发零碎,值得咱们关注甚至尝试应用。 ...

November 17, 2022 · 1 min · jiezi

关于javascript:结合实践解读-packagejson

前言平时大家在公司接手一个已有我的项目的时候,首先会看的是什么呢?我的习惯是先看 README.md 和 package.json。 通过 README 理解我的项目是做什么和留神点,通过package.json理解我的项目波及的技术栈和 npm 库等等。 明天就来深刻理解下package.json这个文件,不仅是解释具体字段含意与使用(疏忽局部第三方字段本文就不介绍了),更重要的是想借此扩大总结下波及工作中与社区出名库的一些实际,对咱们本人做开源我的项目也有肯定帮忙。 本文同步于我的 Github 集体博客 常见配置字段name我的项目的名称,该字段决定了你公布的包在 npm 的名字,也就是平时装置库的包名了 npm i 包名。 该字段也是有命名标准的,如下: 名称的长度必须小于或等于 214 个字符,不能以.和_结尾。不要应用空格、<>、[]、{}、|、\、^、% 等。不能应用大写字母命名如果要公布到 npm 上,名称不能和社区已有的反复,能够应用npm view命令查问,或间接上npm查。比方随机想一个包名,jacky-summer-utilsnpm view jacky-summer-utils# 报 404,证实该名称可用npm ERR! code E404除了惯例命名,咱们还会见到社区有@结尾的命名,格局如:@[scope]/[name] 例子:@ant-design/icons、@babel/preset-env,这代表一个组织下的库。 如果你也想应用这样的构造,比方用本人名字@结尾的话,须要在本人 npm 上建设组织(Add Organization),不这么做的话包名带@则公布时会不通过。 比方我创立了个组织 @summer-toolkit,包名是config,则我的这个包和name值就命名为 @summer-toolkit/config "name": "@summer-toolkit/config"version我的项目版本号,当公布 npm 包时name和version这两个字段是必须的,两个独特形成惟一的我的项目标识,通过更改 version 来对你的 npm 包进行公布更新。 "version": "1.1.0"通常举荐应用 semver 版本控制策略,开源我的项目也通常遵循这个语义化标准 版本格局:主版本号.次版本号.订正号,版本号递增规定如下:主版本号 Major,当你做了不兼容的 API 批改,通常在波及重大性能更新,产生了破坏性变更时会更新此版本号次版本号 Minor,引入了新性能,但未产生破坏性变更,仍然能够向下兼容时会更新此版本号,可了解为 Feature 版本订正号 Patch,修复了一些 bug,也未产生破坏性变更时会更新此版本号,可了解为 Bug Fix当要公布大版本或者外围的性能时,无奈确定该版本性能稳固,可能无奈满足预期的兼容性需要,这个时候就须要通过公布后行版本。后行版本通过会加在版本号的前面,通过-号连贯以.分隔的标识符和版本编译信息: 外部版本(alpha):通常该版本软件的 Bug 较多,须要继续批改公测版本(beta):绝对于 alpha 版已有很大改良,会持续加新个性,修复了较重大的谬误,但仍然存在一些缺点候选版本(rc,即 release candiate):正式版本的候选版本,该版本个别能够说谬误较少了,根本是修复而不是再加新个性了react:16.3.0-alpha.0vue:3.2.34-beta.1、3.0.0-rc.13比方想查看 vue 的历史 Tag 版本,可看到 vue 是比拟严格遵循 semver 版本标准的: ...

November 17, 2022 · 7 min · jiezi

关于javascript:大厂前端面试考什么

async/await 如何捕捉异样async function fn(){ try{ let a = await Promise.reject('error') }catch(error){ console.log(error) }}Promise.rejectPromise.reject = function(reason) { return new Promise((resolve, reject) => reject(reason));}如何进攻 XSS 攻打?能够看到XSS危害如此之大, 那么在开发网站时就要做好进攻措施,具体措施如下: 能够从浏览器的执行来进行预防,一种是应用纯前端的形式,不必服务器端拼接后返回(不应用服务端渲染)。另一种是对须要插入到 HTML 中的代码做好充沛的本义。对于 DOM 型的攻打,次要是前端脚本的不牢靠而造成的,对于数据获取渲染和字符串拼接的时候应该对可能呈现的恶意代码状况进行判断。应用 CSP ,CSP 的实质是建设一个白名单,通知浏览器哪些内部资源能够加载和执行,从而避免恶意代码的注入攻打。CSP 指的是内容安全策略,它的实质是建设一个白名单,通知浏览器哪些内部资源能够加载和执行。咱们只须要配置规定,如何拦挡由浏览器本人来实现。通常有两种形式来开启 CSP,一种是设置 HTTP 首部中的 Content-Security-Policy,一种是设置 meta 标签的形式对一些敏感信息进行爱护,比方 cookie 应用 http-only,使得脚本无奈获取。也能够应用验证码,防止脚本伪装成用户执行一些操作。浏览器渲染过程的线程有哪些浏览器的渲染过程的线程总共有五种: (1)GUI渲染线程 负责渲染浏览器页面,解析HTML、CSS,构建DOM树、构建CSSOM树、构建渲染树和绘制页面;当界面须要重绘或因为某种操作引发回流时,该线程就会执行。 留神:GUI渲染线程和JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保留在一个队列中等到JS引擎闲暇时立刻被执行。 (2)JS引擎线程 JS引擎线程也称为JS内核,负责解决Javascript脚本程序,解析Javascript脚本,运行代码;JS引擎线程始终期待着工作队列中工作的到来,而后加以解决,一个Tab页中无论什么时候都只有一个JS引擎线程在运行JS程序; 留神:GUI渲染线程与JS引擎线程的互斥关系,所以如果JS执行的工夫过长,会造成页面的渲染不连贯,导致页面渲染加载阻塞。 (3)工夫触发线程 工夫触发线程属于浏览器而不是JS引擎,用来管制事件循环;当JS引擎执行代码块如setTimeOut时(也可是来自浏览器内核的其余线程,如鼠标点击、AJAX异步申请等),会将对应工作增加到事件触发线程中;当对应的事件合乎触发条件被触发时,该线程会把事件增加到待处理队列的队尾,期待JS引擎的解决; 留神:因为JS的单线程关系,所以这些待处理队列中的事件都得排队期待JS引擎解决(当JS引擎闲暇时才会去执行); (4)定时器触发过程 定时器触发过程即setInterval与setTimeout所在线程;浏览器定时计数器并不是由JS引擎计数的,因为JS引擎是单线程的,如果处于阻塞线程状态就会影响记计时的准确性;因而应用独自线程来计时并触发定时器,计时结束后,增加到事件队列中,期待JS引擎闲暇后执行,所以定时器中的工作在设定的工夫点不肯定可能准时执行,定时器只是在指定工夫点将工作增加到事件队列中; 留神:W3C在HTML规范中规定,定时器的定时工夫不能小于4ms,如果是小于4ms,则默认为4ms。 (5)异步http申请线程 XMLHttpRequest连贯后通过浏览器新开一个线程申请;检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将回调函数放入事件队列中,期待JS引擎闲暇后执行;Vue通信1.props和$emit2.地方事件总线 EventBus(根本不必)3.vuex(官网举荐状态管理器)4.$parent和$children当然还有一些其余方法,但根本不罕用,或者用起来太简单来。 介绍来通信的形式,还能够扩大说一下应用场景,如何应用,注意事项之类的。什么是原型什么是原型链?<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body></body><script> function Person () { } var person = new Person(); person.name = 'Kevin'; console.log(person.name) // Kevin // prototype function Person () { } Person.prototype.name = 'Kevin'; var person1 = new Person(); var person2 = new Person(); console.log(person1.name)// Kevin console.log(person2.name)// Kevin // __proto__ function Person () { } var person = new Person(); console.log(person.__proto__ === Person.prototype) // true //constructor function Person() { } console.log(Person === Person.prototype.constructor) // true //综上所述 function Person () { } var person = new Person() console.log(person.__proto__ == Person.prototype) // true console.log(Person.prototype.constructor == Person) // true //顺便学习一下ES5得办法,能够取得对象得原型 console.log(Object.getPrototypeOf(person) === Person.prototype) // true //实例与原型 function Person () { } Person.prototype.name = 'Kevin'; var person = new Person(); person.name = 'Daisy'; console.log(person.name) // Daisy delete person.name; console.log(person.name) // Kevin //原型得原型 var obj = new Object(); obj.name = 'Kevin', console.log(obj.name) //Kevin //原型链 console.log(Object.prototype.__proto__ === null) //true // null 示意"没用对象" 即该处不应该有值 // 补充 function Person() { } var person = new Person() console.log(person.constructor === Person) // true //当获取person.constructor时,其实person中并没有constructor属性,当不能读取到constructor属性时,会从person的原型 //也就是Person.prototype中读取时,正好原型中有该属性,所以 person.constructor === Person.prototype.constructor //__proto__ //其次是__proto__,绝大部分浏览器都反对这个非标准的办法拜访原型,然而它并不存在于Person.prototype中,实际上,它 // 是来自与Object.prototype,与其说是一个属性,不如说是一个getter/setter,当应用obj.__proto__时,能够了解成返回了 // Object.getPrototypeOf(obj) 总结: 1、当一个对象查找属性和办法时会从本身查找,如果查找不到则会通过__proto__指向被实例化的构造函数的prototype 2、隐式原型也是一个对象,是指向咱们构造函数的原型 3、除了最顶层的Object对象没有__proto_,其余所有的对象都有__proto__,这是隐式原型 4、隐式原型__proto__的作用是让对象通过它来始终往上查找属性或办法,直到找到最顶层的Object的__proto__属性,它的值是null,这个查找的过程就是原型链</script></html>首屏和白屏工夫如何计算首屏工夫的计算,能够由 Native WebView 提供的相似 onload 的办法实现,在 ios 下对应的是 webViewDidFinishLoad,在 android 下对应的是onPageFinished事件。 ...

November 17, 2022 · 8 min · jiezi

关于javascript:js事件循环与macromicro任务队列前端面试进阶

背景一天惬意的下午。敌人给我分享了一道头条面试题,如下: async function async1(){ console.log('async1 start') await async2() console.log('async1 end')}async function async2(){ console.log('async2')}console.log('script start')setTimeout(function(){ console.log('setTimeout') },0) async1();new Promise(function(resolve){ console.log('promise1') resolve();}).then(function(){ console.log('promise2')})console.log('script end')这个题目次要是考查对同步工作、异步工作:setTimeout、promise、async/await的执行程序的了解水平。(倡议大家也本人先做一下o) 过后因为我对async、await理解的不是很分明,答案错的千奇百怪 :(),就不记录了,而后我就去看文章理了理思路。当初写在上面以供日后参考。 js事件轮询的一些概念这里首先须要明确几个概念:同步工作、异步工作、工作队列、microtask、macrotask 同步工作指的是,在主线程上排队执行的工作,只有前一个工作执行结束,能力执行后一个工作; 异步工作指的是,不进入主线程、而进入"工作队列"(task queue)的工作,期待同步工作执行结束之后,轮询执行异步工作队列中的工作 macrotask 即宏工作,宏工作队列等同于咱们常说的工作队列,macrotask是由宿主环境散发的异步工作,事件轮询的时候总是一个一个工作队列去查看执行的,"工作队列"是一个先进先出的数据结构,排在后面的事件,优先被主线程读取。 microtask 即微工作,是由js引擎散发的工作,总是增加到当前任务队列开端执行。另外在解决microtask期间,如果有新增加的microtasks,也会被增加到队列的开端并执行。留神与setTimeout(fn,0)的区别: setTimeOut(fn(),0)指定某个工作在主线程最早可得的闲暇工夫执行,也就是说,尽可能早得执行。它在"工作队列"的尾部增加一个事件,因而要等到同步工作和"工作队列"现有的事件都解决完,才会失去执行。 总结一下: task queue、microtask、macrotask An event loop has one or more task queues.(task queue is macrotask queue)Each event loop has a microtask queue.task queue = macrotask queue != microtask queuea task may be pushed into macrotask queue,or microtask queuewhen a task is pushed into a queue(micro/macro),we mean preparing work is finished,so the task can be executed now.所以咱们能够失去js执行程序是: ...

November 17, 2022 · 2 min · jiezi

关于javascript:正则手记方法篇

办法篇,JavaScript 中都有哪些操作正则的办法。 RegExp 对象办法办法形容exec检索字符串中指定的值。返回找到的值,并确定其地位。test检索字符串中指定的值。返回 true 或 false。正则.test(字符串)regexp.test(str)办法 regexp.test(str) 查找匹配项,而后返回 true/false 示意是否存在。 let str = "I love JavaScript";// 这两个测试雷同console.log(/love/i.test(str)); // trueconsole.log(str.search(/love/i) != -1); // trueregexp.exec(str)regexp.exec(str) 办法返回字符串 str 中的 regexp 匹配项, 可指定从地位进行搜寻。 基于否具备修饰符 g 其有两种搜寻模式。 (1) 没有修饰符 g,则 regexp.exec(str) 会返回与 第一个匹配项,就像 str.match(regexp) 那样。这种行为并没有带来任何新的货色。 let str = "More about JavaScript at https://javascript.info";let regexp = /javascript/i;console.log(regexp.exec(str));/* [0 : "JavaScript"groups:undefinedindex: 11input :"More about JavaScript at https://javascript.info"] */(2) 有修饰符 g,能够基于 regexp.lastIndex 地位循环搜寻全副。 具体步骤: 调用 regexp.exec(str) 会返回第一个匹配项,并将紧随其后的地位保留在属性 regexp.lastIndex 中。下一次这样的调用会从地位 regexp.lastIndex 开始搜寻,返回下一个匹配项,并将其后的地位保留在 regexp.lastIndex 中。……以此类推。如果没有匹配项,则 regexp.exec 返回 null,并将 regexp.lastIndex 重置为 0。因而,反复调用会一个接一个地返回所有匹配项,应用属性 regexp.lastIndex 来跟踪以后搜寻地位。过来,在将 str.matchAll 办法增加到 JavaScript 之前,会在循环中调用 regexp.exec 来获取组的所有匹配项: ...

November 16, 2022 · 3 min · jiezi

关于javascript:vue中vshow指令与vif指令到底有那些区别又如何使用

v-show指令与v-if指令到底有那些区别?最次要的区别其实在于渲染,用v-show无论绑定的值为true或者false都会渲染dom。如下图在guiplan开发工具中将副标题的显示条件(v-show指令)设置为false,副标题尽管被暗藏了,但dom元素仍然存在。只是强制给副标题增加了一个display:none款式进行了一个暗藏操作。 而咱们持续用v-if指令,能够看出整个的副标题h3间接去掉了,也就是基本就不会给你进行渲染。 什么时候用v-show,什么时候用v-if呢?理解到了他们的区别之后,咱们能力更好的去了解,去应用。首先v-show指令会提前渲染dom,所以做显示与暗藏切换时缓存的dom开箱即用并不会加大性能的损耗,而v-if指令如果频繁的切换,会一直的销毁dom与从新创立dom会造成肯定的性能损耗,特地是要渲染的场景过于简单时。所以v-show指令适宜频繁的切换。比方tab切换,下拉框显示等。以下是记单词一个我的项目截图,当点击tab切换时所有的图片与字母都进行了暗藏,点击查看单词按钮即可显示残缺的图片与单词。这里就比拟适宜v-show指令做频繁的切换。 这么看来如同用v-show指令就够了?事实并非如此,但什么时候用v-if指令呢?其实有很多场景不须要频繁切换的,咱们都能够用v-if指令。并且v-if还反对多条件判断。咱们来看如下场景,在记单词游戏中能够看到外面有图片,中文,英文单词 三种显示模式,而这三种模式咱们只需显示一种即可,并且并不需要频繁切换,这样咱们就能够应用v-if指令。如果类型为图片类型则显示图片,中文类型则显示中文,英文类型则显示英文。如果含有更多的类型,则能够接续用else if指令,实现多条件判断。并且显示一种之后其余不满足条件的都不会被渲染,这样极大升高了不必要的渲染过程,进步性能。 原文转载 http://www.guiplan.com/articl...

November 16, 2022 · 1 min · jiezi

关于javascript:一文彻底搞懂前端缓存机制

浏览器缓存步骤1)浏览器在加载资源时,先依据这个资源的一些http header判断它是否命中强缓存,强缓存如果命中,浏览器间接从本人的缓存中读取资源,不会发申请到服务器。比方某个css文件,如果浏览器在加载它所在的网页时,这个css文件的缓存配置命中了强缓存,浏览器就间接从缓存中加载这个css,连申请都不会发送到网页所在服务器; 2)当强缓存没有命中的时候,浏览器肯定会发送一个申请到服务器,通过服务器端根据资源的另外一些http header验证这个资源是否命中协商缓存,如果协商缓存命中,服务器会将这个申请返回,然而不会返回这个资源的数据,而是通知客户端能够间接从缓存中加载这个资源,于是浏览器就又会从本人的缓存中去加载这个资源; 3)强缓存与协商缓存的共同点是:如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据;区别是:强缓存不发申请到服务器,协商缓存会发申请到服务器。 4)当协商缓存也没有命中的时候,浏览器间接从服务器加载资源数据。 实例:以常见的申请一个CSS款式来说。 第一次申请 通常服务器会传送这4个字段过去, 可能是4个都要,也可能一个字段也没有。这里次要解说4个字段都存在的状况。 第二次申请 前端:首先,浏览器会查看Cache-Control与Expires,有Cache-Control的状况下,以其为规范,如果超时,则向后端发送申请,申请中会带上 If-Modified-Since,If-None-Match。 后盾:后端服务器接管到申请之后,会对这两个字段进行比照,同样以If-None-Match为规范,没有If-None-Match的状况下,比对If-Modified-Since,如果比对后发现文件没有过期,即Etag没有发生变化,或者Last-Modified与If-Modified-Since统一(只存在If-Modified-Since时)。如果扭转了,就会发送新的文件,反之,则间接返回304。 浏览器缓存分类 强缓存客户端第一次问服务器要某个资源时,服务器丢还给客户端所申请的这个资源同时,通知客户端将这个资源保留在本地,并且在将来的某个时点之前如果还须要这个资源,间接从本地获取就行了,不必向服务器申请。这种形式缓存下来的资源称为强缓存。参考视频解说:进入学习 强缓存利用http的返回头部的中Expires(实体首部字段)或者Cache-Control(通用首部字段)两个字段来管制的,用来示意资源的缓存工夫。服务器通过这两个首部字段告知客户端资源的缓存过期工夫和缓存最大生命周期。客户端得悉资源的缓存过期工夫和最大生命周期后,即可自行判断是否可不建设与服务器的链接,间接从浏览器缓存中获取资源。 命中强缓存时,浏览器同样会受到status=200的response,chrome中可通过size辨别从服务器返回的资源还是强缓存取得的资源。 Expires 该字段是http1.0时的标准,值为一个相对工夫的GMT格局的工夫字符串,代表缓存资源的过期工夫,在这个时点之前,即命中缓存。其过程如下: 浏览器第一次跟服务器申请一个资源时,服务器在返回这个资源时,在相应头部会加上Expires,如图:clipboard.png 浏览器接管到该资源后,会把这个资源连同response header一起缓存下来; 浏览器再次申请这个资源时,会先从缓存中找到这个资源,而后获取Expires工夫与以后的申请工夫比拟,如果Expires工夫比以后浏览器的申请工夫晚,阐明缓存未过期,即命中缓存; 如果以后申请工夫比Expires晚,阐明缓存过期,即未命中缓存,浏览器就会发送申请到服务器申请获取资源。 毛病:服务器返回的Expires时点是服务器上的工夫,可能与客户端有时间差,时间差太大时可能造成缓存凌乱。 Cache-Control:max-age Cache-Control有很多属性,不同的属性代表的意义也不同。 private:客户端能够缓存 public:客户端和代理服务器都能够缓存 max-age=t:缓存内容将在t秒后生效 no-cache:须要应用协商缓存来验证缓存数据 no-store:所有内容都不会缓存。 该字段是http1.1的标准,强缓存利用其max-age值来判断缓存资源的最大生命周期,它的值单位为秒,Cache-Control : max-age=3600代表缓存资源无效工夫为1小时,即从第一次获取该资源起一小时内的申请都被认为可命中强缓存。其过程如下: 浏览器第一次跟服务器申请一个资源时,服务器在返回这个资源时,在相应头部会加上Cache-Control:max-age=XXXXXXXX, 浏览器接管到资源后,连同response header一起缓存下来; 浏览器再次跟服务器申请同一个资源时,会先从缓存中找到这个资源,获取date(第一次资源返回的响应工夫)和max-age并计算出一个有效期(date + max-age),而后再和浏览器申请工夫比拟最初判断是否命中缓存(逻辑同Expires); 如果没有命中缓存,浏览器间接从服务器申请资源,Cache-Control会在从新获取到服务器返回资源时更新。 Cache-Control形容的是绝对工夫,采纳本地工夫来计算资源的有效期,所以相比Expires更牢靠。 这两个Header能够只用其一,也能够一起应用。一起应用时以Cache-Control为准。 协商缓存客户端第一次问服务器要某个资源时,服务器丢还给客户端所申请的这个资源同时,将该资源的一些信息(文件摘要、或者最初批改工夫)也返回给客户端,通知客户端将这个资源缓存在本地。当客户端下一次须要这个资源时,将申请以及相干信息(文件摘要、或者最初批改工夫)一并发送给服务器,由服务器来判断客户端缓存的资源是否须要更新:如不须要更新,就间接通知客户端获取本地缓存资源;如须要更新,则将最新的资源连同相应的信息一并返回给客户端。当强缓存未命中时,浏览器就会发送申请到服务器,服务器会验证协商缓存是否命中,如果协商缓存命中,申请返回的http状态为304,并会显示阐明Not Modified,浏览器收到该返回后,就会从缓存中加载了。 协商缓存利用[Last-Modified , If-Modified-Since] 和 [ETag , If-None-Match]这两对Header来治理。 Last-Modified & If-Modified-Since Last-Modified为实体首部字段,值为资源最初更新工夫,随服务器response返回。 If-Modified-Since为申请首部字段,通过比拟两个工夫来判断资源在两次申请期间是否有过批改,如果没有批改,则命中协商缓存,浏览器从缓存中获取资源;如果有过批改,则服务器返回资源,同时返回新的Last-Modified工夫。其过程如下: 浏览器第一次申请服务器资源,且服务器返回了该资源时,会在response headers中加上Last-Modified,这个header示意这个资源在服务器上的最初一次批改工夫;当浏览器再次申请该资源时,会在request headers中加上If-Modified-Since,这个值即为上一次服务器返回的Last-Modified工夫;服务器再次收到资源申请时,将If-Modified-Since工夫和资源在服务器上的最初批改工夫与比照,如果If-Modifid-Since与最初批改工夫统一,则命中缓存,服务器返回304,浏览器从缓存中获取资源;若未命中缓存,服务器返回资源同时,浏览器缓存资源的Last-Modified会被更新。ETag & If-None-Match 有些状况下仅判断最初批改日期来验证资源是否有改变是不够的: 存在周期性重写某些资源,但资源理论蕴含的内容并无变动; 被批改的信息并不重要,如正文等; Last-Modified无奈准确到毫秒,但有些资源更新频率有时会小于一秒。 ...

November 16, 2022 · 1 min · jiezi

关于javascript:一文读懂Js中的this指向

前言this关键字是一个十分重要的语法点。毫不夸大地说,不了解它的含意,大部分开发工作都无奈实现。 简略说,this就是属性或办法“以后”所在的对象。 this.property下面代码中,this就代表property属性以后所在的对象。 上面是一个理论的例子。 var person = { name: '张三', describe: function () { return '姓名:'+ this.name; }};person.describe()// "姓名:张三"下面代码中,this.name示意name属性所在的那个对象。因为this.name是在describe办法中调用,而describe办法所在的以后对象是person,因而this指向person,this.name就是person.name。 因为对象的属性能够赋给另一个对象,所以属性所在的以后对象是可变的,即this的指向是可变的。 var A = { name: '张三', describe: function () { return '姓名:'+ this.name; }};var B = { name: '李四'};B.describe = A.describe;B.describe() // "姓名:李四"下面代码中,A.describe属性被赋给B,于是B.describe就示意describe办法所在的以后对象是B,所以this.name就指向B.name。 只有函数被赋给另一个变量,this的指向就会变。 var A = { name: '张三', describe: function () { return '姓名:'+ this.name; }};var name = '李四';var f = A.describe;f() // "姓名:李四"下面代码中,A.describe被赋值给变量f,外部的this就会指向f运行时所在的对象(本例是顶层对象,在浏览器中就是window),因而name为全局name的值。 本质JavaScript 语言之所以有 this 的设计,跟内存外面的数据结构有关系。 ...

November 16, 2022 · 6 min · jiezi

关于javascript:一比一手写迷你版vue彻底搞懂vue运行机制

前言当初前端面试Vue中都会问到响应式原理以及如何实现的,如果你还只是简略答复通过Object.defineProperty()来劫持属性可能曾经不够了。 本篇文章通过学习文档及视频教程实现手写一个繁难的Vue源码实现数据双向绑定,解析指令等。 几种实现双向绑定的做法目前几种支流的mvc(vm)框架都实现了单向数据绑定,而我所了解的双向数据绑定无非就是在单向绑定的根底上给可输出的元素(input, textare等)增加了change(input)事件,来动静批改model和view,并没有多浅近,所以无需太过介怀是实现的单向或双向绑定。 实现数据绑定的做法有大抵如下几种:发布者-订阅者模式(backbone.js) 脏值查看(angular.js) 数据劫持(Vue.js) 发布者-订阅者模式个别是通过sub, pub的形式来实现数据和试图的绑定坚听,更细数据办法通常做法是vm.set('property', value)这种形式当初毕竟太low来,咱们更心愿通过vm.property = value这种形式更新数据,同时自动更新视图,于是有来上面两种形式。 脏值查看angular.js是通过脏值检测的形式比照数据是否有变更,来决定是否更新视图,最简略的形式就是通过setInterval()定时轮询检测数据变动,当然Google不会这么low,angular只有在制订的事件触发时进入脏值检测,大抵如下 * DOM事件,臂如用户输出文本,点击按钮等(ng-click)* XHR响应事件($http)* 浏览器location变更事件($location)* Timer事件($timeout, $interval)* 执行$diaest()或¥apply()数据劫持Vue.js则是通过数据劫持联合发布者-订阅者模式的形式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时公布音讯给订阅者,触发相应的监听回调。 Vue源码实现index.html <!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title></title> <script type="text/javascript" src="./compile.js"></script> <script type="text/javascript" src="./observe.js"></script> <script type="text/javascript" src="./myvue.js"></script> </head> <body> <div id="app"> <h2>{{person.name}} -- {{person.age}}</h2> <h3>{{person.sex}}</h3> <ul> <li>1</li> <li>2</li> <li>3</li> </ul> <div v-text="msg"></div> <div>{{msg}}</div> <div v-text="person.name"></div> <div v-html="htmlStr"></div> <input type="text" v-model="msg" /> <button type="button" v-on:click="btnClick">v-on:事件</button> <button type="button" @click="btnClick">@事件</button> </div> <script type="text/javascript"> let vm = new Myvue({ el: '#app', data: { person: { name: '只会番茄炒蛋', age: 18, sex: '男' }, msg: '学习MVVM实现原理', htmlStr: '<h1>我是html指令渲染的</h1>' }, methods: { btnClick() { console.log(this.msg) } } }) </script> </body></html>第一步 - 实现一个指令解析器(Compile)compile次要做的事件是解析模板指令,将模板中的变量替换成数据,而后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,增加监听数据的订阅者,一旦数据有变动,收到告诉,更新视图,参考视频解说:进入学习 ...

November 16, 2022 · 5 min · jiezi

关于javascript:如何判断浏览器是下载还是浏览文件

1、浏览器会依据Content-Type的值来判断如何解决申请的文件,然而即使Content-Type的值设置正确也无奈保障申请的url是浏览文件还是下载文件;2、须要再次确认: Content-Disposition:inline【浏览文件】Content-Disposition:attachment【下载文件】Content-Disposition:attachment; filename="yourFileName":以自定义文件名的模式下载到浏览器指定门路。yourFileName用于自定义下载后的文件名称,例如example.jpg。参考文档链接:https://help.aliyun.com/docum...

November 9, 2022 · 1 min · jiezi

关于javascript:关于微前端你理解到究极奥义了么

hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块计划 ,欢送关注与理解微前端的起源 在微前端这个概念呈现之前,咱们或多或少都可能联想到另一个词性上有些类似的概念微服务,它从呈现后便始终都很炽热,并一直催生着后端架构体系的演进,而此刻咱们如果细品一下这微字头的两兄弟,探索他们的诞生起因,会有很多有意思的点。 咱们暂且忘掉这兄弟两,到一个更高的角度会发现,很多新概念的诞生,肯定可能顺藤摸瓜的追溯到一个某个原点上,这个原点咱们能够把它比作宇宙诞生的奇点,压抑了足够久之后产生了大爆炸,而后逐步向外扩散生成万物原型,so...... 咱们复盘一下处在这个信息高速时代,当网络带宽越来越大,覆盖范围越来越广,提早越来越低,触达人群越来越多的时候,让web从1.0进化2.0、3.0、4.0,在这个全民入网的时代,网络条件如此优越的时代,是什么开始按捺不住那宏大的能量,开始胡作非为的爆炸起来了呢? 爆炸的数据聪慧的你肯定意识到了,它就是数据,优越的网络条件如同肥沃的土壤,让全民皆参加到内容生产当中,于是乎海量的数据疯狂成长,让咱们进入了大数据时代,面对如此澎湃的体量,云计算、分布式等新概念簇拥而出,有了用武之地,或者说数据的爆炸倒逼着这些技术的产生与倒退。 再回到微服务与微前端两兄弟上,想一下是不是同样的也正因为数据的爆炸,须要精细化的经营各种场景,让咱们传统的单体服务架构上不得不承载着越来越多的业务呢? 这种蕴含n个服务形成的一个后盾我的项目,从开发侧看,只能在既有的技术栈上不停的叠加新性能,当新的技术福利诞生时想作替换将是一场噩梦,从运维测看,因整个我的项目打包在一起形成了一个产物,而不得不面对任何一点批改都必须全副一起公布的繁琐。 于是乎微服务诞生了,将这种巨石服务或按各职责、或按性能、或按业务等维度作为拆分的维度,拆解成一个个服务,可独立构建、独立部署,通过rpc通信做到利用的语言架构无关,让开发者不再捆绑到某一个编程语言上,当然了,作为拆的代价,服务注册、服务治理、服务发现、服务熔断、服务监控、链路追踪等新机制的引入带来了更高的复杂度,所以服务的拆分肯定是一个渐进式的过程,为了拆而拆必然带来运维上的更高老本与挑战。 重刷存在感的微前端 和微服务不一样的是,如果咱们不死磕微前端概念,而是从拆字这个角度来看,其实微前端其实从html诞生那天开始始终都存在,我么认真回忆一下,传统的服务器端渲染,是不是一个路由对应着服务器端一个html页面的字符串返回呢,这一个返回对应着后端的一个页面模板,不论它是动态生成的还是动静生成的,它在后端的目录构造里都是一个个独立存在的文件,所以咱们始终都是在用微前端搭建我的项目的视图局部。 随着前端的业务复杂度极巨俯冲,传统的服务端渲染形式给前端工程化带来了微小的挑战,因为工程化的根底是组件化,而后端的模板引擎所反对的组件化天生有着用绵软有力的感觉,无论是书写体验还是调试体验都远远弱于浏览器端渲染,而随着作为浏览器端主战场的不二人选js,生态周边越来越丰盛与弱小,如node的诞生为前端工程化催生了大量优良的构建工具、编译工具,js引擎的性能也始终在攀升,js本身的标准和语言个性也一直的进化,以及和相干组件化开发的优良库如春笋版冒出(react、vue、angular、svelte...),良好的npm生态让库共享大海捞针等,在这种有利于前端工程化的土壤培养下,让咱们面对简单的前端我的项目时,如可疏忽seo优化,首屏速度等因素时(只管也有相似的解决方案),偏向于从服务器渲染迁徙到浏览器端渲染了。 微前端之5个核心思想前端工程化也面临着后端同样的问题,一个工程随着工夫流逝会逐步重叠大量业务,从而让一个前端我的项目缓缓演变成一个巨石利用,基于此背景下在micro-frontends上对微前端做了如下论述: 微前端背地的想法是将网站或 Web 应用程序视为由独立团队领有 的 性能的组合。每个团队都有不同的业务畛域或工作,它关怀和专一于,一个团队是跨职能的,从数据库到用户界面,端到端地开发其性能,但这个想法并不陈腐,它与自蕴含零碎的概念有很多共同之处。在过来,这种办法被称为垂直零碎的前端集成。但微前端显然是一个更敌对、更简洁的术语。 并进一步提炼出以下5点微前端的核心思想 与技术无关 每个团队都应该可能抉择和降级他们的堆栈,而无需与其余团队协调。自定义元素是暗藏实现细节同时为其他人提供中性界面的好办法。隔离团队代码 不要共享运行时,即便所有团队都应用雷同的框架。构建自蕴含的独立应用程序。不要依赖共享状态或全局变量。建设团队前缀 就尚无奈隔离的命名约定达成统一。命名空间 CSS、事件、本地存储和 Cookie,以防止抵触并明确所有权。优先应用本机浏览器性能而不是自定义 API 应用浏览器事件进行通信,而不是构建全局 PubSub 零碎。如果你真的须要构建一个跨团队的 API,尽量让它尽可能简略。构建弹性站点 即便 JavaScript 失败或尚未执行,您的性能也应该很有用。应用通用渲染和渐进加强来进步感知性能。微前端之模块联邦以上阶段1里强调的5点个性看起来仿佛给微前端下了一个相当完满的定义,以至于起初的各种微前端框架都在这5个核心思想领导上来做实现,直到2020年 webpack 5 module federation(以下咱们简称MF)模块联邦诞生,并对此个性在官网做了一个很简略的介绍: 模块联结的动机,让多个独自的构建应该可组合为一个应用程序,这些独自的构建之间不应该有依赖关系,因而它们能够独自开发和部署,这通常被称为微前端,但不限于此。细细玩味这段话,咱们发现webpack 5视角下的微前端仅须要蕴含3个特点:独立开发、独立部署、运行时组合。 如果你基于webpack 5 MF公布过近程模块,你会晓得它并不蕴含micro-frontends站点里提到的隔离团队代码这个关键点,只管咱们晓得波及到代码运行隔离须要用上shadowrealm(将来的隔离计划)、proxy window、iframe 等计划,但MF并未强调这一点,所以看起来MF了解下的微前端是阉割版的微前端? 再思考微前端咱们将micro-frontends 和 webpack 5 两个出处的微前端定义做一个比照,并提出一个灵魂的拷问,是否以下表白成立? 事实上随着模块联邦这个概念开始逐步深入人心,微前端架构曾经决裂出两个方向: 容器型微前端 咱们把以single-spa为代表的这一类计划统称为微容器,在single-spa走红之后市面很多基于single-spa二次封装的库如雨后春笋般涌出,典型的代表作如阿里的qiankun,意在解决一些single-spa未解决的问题并让其更适宜企业级开发,同时也诞生了很多非singlespa系的框架,如京东的micro-app、腾讯的wujie等,它们的细节实现各有差别,蕴含js沙箱隔离、css隔离、iframe编排、启用web-component、window代理、接入过程等各个中央的细节也各有千秋,但它们都一个很显著的特点,对应的模块粒度是整个利用,做出的产品能够了解为一种以宏观态的形式来组合多个利用交付给用户应用。 试想一下,你不会极其到以运行时隔离的形式去渲染多个按钮吧?模块型微前端 相较于微容器宏观态的组合利用形式,微模块则能够形容为宏观态的组合形式,它的粒度更小,小到能够是一个函数,一个根底的组件,对于开发者来说,引入微模块和引入一个一般的js包没有任何区别,他们在应用上也并无任何区别,但恰好是这一点!是它和微容器最大差别之一,微模块的应用形式回归到了js语法自身。 微容器和微模块在开源社区均有很多实现,它们的特点很显著 所以基于两种计划搭建的微前端架构也是区别非常明显的 微前端技术该如何选型咱们只有深刻理解到微模块是人造就假设运行在同一个宿主里(即同个一js环境里),它要解决的外围问题是大规模独立构建的利用间如何疾速动静共享公共模块这个辣手问题。 例如你有100个外部的前端我的项目依赖了lodash-1.0.0,忽然该库裸露了一个破绽,你须要100个前端我的项目全副从新构建降级到1.0.1才代表平安解决此破绽问题,而基于模块联邦的lodash,你仅须要构建一次mf-lodash,其余我的项目即可援用到最新的平安代码。 再综合思考到两个以下关键点,就很容易得出技术如何选型的论断了: 1 是否须要多技术栈混合开发(react、vue...)2 是否须要多版本技术栈同时迭代等(vue2, vue3...)因为微模块是宏观态的组合形式,它能够迅速的将你逐步宏大的利用拆为一个个可独立部署的组件并再次组合起来,绝对于微容器计划,大多数时候或者你的新我的项目并不需要染指微容器。 当你须要组合一些第三方利用或本人的其余技术栈利用,并须要让它的就是被隔离起来平安的运行时,微容器是你武器库里适宜拿进去的强力武器。 ...

November 9, 2022 · 1 min · jiezi

关于javascript:js手写题汇总面试前必刷

event模块实现node中回调函数的机制,node中回调函数其实是外部应用了观察者模式。 观察者模式:定义了对象间一种一对多的依赖关系,当指标对象Subject产生扭转时,所有依赖它的对象Observer都会失去告诉。function EventEmitter() { this.events = new Map();}// 须要实现的一些办法:// addListener、removeListener、once、removeAllListeners、emit// 模仿实现addlistener办法const wrapCallback = (fn, once = false) => ({ callback: fn, once });EventEmitter.prototype.addListener = function(type, fn, once = false) { const hanlder = this.events.get(type); if (!hanlder) { // 没有type绑定事件 this.events.set(type, wrapCallback(fn, once)); } else if (hanlder && typeof hanlder.callback === 'function') { // 目前type事件只有一个回调 this.events.set(type, [hanlder, wrapCallback(fn, once)]); } else { // 目前type事件数>=2 hanlder.push(wrapCallback(fn, once)); }}// 模仿实现removeListenerEventEmitter.prototype.removeListener = function(type, listener) { const hanlder = this.events.get(type); if (!hanlder) return; if (!Array.isArray(this.events)) { if (hanlder.callback === listener.callback) this.events.delete(type); else return; } for (let i = 0; i < hanlder.length; i++) { const item = hanlder[i]; if (item.callback === listener.callback) { hanlder.splice(i, 1); i--; if (hanlder.length === 1) { this.events.set(type, hanlder[0]); } } }}// 模仿实现once办法EventEmitter.prototype.once = function(type, listener) { this.addListener(type, listener, true);}// 模仿实现emit办法EventEmitter.prototype.emit = function(type, ...args) { const hanlder = this.events.get(type); if (!hanlder) return; if (Array.isArray(hanlder)) { hanlder.forEach(item => { item.callback.apply(this, args); if (item.once) { this.removeListener(type, item); } }) } else { hanlder.callback.apply(this, args); if (hanlder.once) { this.events.delete(type); } } return true;}EventEmitter.prototype.removeAllListeners = function(type) { const hanlder = this.events.get(type); if (!hanlder) return; this.events.delete(type);}实现Event(event bus)event bus既是node中各个模块的基石,又是前端组件通信的依赖伎俩之一,同时波及了订阅-公布设计模式,是十分重要的根底。 ...

November 9, 2022 · 10 min · jiezi

关于javascript:几个常见的js手写题你能写出来几道

实现 new 过程:要点: 函数第一个参数是构造函数实例的__proto__指向构造函数的原型属性prototype函数残余参数要挂载到一个实例对象上构造函数有返回值时,就返回这个返回值const createObj = function () { let obj = {} let Constructor = [].shift.call(arguments) // 1 obj.__proto__ = Constructor.prototype // 2 let ret = Constructor.apply(obj, arguments) // 3 return typeof ret === 'object' ? ret: obj // 4}// 应用const Fun = function (name) { this.name = name}Fun.prototype.getName = function() { alert(this.name)}let fun = createObj(Fun, 'gim')fun.getName() // gim值得注意的是,es6的class必须用new调用,否则会报错,如下: class Fun { constructor(name) { this.name = name } getName() { alert(this.name) }}let fun = createObj(Fun, 'gim')fun.getName() // Uncaught TypeError: Class constructor Fun cannot be invoked without 'new'手写 call、apply 及 bind 函数共同点: ...

November 9, 2022 · 4 min · jiezi

关于javascript:前端一面必会手写面试题指南

reduce用法汇总语法 array.reduce(function(total, currentValue, currentIndex, arr), initialValue);/* total: 必须。初始值, 或者计算完结后的返回值。 currentValue: 必须。以后元素。 currentIndex: 可选。以后元素的索引; arr: 可选。以后元素所属的数组对象。 initialValue: 可选。传递给函数的初始值,相当于total的初始值。*/reduceRight() 该办法用法与reduce()其实是雷同的,只是遍历的程序相同,它是从数组的最初一项开始,向前遍历到第一项1. 数组求和 const arr = [12, 34, 23];const sum = arr.reduce((total, num) => total + num);// 设定初始值求和const arr = [12, 34, 23];const sum = arr.reduce((total, num) => total + num, 10); // 以10为初始值求和// 对象数组求和var result = [ { subject: 'math', score: 88 }, { subject: 'chinese', score: 95 }, { subject: 'english', score: 80 }];const sum = result.reduce((accumulator, cur) => accumulator + cur.score, 0); const sum = result.reduce((accumulator, cur) => accumulator + cur.score, -10); // 总分扣除10分2. 数组最大值 ...

November 9, 2022 · 9 min · jiezi

关于javascript:实现Promise的原型方法前端面试能力提升

说起Promise大家应该都耳熟能详,咱们明天来看下Promise的相干办法有如下:原型办法:then、catch、finally 静态方法:resolve、reject、race、all、allSettled、any 手写实现办法如下:实现resolve办法promise.resolve('123')本质上就是new Promise(resolve=>resolve('123')})Promise.resolve(value) 将给定的一个值转为Promise对象。 如果这个值是一个 promise ,那么将返回这个 promise ;如果这个值是thenable(即带有"then" 办法),返回的promise会“追随”这个thenable的对象,采纳它的最终状态;否则返回的promise将以此值实现,即以此值执行resolve()办法 (状态为fulfilled)。 class MyPromise { static PENDING = 'pending' static FULFILLED = 'fulfilled' static REJECTED = 'rejected' constructor(executor) { this.PromiseState = MyPromise.PENDING this.PromiseResult = null this.fulfilledCallBacks = [] this.rejectedCallBacks = [] try { executor(this.resolve.bind(this), this.reject.bind(this)) } catch (error) { this.reject(error) } } resolve(result) { if ((this.PromiseState = MyPromise.PENDING)) { setTimeout(() => { this.PromiseState = MyPromise.FULFILLED this.PromiseResult = result for (const callBack of this.fulfilledCallBacks) { callBack(result) } }) } } reject(reason) { if ((this.PromiseState = MyPromise.PENDING)) { setTimeout(() => { this.PromiseState = MyPromise.REJECTED this.PromiseResult = reason for (const callBack of this.rejectedCallBacks) { callBack(reason) } }) } } then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (val) => val onRejected = typeof onRejected === 'function' ? onRejected : (err) => { throw err } return new MyPromise((resolve, reject) => { if (this.PromiseState === MyPromise.PENDING) { this.fulfilledCallBacks.push(() => { setTimeout(() => { let x = onFulfilled(this.PromiseResult) x instanceof MyPromise ? x.then(resolve, reject) : resolve(x) }) }) this.rejectedCallBacks.push(() => { setTimeout(() => { let x = onRejected(this.PromiseResult) x instanceof MyPromise ? x.then(resolve, reject) : reject(x) }) }) } else if (this.PromiseState === MyPromise.FULFILLED) { try { setTimeout(() => { let x = onFulfilled(this.PromiseResult) x instanceof MyPromise ? x.then(resolve, reject) : resolve(x) }) } catch (error) { reject(error) } } else { try { setTimeout(() => { let x = onRejected(this.PromiseResult) x instanceof MyPromise ? x.then(resolve, reject) : reject(x) }) } catch (error) { reject(error) } } }) } //value 要解析为 Promise 对象的值 static resolve(value) { //如果是 if (value instanceof MyPromise) { return value } else if (value && typeof value === 'object' && 'then' in value) { return new MyPromise((resolve, reject) => { value.then(resolve, reject) }) } return new MyPromise((resolve) => { resolve(value) }) } } const promise1 = MyPromise.resolve(123) promise1.then((value) => { console.log(value) // expected output: 123 }) // Resolve一个thenable对象 var p1 = MyPromise.resolve({ then: function (onFulfill) { onFulfill('Resolving') }, }) console.log(p1 instanceof MyPromise) // true, 这是一个Promise对象 setTimeout(() => { console.log('p1 :>> ', p1) }, 1000) p1.then( function (v) { console.log(v) // 输入"Resolving!" }, function (e) { // 不会被调用 } ) // Thenable在callback之前抛出异样 // MyPromise rejects var thenable = { then: function (resolve) { throw new TypeError('Throwing') resolve('Resolving') }, } var p2 = MyPromise.resolve(thenable) p2.then( function (v) { // 不会被调用 }, function (e) { console.log(e) // TypeError: Throwing } )参考 前端手写面试题具体解答 ...

November 9, 2022 · 15 min · jiezi

关于javascript:前端面试比较好的回答

DNS同时应用TCP和UDP协定?DNS占用53号端口,同时应用TCP和UDP协定。 (1)在区域传输的时候应用TCP协定 辅域名服务器会定时(个别3小时)向主域名服务器进行查问以便理解数据是否有变动。如有变动,会执行一次区域传送,进行数据同步。区域传送应用TCP而不是UDP,因为数据同步传送的数据量比一个申请应答的数据量要多得多。TCP是一种牢靠连贯,保障了数据的准确性。(2)在域名解析的时候应用UDP协定 客户端向DNS服务器查问域名,个别返回的内容都不超过512字节,用UDP传输即可。不必通过三次握手,这样DNS服务器负载更低,响应更快。实践上说,客户端也能够指定向DNS服务器查问时用TCP,但事实上,很多DNS服务器进行配置的时候,仅反对UDP查问包。常见的DOM操作有哪些1)DOM 节点的获取DOM 节点的获取的API及应用: getElementById // 依照 id 查问getElementsByTagName // 依照标签名查问getElementsByClassName // 依照类名查问querySelectorAll // 依照 css 选择器查问// 依照 id 查问var imooc = document.getElementById('imooc') // 查问到 id 为 imooc 的元素// 依照标签名查问var pList = document.getElementsByTagName('p') // 查问到标签为 p 的汇合console.log(divList.length)console.log(divList[0])// 依照类名查问var moocList = document.getElementsByClassName('mooc') // 查问到类名为 mooc 的汇合// 依照 css 选择器查问var pList = document.querySelectorAll('.mooc') // 查问到类名为 mooc 的汇合2)DOM 节点的创立创立一个新节点,并把它增加到指定节点的前面。 已知的 HTML 构造如下: <html> <head> <title>DEMO</title> </head> <body> <div id="container"> <h1 id="title">我是题目</h1> </div> </body></html>要求增加一个有内容的 span 节点到 id 为 title 的节点前面,做法就是: ...

November 9, 2022 · 4 min · jiezi

关于javascript:从这两道题重新理解JS的this作用域闭包对象

日常开发中,咱们常常用到this。例如用Jquery绑定事件时,this指向触发事件的DOM元素;编写Vue、React组件时,this指向组件自身。对于老手来说,常会用一种意会的感觉去判断this的指向。以至于当遇到简单的函数调用时,就分不清this的真正指向。 本文将通过两道题去缓缓剖析this的指向问题,并波及到函数作用域与对象相干的点。最终给大家带来真正的实践剖析,而不是简简单单的一句话概括。 置信若是对this稍有钻研的人,都会搜到这句话:this总是指向调用该函数的对象。 然而箭头函数并不是如此,于是大家就会遇到如下各式说法: 箭头函数的this指向外层函数作用域中的this。箭头函数的this是定义函数时所在上下文中的this。箭头函数体内的this对象,就是定义时所在的对象,而不是应用时所在的对象。各式各样的说法都有,乍看下感觉说的差不多。废话不多说,凭着你之前的了解,来先做一套题吧(非严格模式下)。 /** * Question 1 */var name = 'window'var person1 = { name: 'person1', show1: function () { console.log(this.name) }, show2: () => console.log(this.name), show3: function () { return function () { console.log(this.name) } }, show4: function () { return () => console.log(this.name) }}var person2 = { name: 'person2' }person1.show1()person1.show1.call(person2)person1.show2()person1.show2.call(person2)person1.show3()()person1.show3().call(person2)person1.show3.call(person2)()person1.show4()()person1.show4().call(person2)person1.show4.call(person2)()大抵意思就是,有两个对象person1,person2,而后花式调用person1中的四个show办法,预测真正的输入。 你能够先把本人预测的答案按程序记在本子上,而后再往下拉看正确答案。 正确答案选下: person1.show1() // person1person1.show1.call(person2) // person2person1.show2() // windowperson1.show2.call(person2) // windowperson1.show3()() // windowperson1.show3().call(person2) // person2person1.show3.call(person2)() // windowperson1.show4()() // person1person1.show4().call(person2) // person1person1.show4.call(person2)() // person2比照下你刚刚记下的答案,是否有不一样呢?让咱们尝试来最开始那些实践来剖析下。 ...

November 9, 2022 · 2 min · jiezi

关于javascript:拿到大厂前端offer的前端开发是怎么回答面试题的

代码输入问题function A(){}function B(a){ this.a = a;}function C(a){ if(a){this.a = a; }}A.prototype.a = 1;B.prototype.a = 1;C.prototype.a = 1;console.log(new A().a);console.log(new B().a);console.log(new C(2).a);输入后果:1 undefined 2 解析: console.log(new A().a),new A()为构造函数创立的对象,自身没有a属性,所以向它的原型去找,发现原型的a属性的属性值为1,故该输入值为1;console.log(new B().a),ew B()为构造函数创立的对象,该构造函数有参数a,但该对象没有传参,故该输入值为undefined;console.log(new C(2).a),new C()为构造函数创立的对象,该构造函数有参数a,且传的实参为2,执行函数外部,发现if为真,执行this.a = 2,故属性a的值为2。一个 tcp 连贯能发几个 http 申请?如果是 HTTP 1.0 版本协定,个别状况下,不反对长连贯,因而在每次申请发送结束之后,TCP 连贯即会断开,因而一个 TCP 发送一个 HTTP 申请,然而有一种状况能够将一条 TCP 连贯放弃在沉闷状态,那就是通过 Connection 和 Keep-Alive 首部,在申请头带上 Connection: Keep-Alive,并且能够通过 Keep-Alive 通用首部中指定的,用逗号分隔的选项调节 keep-alive 的行为,如果客户端和服务端都反对,那么其实也能够发送多条,不过此形式也有限度,能够关注《HTTP 权威指南》4.5.5 节对于 Keep-Alive 连贯的限度和规定。 而如果是 HTTP 1.1 版本协定,反对了长连贯,因而只有 TCP 连接不断开,便能够始终发送 HTTP 申请,继续一直,没有下限; 同样,如果是 HTTP 2.0 版本协定,反对多用复用,一个 TCP 连贯是能够并发多个 HTTP 申请的,同样也是反对长连贯,因而只有一直开 TCP 的连贯,HTTP 申请数也是能够没有下限地继续发送 ...

November 9, 2022 · 5 min · jiezi

关于javascript:令人头秃的js隐式转换面试题你能做对吗

你有没有在面试中遇到特地奇葩的js隐形转换的面试题,第一反馈是怎么会是这样呢?难以自信,js到底是怎么去计算失去后果,你是否有深刻去理解其原理呢?上面将深刻解说其实现原理。 其实这篇文章初稿三个月前就写好了,在我读一些源码库时,遇到了这些基础知识,想归档整顿下,就有了这篇文章。因为始终忙没工夫整顿,最近看到了这个比拟热的题,决定把这篇文章整顿下。 const a = { i: 1, toString: function () { return a.i++; }}if (a == 1 && a == 2 && a == 3) { console.log('hello world!');}网上给出了很多不错的解析过程,读了上面内容,你将更深刻的理解其执行过程。 1、js数据类型js中有7种数据类型,能够分为两类:原始类型、对象类型: 根底类型(原始值): Undefined、 Null、 String、 Number、 Boolean、 Symbol (es6新出的,本文不探讨这种类型)简单类型(对象值): object2、三种隐式转换类型js中一个难点就是js隐形转换,因为js在一些操作符下其类型会做一些变动,所以js灵便,同时造成易出错,并且难以了解。 波及隐式转换最多的两个运算符 + 和 ==。 +运算符即可数字相加,也能够字符串相加。所以转换时很麻烦。== 不同于===,故也存在隐式转换。- * / 这些运算符只会针对number类型,故转换的后果只能是转换成number类型。 既然要隐式转换,那到底怎么转换呢,应该有一套转换规则,能力追踪最终转换成什么了。 隐式转换中次要波及到三种转换: 1、将值转为原始值,ToPrimitive()。 2、将值转为数字,ToNumber()。 3、将值转为字符串,ToString()。 2.1、通过ToPrimitive将值转换为原始值js引擎外部的形象操作ToPrimitive有着这样的签名: ToPrimitive(input, PreferredType?) input是要转换的值,PreferredType是可选参数,能够是Number或String类型。他只是一个转换标记,转化后的后果并不一定是这个参数所值的类型,然而转换后果肯定是一个原始值(或者报错)。 2.1.1、如果PreferredType被标记为Number,则会进行上面的操作流程来转换输出的值。1、如果输出的值曾经是一个原始值,则间接返回它2、否则,如果输出的值是一个对象,则调用该对象的valueOf()办法, 如果valueOf()办法的返回值是一个原始值,则返回这个原始值。3、否则,调用这个对象的toString()办法,如果toString()办法返回的是一个原始值,则返回这个原始值。4、否则,抛出TypeError异样。2.1.2、如果PreferredType被标记为String,则会进行上面的操作流程来转换输出的值。1、如果输出的值曾经是一个原始值,则间接返回它2、否则,调用这个对象的toString()办法,如果toString()办法返回的是一个原始值,则返回这个原始值。3、否则,如果输出的值是一个对象,则调用该对象的valueOf()办法, 如果valueOf()办法的返回值是一个原始值,则返回这个原始值。4、否则,抛出TypeError异样。既然PreferredType是可选参数,那么如果没有这个参数时,怎么转换呢?PreferredType的值会依照这样的规定来主动设置: 1、该对象为Date类型,则PreferredType被设置为String2、否则,PreferredType被设置为Number2.1.3、valueOf办法和toString办法解析下面次要提及到了valueOf办法和toString办法,那这两个办法在对象里是否肯定存在呢?答案是必定的。在控制台输入Object.prototype,你会发现其中就有valueOf和toString办法,而Object.prototype是所有对象原型链顶层原型,所有对象都会继承该原型的办法,故任何对象都会有valueOf和toString办法。 先看看对象的valueOf函数,其转换后果是什么?对于js的常见内置对象:Date, Array, Math, Number, Boolean, String, Array, RegExp, Function。 ...

November 9, 2022 · 3 min · jiezi

关于javascript:JavaScript中的箭头函数

前言本文能够让你理解所有无关JavaScript箭头函数的信息。咱们将通知你如何应用ES6的箭头语法,以及在代码中应用箭头函数时须要留神的一些常见谬误。你会看到很多例子来阐明它们是如何工作的。 JavaScript的箭头函数随着ECMAScript 2015的公布而到来,也被称为ES6。因为其简洁的语法和对this关键字的解决,箭头函数迅速成为开发者们最青睐的性能。 箭头函数语法函数就像食谱一样,你在其中存储有用的指令,以实现你须要在程序中产生的事件,比方执行一个动作或返回一个值。通过调用函数,来执行食谱中蕴含的步骤。你能够在每次调用该函数时都这样做,而不须要一次又一次地重写菜谱。 上面是在JavaScript中申明函数并调用它的规范办法: // function declarationfunction sayHiStranger() { return 'Hi, stranger!'}// call the functionsayHiStranger()你也能够编写同样的函数作为函数表达式,就行这样: const sayHiStranger = function () { return 'Hi, stranger!'}JavaScript箭头函数始终是表达式。上面是如何应用箭头符号重写下面的函数: const sayHiStranger = () => 'Hi, stranger'这样做的益处包含: 代码只有一行没有function关键字没有return关键字没有大括号{}在JavaScript中,函数是一等公民。你能够把函数存储在变量中,把它们作为参数传递给其余函数,并从其余函数中把它们作为值返回。你能够应用JavaScript箭头函数来做所有这些事件。 无圆括号语法在上述示例中,函数是没有参数的。在本例中,你必须在胖箭头符号(=>)之前增加一对空的圆括号()。当有多个参数时同理: const getNetflixSeries = (seriesName, releaseDate) => `The ${seriesName} series was released in ${releaseDate}`// call the functionconsole.log(getNetflixSeries('Bridgerton', '2020') )// output: The Bridgerton series was released in 2020如果只有一个参数,你能够省略圆括号(你不用如此,但你能够这么做): const favoriteSeries = seriesName => seriesName === "Bridgerton" ? "Let's watch it" : "Let's go out"// call the functionconsole.log(favoriteSeries("Bridgerton"))// output: "Let's watch it"当你这么做的时候要小心一点。比如说,你决定应用默认参数,你必须将其包裹在圆括号中: ...

November 8, 2022 · 4 min · jiezi

关于javascript:llqrcodejs识别二维码解析二维码信息

llqrcode.js具备扫描二维码性能,用来进行从图片中辨认二维码,可解析二维码的信息。 代码<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>llqrcode辨认二维码</title> <script src="llqrcode.js"></script> <script> function getUrl(e,param){ analyticCode.getUrl( param,e,function(url,param){ document.querySelector("#uploadQrcode").style.display = "none"; document.querySelector("#uploadQrcode_preview").innerHTML ="<img src='"+param+"' />"; document.querySelector("#qrcodeUrl").innerHTML ="辨认内容:"+ url; document.querySelector("#rescan").style.display = "block"; } ) } let getObjectURL = function(file){ let url = null ; if (window.createObjectURL!=undefined) { url = window.createObjectURL(file) ; } else if (window.URL!=undefined) { url = window.URL.createObjectURL(file) ; } else if (window.webkitURL!=undefined) { url = window.webkitURL.createObjectURL(file) ; } return url ; } window.analyticCode = { getUrl : function(type,elem,fn){ let url = null,src = null; if(type === 'img-url'){ url = elem.src; }else if(type === 'file-url' && elem.files.length > 0){ url = getObjectURL(elem.files[0]); } qrcode.decode(url); qrcode.callback = function(imgMsg){ fn(imgMsg,url); } } } </script> <style> h3{ text-align: center; margin-top: 100px; } #uploadQrcode{ width: 80px; height: 80px; margin:20px auto 0; border: 2px dashed #ccc; border-radius: 20px; font-size: 25px; line-height: 80px; text-align: center; color: #ccc; position: relative; cursor: pointer; } #selectQrcode{ position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; } #qrcodeUrl{ text-align: center; margin-top: 15px; } #uploadQrcode_preview{ width: 80px; height: 80px; margin:20px auto 0; } #uploadQrcode_preview img{ width: 80px; height: 80px; } #rescan{ text-align: center; text-decoration: none; color: #666; font-size: 15px; margin-top: 15px; display: none; } </style></head><body> <h3>抉择一张二维码图片</h3> <div id="uploadQrcode"> <span>+</span> <input type="file" id="selectQrcode" onChange="getUrl(this,'file-url')" /> </div> <!-- 图片预览 --> <div id="uploadQrcode_preview"></div> <!-- 辨认后果 --> <p id="qrcodeUrl"></p> <a href="" id="rescan">从新辨认</a></body></html>llqrcode.js下载:https://likeyun.lanzout.com/i... ...

November 8, 2022 · 2 min · jiezi

关于javascript:假如面试官要你手写一个promise

promise在开发中,常常须要用到promise,promise具备很多个性,这一次将对promise个性进行总结,并从零写一个promise。 步骤一Promise特点 1,创立时须要传递一个函数,否则会报错2,会给传入的函数设置两个回调函数3,刚创立的Promise对象状态是pendingclass MyPromise { constructor(handle) { // 3,刚创立的Promise对象状态是pending this.status = "pending"; // 1,创立时须要传递一个函数,否则会报错 if (!this._isFunction(handle)) { throw new Error("请传入一个函数"); } // 2,会给传入的函数设置两个回调函数 handle(this._resolve.bind(this), this._reject.bind(this)) } _resolve() { } _reject() { } _isFunction(fn) { return typeof fn === "function"; }}步骤二Promise特点 4,状态一旦产生扭转就不可再次扭转5,能够通过then来监听状态的扭转 5.1,如果创立监听时,状态曾经扭转,立刻执行监听回调5.2,如果创立监听时,状态未扭转,会等状态扭转后执行5.3,同一promise对象能够增加多个then监听,状态扭转时依照注册程序顺次执行// 定义常量保留对象的状态const PENDING = "pending";const FULFILLED = "fulfilled";const REJECTED = "rejected";class MyPromise { constructor(handle) { // 3,刚创立的Promise对象状态是pending this.status = PENDING; // 胜利回调的值 this.value = undefined; // 失败回调的值 this.reason = undefined; // 注册的胜利回调 this.onResolvedCallbacks = []; // 注册的失败回调 this.onRejectedCallbacks = []; // 1,创立时须要传递一个函数,否则会报错 if (!this._isFunction(handle)) { throw new Error("请传入一个函数"); } // 2,会给传入的函数设置两个回调函数 handle(this._resolve.bind(this), this._reject.bind(this)) } _resolve(value) { // 4,状态一旦产生扭转就不可再次扭转 if (this.status === PENDING) { this.status = FULFILLED; this.value = value; // 5.3,同一promise对象能够增加多个then监听,状态扭转时依照注册程序顺次执行 this.onResolvedCallbacks.forEach(fn => fn(this.value)); } } _reject(reason) { // 4,状态一旦产生扭转就不可再次扭转 if (this.status === PENDING) { this.status = REJECTED; this.reason = reason; // 5.3,同一promise对象能够增加多个then监听,状态扭转时依照注册程序顺次执行 this.onRejectedCallbacks.forEach(fn => fn(this.reason)); } } then(onResolved, onRejected) { // 判断有没有传入胜利的回调 if (this._isFunction(onResolved)) { // 5.1,如果创立监听时,状态曾经扭转,立刻执行监听回调 if (this.status === FULFILLED) { onResolved(this.value); } } // 判断有没有传入失败的回调 if (this._isFunction(onRejected)) { // 5.1,如果创立监听时,状态曾经扭转,立刻执行监听回调 if (this.status === REJECTED) { onRejected(this.reason); } } // 5.2,如果创立监听时,状态未扭转,会等状态扭转后执行 if (this.status === PENDING) { if (this._isFunction(onResolved)) { this.onResolvedCallbacks.push(onResolved); } if (this._isFunction(onRejected)) { this.onRejectedCallbacks.push(onRejected); } } } _isFunction(fn) { return typeof fn === "function"; }}参考 前端手写面试题具体解答 ...

November 8, 2022 · 3 min · jiezi

关于javascript:最近面试经常被问到的js手写题

实现apply办法思路: 利用this的上下文个性。apply其实就是改一下参数的问题Function.prototype.myApply = function(context = window, args) { // this-->func context--> obj args--> 传递过去的参数 // 在context上加一个惟一值不影响context上的属性 let key = Symbol('key') context[key] = this; // context为调用的上下文,this此处为函数,将这个函数作为context的办法 // let args = [...arguments].slice(1) //第一个参数为obj所以删除,伪数组转为数组 let result = context[key](...args); // 这里和call传参不一样 // 革除定义的this 不删除会导致context属性越来越多 delete context[key]; // 返回后果 return result;}// 应用function f(a,b){ console.log(a,b) console.log(this.name)}let obj={ name:'张三'}f.myApply(obj,[1,2]) //arguments[1]实现防抖函数(debounce)防抖函数原理:把触发十分频繁的事件合并成一次去执行 在指定工夫内只执行一次回调函数,如果在指定的工夫内又触发了该事件,则回调函数的执行工夫会基于此刻从新开始计算 防抖动和节流实质是不一样的。防抖动是将屡次执行变为最初一次执行,节流是将屡次执行变成每隔一段时间执行 eg. 像百度搜寻,就应该用防抖,当我连续不断输出时,不会发送申请;当我一段时间内不输出了,才会发送一次申请;如果小于这段时间持续输出的话,工夫会从新计算,也不会发送申请。手写简化版: // func是用户传入须要防抖的函数// wait是等待时间const debounce = (func, wait = 50) => { // 缓存一个定时器id let timer = 0 // 这里返回的函数是每次用户理论调用的防抖函数 // 如果曾经设定过定时器了就清空上一次的定时器 // 开始一个新的定时器,提早执行用户传入的办法 return function(...args) { if (timer) clearTimeout(timer) timer = setTimeout(() => { func.apply(this, args) }, wait) }}实用场景: ...

November 8, 2022 · 6 min · jiezi

关于javascript:写个JS深拷贝面试备用

深拷贝浅拷贝和赋值的原理及实现分析在工作中咱们常常会用到深拷贝与浅拷贝,然而你有没有去剖析什么场景下应用它,为什么须要应用呢,深浅拷贝有何异同呢,什么是深拷贝呢,如何实现呢,你会有这些问题吗,明天就为大家总结一下吧。 栈内存与堆内存区别浅拷贝---拷贝的是一个对象的指针,而不是复制对象自身,拷贝进去的对象共用一个指针,其中一个扭转了值,其余的也会同时扭转。深拷贝---拷贝进去一个新的对象,开拓一块新的空间,拷贝前后的对象互相独立,相互不会扭转,领有不同的指针。简略的总结下,假如有个A,咱们拷贝了一个为B,就是批改A或者B的时候看看另一个会不会也变动,如果扭转A的值B也变了那么就是浅拷贝,如果扭转A之后B的值没有发生变化就是深拷贝,当然这是根底了解,上面咱们一起来剖析下吧。 赋值/** demo1根本数据类型 */let a = 1;let b = a;b = 10;console.log(a,b)// 1 10/** demo2援用数据类型 */let a = { name: '小九', age: 23, favorite: ['吃饭','睡觉','打豆豆']}let b = a;a.name = '小七'a.age = 18a.favorite = ['下班','上班','加班']console.log(a,b)/** { name: '小七', age: 18, favorite: [ '下班', '上班', '加班' ] } { name: '小七', age: 18, favorite: [ '下班', '上班', '加班' ] }*/通过看下面的例子能够看出通过赋值去拿到新的值,赋值对于根本数据来说就是在栈中新开了一个变量,相当于是两个独立的栈内存,所以互相不会影响,然而对于援用数据类型,他只是复制了一份a在栈内存的指针,所以两个指针指向了同一个堆内存的空间,通过任何一个指针扭转值都会影响其余的,通过这样的赋值能够产生多个指针,然而堆内存的空间始终只有一个,这就是赋值产生的问题,咱们在开发中当然不心愿扭转B而影响了A,所以这个时候就须要用到浅拷贝和深拷贝了。 针对根本数据类型,轻易赋值都不会相互影响针对援用数据类型,赋值就会呈现咱们不想看到的,改变一方单方都变动。浅拷贝Object.assign()/** Object.assign */let A = { name: '小九', age: 23, sex: '男'}let B = Object.assign( {}, A);B.name = '小七'B.sex = '女'B.age = 18console.log(A,B)/** { name: '小九', age: 23, sex: '男' } { name: '小七', age: 18, sex: '女' } */首先实现浅拷贝的第一个办法是通过 Object.assign()这个 办法,Object.assign() 办法用于将所有可枚举属性的值从一个或多个源对象复制到指标对象。它将返回指标对象。 ...

November 8, 2022 · 6 min · jiezi

关于javascript:前端打工人的面试总结

v-model语法糖是怎么实现的<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <!-- v-model 只是语法糖而已 --> <!-- v-model 在外部为不同的输出元素应用不同的property并抛出不同的事件 --> <!-- text和textarea 元素应用value property 和 input事件 --> <!-- checkbox 和radio应用checked property 和 change事件--> <!-- select 字段将value 作为prop 并将change 作为事件 --> <!-- 留神:对于须要应用输入法(如中文、日文、韩文等)的语言,你将会发现v-model不会再输入法 组合文字过程中失去更新 --> <!-- 再一般标签上 --> <input v-model="sth" /> //这一行等于下一行 <input v-bind:value="sth" v-on:input="sth = $event.target.value" /> <!-- 再组件上 --> <currency-input v-model="price"></currentcy-input> <!--上行代码是上行的语法糖 <currency-input :value="price" @input="price = arguments[0]"></currency-input> --> <!-- 子组件定义 --> Vue.component('currency-input', { template: ` <span> <input ref="input" :value="value" @input="$emit('input', $event.target.value)" > </span> `, props: ['value'], }) </body></html>数字证书是什么?当初的办法也不肯定是平安的,因为没有方法确定失去的公钥就肯定是平安的公钥。可能存在一个中间人,截取了对方发给咱们的公钥,而后将他本人的公钥发送给咱们,当咱们应用他的公钥加密后发送的信息,就能够被他用本人的私钥解密。而后他伪装成咱们以同样的办法向对方发送信息,这样咱们的信息就被窃取了,然而本人还不晓得。为了解决这样的问题,能够应用数字证书。 ...

November 8, 2022 · 5 min · jiezi

关于javascript:从输入URL到渲染的完整过程

浏览器有一个重要的安全策略,称之为「同源策略」 其中,源=协定+主机+端口,**两个源雷同,称之为同源,两个源不同,称之为跨源或跨域 同源策略是指,若页面的源和页面运行过程中加载的源不统一时,出于平安思考,浏览器会对跨域的资源拜访进行一些限度 同源策略对 ajax 的跨域限度的最为凶狠,默认状况下,它不容许 ajax 拜访跨域资源 所以,咱们通常所说的跨域问题,就是同源策略对 ajax 产生的影响 有多种形式解决跨域问题,常见的有: 代理,罕用CORS,罕用JSONP无论应用哪一种形式,都是要让浏览器晓得,我这次跨域申请的是本人人,就不要拦挡了。 跨域解决办法1-代理对于前端开发而言,大部分的跨域问题,都是通过代理解决的 代理实用的场景是:生产环境不产生跨域,但开发环境产生跨域 因而,只须要在开发环境应用代理解决跨域即可,这种代理又称之为开发代理 在理论开发中,只须要对开发服务器稍加配置即可实现 // vue 的开发服务器代理配置// vue.config.jsmodule.exports = { devServer: { // 配置开发服务器 proxy: { // 配置代理 "/api": { // 若申请门路以 /api 结尾 target: "http://dev.taobao.com", // 将其转发到 http://dev.taobao.com }, }, },};跨域解决办法2-JSONP在CORS呈现之前,人们想了一种微妙的方法来实现跨域,这就是JSONP。 要实现JSONP,须要浏览器和服务器来一个浑然一体的绝妙配合。 JSONP的做法是:当须要跨域申请时,不应用AJAX,转而生成一个script元素去申请服务器,因为浏览器并不阻止script元素的申请,这样申请能够达到服务器。服务器拿到申请后,响应一段JS代码,这段代码实际上是一个函数调用,调用的是客户端事后生成好的函数,并把浏览器须要的数据作为参数传递到函数中,从而间接的把数据传递给客户端 JSONP有着显著的毛病,即其只能反对GET申请 跨域解决办法3-CORS概述CORS是基于http1.1的一种跨域解决方案,它的全称是Cross-Origin Resource Sharing,跨域资源共享。参考 前端进阶面试题具体解答 它的总体思路是:如果浏览器要跨域拜访服务器的资源,须要取得服务器的容许 而要晓得,一个申请能够附带很多信息,从而会对服务器造成不同水平的影响 比方有的申请只是获取一些新闻,有的申请会改变服务器的数据 针对不同的申请,CORS 规定了三种不同的交互模式,别离是: 简略申请须要预检的申请附带身份凭证的申请这三种模式从上到下层层递进,申请能够做的事越来越多,要求也越来越严格。 上面别离阐明三种申请模式的具体标准。 简略申请当浏览器端运行了一段 ajax 代码(无论是应用 XMLHttpRequest 还是 fetch api),浏览器会首先判断它属于哪一种申请模式 ...

November 8, 2022 · 2 min · jiezi

关于javascript:前端面试中小型公司都考些什么

两栏布局的实现个别两栏布局指的是右边一栏宽度固定,左边一栏宽度自适应,两栏布局的具体实现: 利用浮动,将右边元素宽度设置为200px,并且设置向左浮动。将左边元素的margin-left设置为200px,宽度设置为auto(默认为auto,撑满整个父元素)。.outer { height: 100px;}.left { float: left; width: 200px; background: tomato;}.right { margin-left: 200px; width: auto; background: gold;}利用浮动,左侧元素设置固定大小,并左浮动,右侧元素设置overflow: hidden; 这样左边就触发了BFC,BFC的区域不会与浮动元素产生重叠,所以两侧就不会产生重叠。.left{ width: 100px; height: 200px; background: red; float: left; } .right{ height: 300px; background: blue; overflow: hidden; }利用flex布局,将右边元素设置为固定宽度200px,将左边的元素设置为flex:1。.outer { display: flex; height: 100px;}.left { width: 200px; background: tomato;}.right { flex: 1; background: gold;}利用相对定位,将父级元素设置为绝对定位。右边元素设置为absolute定位,并且宽度设置为200px。将左边元素的margin-left的值设置为200px。.outer { position: relative; height: 100px;}.left { position: absolute; width: 200px; height: 100px; background: tomato;}.right { margin-left: 200px; background: gold;}利用相对定位,将父级元素设置为绝对定位。右边元素宽度设置为200px,左边元素设置为相对定位,右边定位为200px,其余方向定位为0。.outer { position: relative; height: 100px;}.left { width: 200px; background: tomato;}.right { position: absolute; top: 0; right: 0; bottom: 0; left: 200px; background: gold;}React 17 带来了哪些扭转最重要的是以下三点:新的 JSX 转换逻辑事件零碎重构Lane 模型的引入1. 重构 JSX 转换逻辑 ...

November 8, 2022 · 8 min · jiezi

关于javascript:从输入URL到渲染的过程中到底发生了什么

CDN缓存DNSTCP三次握手、四次挥手浏览器渲染过程输出URL到页面渲染过程的一些优化上面我将“从输出URL到渲染的全过程”大略的形容进去,再对其过程加以解释,理解过程中能够做哪些优化。文章内容有点长,须要有足够的急躁看完哟!!上面我要开始啦! 1、URL解析 2、DNS解析 3、建设TCP链接 4、客户端发送申请 5、服务器解决和响应申请 6、浏览器解析并渲染响应内容 7、TCP四次挥手断开连接 一、URL解析地址解析和编码咱们输出URL后,浏览器会解析输出的字符串,判断是URL还是搜寻关键字,如果是URL就开始编码。 一般来说URL只能应用英文字母、阿拉伯数字和某些标点符号,不能应用其余文字和符号,所以,如果URL中有文字就必须编码后应用。然而URL编码很凌乱,不同的操作系统、浏览器、网页字符集,会导致不同的编码后果。所以咱们须要应用JavaScript先对URL编码,而后提交给服务器,不给浏览器插手的机会。咱们通常会应用encodeURI()函数或者encodeURIComponent()函数来编码URL HSTSHSTS(HTTP Strict TransportSecurity)是一种新的Web平安协定,HSTS的作用是强制客户端应用HTTPS与服务器创立连贯。比方你在地址栏输出http://xxx/,浏览器会主动将http转写成https,而后间接向 https://xxx/ 发送申请。 缓存查看浏览器在发送申请之前先查看有没有缓存,过程如下: 浏览器会先去查看强缓存(Expires和cache-control)判断是否过期,如果强缓存失效,间接从缓存中读取资源;若不失效则进行协商缓存(Last-Modified / If-Modified-Since和Etag/If-None-Match),协商缓存由服务器决定是否应用缓存,若协商缓存生效,那么代表该申请的缓存生效,返回200,并从新返回资源和缓存标识,再次存入浏览器缓存中;失效则返回304,并从缓存中读取资源。(协商缓存之前要通过DNS域名解析,之后建设TCP链接) 那么浏览器缓存的地位在哪呢? Service Worker:浏览器独立线程进行缓存Memory Cache:内存缓存Disk Cache:硬盘缓存Push Cache:推送缓存(HTTP/2中的)留神:输出网址之后,会查找内存缓存,没有再找硬盘,都没有就产生网络申请。一般刷新(F5):因为TAB没有敞开,所以内存缓存可用,如果匹配上会被优先应用,其次是磁盘缓存强制刷新(Ctrl+F5):浏览器不应用缓存,因而发送的申请头均带有Cache-control:no-cache,服务器间接返回200和最新内容。 二、进行DNS解析DNS(1)、DNS:把域名和ip地址互相映射分布式数据库,让用户能更不便的拜访互联网,DNS协定运行在UDP协定之上 (2)、DNS解析:通过域名最终失去对应ip地址的过程。 (3)、DNS缓存:浏览器,操作系统,路由器,本地DNS,根域名服务器都会对DNS后果作出肯定的缓存 DNS解析过程(1)、首先搜寻浏览器本身的DNS缓存,有缓存间接返回; (2)、浏览器本身DNS不存在,浏览器就会调用一个相似gethostbyname的库函数,此函数会先去检测本地hosts文件,查看是否有对应ip。 (3)、如果本地hosts文件不存在映射关系,就会查问路由缓存,路由缓存不存在就去查找本地DNS服务器(个别TCP/IP参数里会设首选DNS服务器,通常是8.8.8.8)(客户端到本地DNS服务器是递归过程) (4)、如果本地DNS服务器还没找到就会向根服务器发出请求。(DNS服务器之间是迭代过程) 具体过程: 本地DNS服务器代咱们的浏览器发动迭代DNS解析申请,首先它会找根域的DNS的IP地址(寰球13台哟,惋惜中国没有!)。找到根域的DNS地址,就会向其发动申请(请问www.baidu.com这个域名的IP地址是多少呀?);根域发现这是一个顶级域com域的一个域名,于是通知本地DNS服务器我不晓得这个域名的IP地址,然而我晓得com域的IP地址,你去找它去吧;于是本地DNS服务器就失去了com域的IP地址,又向com域的IP地址发动了申请(请问www.baidu.com这个域名的IP地址是多少呀?),于是com域服务器通知本地DNS服务器我不晓得www.baidu.com这个域名的IP地址,然而我晓得baidu.com这个域的DNS地址,你去找它去;于是本地DNS服务器又向baidu.com这个域名的DNS地址(这个个别就是由域名注册商提供的,像万网,新网等)发动申请(请问www.baidu.com这个域名的IP地址是多少?),这个时候baidu.com域的DNS服务器一查,呀!果然在我这耶,于是就把找到的后果发送给本地DNS服务器;这个时候本地DNS服务器就拿到了www.baidu.com这个域名对应的IP地址。参考 前端进阶面试题具体解答 DNS优化DNS也是开销,通常浏览器查找一个给定域名的IP地址要花费20~120毫秒,在实现域名解析之前,浏览器不能从服务器加载到任何货色。那么如何缩小域名解析工夫,放慢页面加载速度呢? (1)、缩小DNS申请次数 (2)、DNS预获取,DOM还没开始,浏览器预解析地址,把解析好的地址放在本地缓存外面,DOM树生成完,要加载图片类的发现DNS曾经解析好了,再发送申请。<link rel='dns-prefetch'href='//dfns.tanx.com'> (次要对图片资源) (3)、DNS 查问的过程经验了很多的步骤,如果每次都如此,会消耗太多的工夫、资源。所以咱们应该尽早的返回实在的IP地址:(缩小查问过程,也就是DNS缓存。浏览器获取到IP地址后,个别都会缓存到浏览器的缓存中,本地的DNS缓存服务器,也能够去记录。另外,每天几亿网名的拜访需要,一秒钟几千万的申请域名服务器如何满足?就是DNS负载平衡。通常咱们的网站利用各种云服务,或者各种服务商提供相似的服务,由他们去帮咱们解决这些问题。 DNS零碎依据每台机器的负载量,地理位置的限度(长距离的传输效率)等等,去提供高效疾速的 DNS 解析服务。 (4)、当客户端DNS缓存(浏览器和操作系统)缓存为空时,DNS查找的数量与要加载的Web页面中惟一主机名的数量雷同,包含页面URL、脚本、样式表、图片、Flash对象等的主机名。缩小主机名的数量就能够缩小DNS查找的数量; (5)、缩小惟一主机名的数量会潜在缩小页面中并行下载的数量(HTTP1.1标准倡议从每个主机名并行下载两个组件,但实际上能够多个);然而缩小主机名和并行下载的计划会产生矛盾,须要大家本人衡量。倡议将组件放到至多两个但不多于4个主机名下,缩小DNS查找的同时也容许高度并行下载。DNS解析后会把域名的解析权交给cname()指向的内容散发(CDN)专用的DNS服务器。CDN专用的DNS服务器把CDN的全局负载平衡设施的ip地址返回给用户。 CDN举个例子:以前坐火车买票,都要到火车站买,所有人都去火车站买票,火车站售票厅的压力可想而知有多大。起初火车票代售点呈现了,散布在各个城市,城镇,咱们只须要去间隔咱们最近的火车票售卖点买票就能够了。卖火车票的代理售票点(缓存服务器),为买票者提供了不便,帮忙他们在最近的中央(最近的CDN节点),用最短的工夫(最短的申请工夫)买到票(拿到资源)。加重了售票大厅的压力(起到分流作用,加重服务器负载压力) CDN缓存:在浏览器本地缓存生效后,浏览器会像CDN边缘节点发动申请,相似浏览器缓存,CDN边缘节点也存在一套缓存机制, CDN边缘节点缓存策略因服务商不同而不同,通过http响应头中的cache-control:max-age字段设置CDN边缘节点数据缓存工夫。当浏览器向CDN节点申请数据时,CDN节点会判断缓存数据是否过期,若缓存数据过期,CDN会向服务器收回回源申请,从服务器拉取最新数据,更新本地缓存,并将最新数据返回给客户端,CDN服务商个别会提供基于文件后缀,目录多个维度来指定CDN缓存工夫,为用户提供更精细化的缓存治理。CDN工作形式:(1)、当你点击网站页面的url时,通过本DNS解析,DNS解析后会把域名的解析权交给cname()指向的内容散发专用的DNS服务器。内容散发专用的DNS服务器把内容散发的全局负载平衡(GSLB)设施的ip地址返回给用户。 (2)、当你向CDN的全局负载平衡设施的ip地址发动url拜访申请,CDN的全局负载平衡设施会为你抉择一台适合的缓存服务器提供服务。 抉择的根据:用户的ip地址,判断哪台服务器间隔用户最近,依据用户申请的url中携带的内容名称判断哪台服务器上有用户要的数据,查问各个服务器以后负载状况,判断哪台服务器有服务能力。调配:基于这些条件综合剖析后,区域负载平衡设施会向全局负载平衡设施申请返回一台缓存服务器的IP地址。全局负载平衡设施返回服务器IP地址,用户向缓存服务器发动申请,缓存服务器响应用户申请,将用户所需内容传送到用户终端,如果这台缓存服务器没有用户想要的内容,而区域平衡设施仍然将它调配给了用户,那么这台服务器就要向它的上一级缓存服务器申请内容,直至追溯到网站的源服务器将内容拉到本地。域名解析服务器依据用户ip地址,把域名解析成相应节点的缓存服务器ip地址,实现用户就近拜访,应用CDN服务的网站,只有将其域名解析权交给CDN的全局负载平衡设施,将须要散发的内容注入到CDN就能够实现内容减速了。CDN劣势:(1)、CDN节点解决了跨运营商和跨地区拜访的问题,拜访延时大大降低; (2)、大部分申请在CDN边缘节点实现,CDN起到分流作用,加重了源服务器的负载。CDN劣势(1)、当网站更新时,如果CDN节点上数据没有及时更新,即使用户在浏览器应用 Ctrl +F5 的形式使浏览器端的缓存生效,也会因为CDN边缘节点没有同步最新数据而导致用户拜访异样。 (2)、CDN不同的缓存工夫会对“回源率”产生间接的影响: 如果缓存工夫短,CDN边缘节点的内容常常生效,导致频繁回源。不仅减少服务器压力,也减少了用户拜访工夫。如果缓存工夫长,数据更新了,边缘节点的内容都还没更新,开发者对特定的工作做特定的数据缓存工夫治理。CDN刷新缓存CDN边缘节点对开发者是通明的,相比于浏览器Ctrl+F5的强制刷新来使浏览器本地缓存生效,开发者能够通过CDN服务商提供的“刷新缓存”接口来达到清理CDN边缘节点缓存的目标。这样开发者在更新数据后,能够应用“刷新缓存”性能来强制CDN节点上的数据缓存过期,保障客户端在拜访时,拉取到最新的数据。 |CDN优化(1)、前端须要被减速的文件大抵包含: js、css、图片、视频、和页面等文件。页面文件有动静和动态之分。这些文件和页面(比方html)最大的区别是:这些文件都是动态的,改变比拟小,这类动态文件适宜做CDN减速。咱们把这些动态文件通过CDN散发到世界各地的节点,用户能够在间隔最近的边缘节点拿到须要的内容,从而晋升内容下载速度放慢网页关上速度。页面分为动静页面和动态页面,动静页面不适宜做CDN缓存,因为页面是动静的话,内容的有效期就比拟沉闷。边缘节点的数据常常生效要回源,造成源服务器压力。(2)、缩小资源申请的等待时间 不同浏览器的并发数量不一样:IE11 、IE10 、chrome、Firefox 的并发连接数是 6个,IE9是10个。如果页面动态资源(图片等)过多(大于6个)会存在资源申请期待的状况。目前现实状况是大多用户带宽越来越大,然而咱们的动态资源并非那么大,很多文件都是几k或者几十k,6个文件加起来都小于带宽。这样就导致了资源的节约。 解决方案是:用多个不同IP的服务器来存储这些文件,并在页面中通过绝对路径的形式援用(要求同一IP的文件不超过6个)。这样就能够尽可能的缩小资源申请期待的状况。至此,你曾经获取到缓存服务器的IP地址,并且筹备向这个IP地址发送申请了。 三、建设TCP连贯TCP(1)、TCP是一种面向连贯的,牢靠的,基于字节流的传输层通信协议。 (2)、建设TCP连贯须要进行三次握手。过程如下: TCP握手过程(1)、客户端发送带有SYN标识(SYN=1,seq=x)的申请报文段,而后进入SYN_SEND状态,期待服务端确认; (2)、服务端接管到客户端SYN报文段后,须要发送ACK信息对这个SYN进行确认,同时还要发送本人的SYN信息(SYN=1,ACK=1,seq=y,ack=x+1)服务端把这些信息放在一个报文段中((SYN+ACK报文段),一并发给客户端,此时客户端进入SYN_RECV状态; (3)、客户端接管到服务端的SYN+ACK报文段后会向服务端发送ACK(ACK=1,seq=x+,ack=y+1)确认报文段,这个报文段发送后,客户端和服务端都进入ESTABLISHED状态,实现三次握手。为什么TCP建设肯定要三次呢?两次不行吗?起因: ...

November 8, 2022 · 1 min · jiezi

关于javascript:可选链操作符-空值合并运算符-的学习

明天学到了一些简洁代码的两个操作符: 1. 可选链操作符( ?. )可选链操作符( ?. )容许读取位于连贯对象链深处的属性的值,而不用明确验证链中的每个援用是否无效。?. 操作符的性能相似于 . 链式操作符,不同之处在于,在援用为空(null 或者 undefined) 的状况下不会引起谬误,该表达式短路返回值 let aa = { bb: { cc: 100 }}let ee = aa.bb?.cc;console.log(ee, 'ee')// 100 'ee'let dd = aa.bbb?.cc;console.log(dd, 'dd')// undefined 'dd'2. 空值合并操作符(??)空值合并操作符(??)是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。 let aa = { bb: { cc: 100 }}let dd = aa.bbb?.cc ?? 1234console.log(dd)// 1234

November 7, 2022 · 1 min · jiezi

关于javascript:手写vuerouter核心原理

最近也在察看vue3新个性,抽空玩一玩嵌套路由的vue-router,间接上代码 我的项目目录构造 代码展现app.vue<template> <div id="app"> <div> <router-link to="/">Index</router-link> | <router-link to="/person">Person</router-link> | <router-link to="/person/info">PersonInfo</router-link> </div> <!-- 一级路由 --> <router-view /> </div></template><style>#app{ display: flex; flex-direction: column; align-items: center;}</style>Index.vue<template> <div class="index"> <h1>this is index page</h1> </div></template>Person.vue<template> <div class="person"> <h1>this is person page</h1> <!-- 二级路由 --> <router-view /> </div></template>PersonInfo.vue<template> <div class="personInfo"> <h2>this is personInfo page</h2> </div></template>js文件main.jsimport Vue from 'vue'import App from './App.vue'import router from './router'new Vue({ router, render: h => h(App)}).$mount('#app')babel.config.js须要增加babel依赖反对新语法,如可选链npm install --save-dev @babel/core @babel/clinpm install --save-dev @babel/plugin-proposal-optional-chainingmodule.exports = { presets: [ '@babel/preset-env' ], plugins: ['@babel/plugin-proposal-optional-chaining']}router目录下文件index.jsimport Vue from "vue";import VueRouter from "./vue-router";import Index from "../views/Index.vue";import Person from "../views/Person.vue";import PersonInfo from "../views/PersonInfo.vue";Vue.use(VueRouter);const routes = [ { path: "/", name: "Index", component: Index }, { path: "/person", name: "Person", component: Person, children:[ { path: "/person/info", name: "PersonInfo", component: PersonInfo } ] }];const router = new VueRouter({ routes});export default router;参考视频解说:进入学习 ...

November 7, 2022 · 2 min · jiezi

关于javascript:细说JavaScript闭包

JavaScript 闭包难点分析一、作用域根本介绍ES6之前只有全局作用域与函数作用域两种,ES6呈现之后,新增了块级作用域1.全局作用域在JavaScript中,全局变量是挂载在window对象下的变量,所以在网页中的任何地位你都能够应用并且拜访到这个全局变量当咱们定义很多全局变量的时候,会容易引起变量命名的抵触,所以在定义变量的时候应该留神作用域的问题var globalName = 'global'function getName() { console.log(globalName) // global var name = 'inner' console.log(name) // inner}getName()console.log(name) // 报错console.log(globalName) // globalfunction setName() { vName = 'setName'}setName()console.log(vName) // setNameconsole.log(windwo.vName) // setName2.函数作用域在JavaScript中,函数定义的变量叫作函数变量,这个时候只能在函数外部能力拜访到它,所以它的作用域也就是函数的内存,称为函数作用域当这个函数被执行完之后,这个局部变量也相应会被销毁。所以你会看到在getName函数里面的name是拜访不到的function getName() { var name = 'inner' console.log(name) // inner}getName()console.log(name) // 报错3.块级作用域ES6新增了块级作用域,最间接的体现就是新增的let关键词,应用let关键词定义的变量只能在块级作用域中被拜访,有"暂时性死区"的特定,也就是说这个变量在定义之前是不能被应用的。if语句及for语句前面的{...}这外面所包含的,就是块级作用域console.log(a) // a is not definedif (true) { let a = '123' console.log(a) // 123}console.log(a) // a is not defined二、什么是闭包?红宝书:闭包是指有权拜访另外一个函数作用域中的变量的函数MDN:一个函数和对其四周状态的援用捆绑在一起(或者说函数被援用突围),这样的组合就是闭包。也就是说,闭包让你能够在一个内层函数中拜访到其外层函数的作用域。1.闭包的基本概念闭包其实就是一个能够拜访其余函数外部变量的函数。即一个定义在函数外部的函数,或者间接说闭包是个内嵌函数也能够。因为通常状况下,函数外部变量是无奈在内部拜访的(即全局变量和局部变量的区别),因而应用闭包的作用,就具备实现了能在内部拜访某个函数外部变量的性能,让这些外部变量的值始终能够保留在内存中。function fun1() { var a = 1 return function () { console.log(a) }}fun1()var result = fun1()result() // 12.闭包产生的起因当拜访一个变量时,代码解释器会首先在以后的作用域查找,如果没找到,就去父级作用域去查找,直到找到该变量或者不存在父级作用域中,这样的链路就是作用域链。var a = 1function fun1() { var a = 2 function fun2() { var a = 3 console.log(a) // 3 }}// fun1 函数的作用域指向全局作用域(window)和它本人自身;fun2 函数的作用域指向全局作用域(window)、fun1 和它自身;而作用域是从最底层向上找,直到找到全局作用域 window 为止,如果全局还没有的话就会报错function fun1() { var a = 2 function fun2() { console.log(a) // 2 } return fun2}var result = fun1()result()// 那是不是只有返回函数才算是产生了闭包呢?其实也不是,回到闭包的实质,**咱们只须要让父级作用域的援用存在即可**var fun3function fun1() { var a = 2 fun3 = function () { console.log(a) }}fun1()fun3()参考视频解说:进入学习 ...

November 7, 2022 · 2 min · jiezi

关于javascript:细说Js中的this

为什么应用this先看个例子: function identity() { return this.name.toUpperCase();}function speak() { return "Hello, i'm " + identity.call(this);}var me = { name: 'rod chen'}var you = { name: "others in Aug"}console.log(identity.call(me)); //ROD CHENconsole.log(identity.call(you)); //OTHERS IN AUGconsole.log(speak.call(me)); //Hello, i'm ROD CHEN console.log(speak.call(you)); //Hello, i'm OTHERS IN AUG输入的后果很显著,对于call的用法后面文章有提到,第一个参数就是传入到函数里的this的值。这段代码能够在不同的上下文对象( me 和 you )中重复使用函数 identify() 和 speak() ,如果咱们不实用this的话,那就须要identity和speak显示传入一个上下文对象,就像上面的形式 function identity(context) { return context.name.toUpperCase();}function speak(context) { return "Hello, i'm " + identity(context);}var me = { name: 'rod chen'}var you = { name: "others in Aug"}console.log(identity(me));console.log(identity(you));console.log(speak(me));console.log(speak(you));总结: this 提供了一种更优雅的形式来隐式“传递”一个对象援用,因而能够将API设计得更加简洁并且易于复用。随着应用模式越来越简单,显式传递上下文对象会让代码变得越来越凌乱,应用 this 则不会这样 ...

November 7, 2022 · 6 min · jiezi

关于javascript:又是一年立冬时节消防安全知识答题小程序v30千呼万唤始出来

此去经年,又是一年立冬季节。回首过来,优质的消防安全常识竞答流动小程序v1.0刚进去,就收到了不少好评,我随即把源码分享进去。 过后正值立冬,“雪花飘飘北风萧萧~” v1.0首页、答题页、后果页实现页面间跳转性能实现转发分享答题问题性能实现用云开发实现查问题库性能实现动静题目数据绑定答题交互逻辑切换下一题提交答卷保留到云数据库汇合零碎主动判分答题后果页从云数据库查问答题问题界面截图 起初,我感觉v1.0尽管页面成果比拟优质,还是性能上比拟繁难的前端版,而后快马加急把云开发能力补上,并在在1.0的根底上更加欠缺了一下,麻雀虽小,前后端数据库俱全了。 过后是:*“真情像梅花开过冷冷冰雪不能吞没就在最冷枝头绽开看见春天走向你我”* 基于云开发的答题流动小程序v2.0,终于赶在11月最初一天实现了。 v2.0答题记录列表页登录页流动规定页题库随机抽题查问历史问题微信受权登录获取微信头像和昵称排行榜等先看看成果吧 防火平安常识专项学习与竞答 11月是全国“119”消防宣传月,不少企事业单位会举办消防安全常识比赛,因而我搭建了最新版的消防安全常识答题流动小程序。 它基于微信原生小程序+云开发实现。提炼了典型的业务模型,它能够帮忙你疾速搭建各种模式的答题软件产品。 置信不论你的需要是什么,本我的项目都能帮忙到你。 系列教程还写了手把手教你搭建答题流动小程序系列文章,用以帮忙初学者疾速入门云开发。 感兴趣的能够去我主页翻看系列文章,这里就不一一列举进去了。 工夫回到以后,又是一年立冬季节,消防安全常识答题小程序v3.0千呼万唤始进去。当初许下的承诺,都将一一去实现。 *“一剪寒梅傲立雪中只为伊人飘香”* v3.0已实现注册登录页 √题库学习 √反对单选、判断题型 √错题集 √查看所有用户的答题记录-管理员 √查看用户的答题问题以及答题状况-管理员 √后盾数据监控-管理员 √后盾治理-管理员 √防火平安常识专项学习与竞答 防火平安常识专项学习与竞答 防火平安常识专项学习与竞答 若想在短期内,进行消防安全常识的流传,那么答题无疑是无效形式之一。

November 7, 2022 · 1 min · jiezi

关于javascript:那些年面挂的js手写题

数组去重办法汇总首先:我晓得多少种去重形式1. 双层 for 循环 function distinct(arr) { for (let i=0, len=arr.length; i<len; i++) { for (let j=i+1; j<len; j++) { if (arr[i] == arr[j]) { arr.splice(j, 1); // splice 会扭转数组长度,所以要将数组长度 len 和下标 j 减一 len--; j--; } } } return arr;}思维: 双重 for 循环是比拟蠢笨的办法,它实现的原理很简略:先定义一个蕴含原始数组第一个元素的数组,而后遍历原始数组,将原始数组中的每个元素与新数组中的每个元素进行比对,如果不反复则增加到新数组中,最初返回新数组;因为它的工夫复杂度是O(n^2),如果数组长度很大,效率会很低2. Array.filter() 加 indexOf/includes function distinct(a, b) { let arr = a.concat(b); return arr.filter((item, index)=> { //return arr.indexOf(item) === index return arr.includes(item) })}思维: 利用indexOf检测元素在数组中第一次呈现的地位是否和元素当初的地位相等,如果不等则阐明该元素是反复元素3. ES6 中的 Set 去重 ...

November 7, 2022 · 6 min · jiezi

关于javascript:从零开始实现一个Promise

1.Promise产生背景及标准家喻户晓,Promise是ES6引入的新个性,旨在解决回调天堂。上面是一个简略的例子:管制接口调用程序: apiA-->apiB-->apiC。简单的业务,开发人员会裂开。后生在此向老前辈致敬。 // 回调天堂apiA({ handleSuccess(resA){ apiB({ handleSuccess(resB){ apiC({ handleSuccess(resC){ } }) } }) }})因而Promise/A+标准应运而生,ES6的Promise就是遵循标准开发进去的。 2. 同步Promise浏览标准可得上面几点根本要求: Promise存在三个状态:pending(期待态)、fulfilled(胜利态)、rejected(失败态)pending为初始态,并能够转化为fulfilled和rejected胜利时,不可转为其余状态,且必须有一个不可扭转的值(value)失败时,不可转为其余状态,且必须有一个不可扭转的起因(reason)new Promise(executor=(resolve,reject)=>{resolve(value)}),resolve(value)将状态置为 fulfillednew Promise(executor=(resolve,reject)=>{reject(reson)}),reject(reson)将状态置为 rejected若是executor运行异样执行reject()thenable:then(onFulfilled, onRejected) onFulfilled:status为fulfilled,执行onFulfilled,传入valueonRejected:status为rejected,执行onRejected,传入reason// 1.Promise存在三个状态:pending(期待态)、fulfilled(胜利态)、rejected(失败态)const STATUS_PENDING = 'pending'const STATUS_FULFILLED = 'fulfilled'const STATUS_REJECTED = 'rejected'class myPromise { constructor(executor) { // pending为初始态,并能够转化为fulfilled和rejected this.status = STATUS_PENDING this.value = '' // 3 this.reason = '' // 4 let resolve = value => { // 5. if (this.status === STATUS_PENDING) { this.status = STATUS_FULFILLED this.value = value } } let reject = reason => { //6. if (this.status === STATUS_PENDING) { this.status = STATUS_REJECTED this.reason = reason } } // 7. try { executor(resolve, reject); } catch (err) { reject(err); } } // 8. then(onFulfilled = () => {}, onRejected = () => {}) { // 8.1 if (this.status === STATUS_FULFILLED) { onFulfilled(this.value) } // 8.2 if (this.status === STATUS_REJECTED) { onRejected(this.reason) } }}new myPromise(resolve => { console.log('before resolve') resolve(1)}).then(res => { console.log(res)})new myPromise((resolve, reject) => { console.log('before reject') reject('reject error')}).then(res => { console.log(res)}, error => { console.log(error)})参考 前端手写面试题具体解答 ...

November 7, 2022 · 5 min · jiezi

关于javascript:nodexlsx-简单几行代码处理导入导出-excel-表格数据免费开源的-javascript-工具库

最近开发的我的项目上须要把数据导出为 xlsx 文档,找了一圈,发现 node-xlsx 简略好用,分享给各位。 对于 node-xlsx在 web 开发中,治理后盾生成 excel 报表并且下载,一个很罕用的性能,很多 javascript 开发者也提供了很多的这方面的工具卡来实现这一性能。明天介绍的 node-xlsx 就是一个基于 node.js 和 SheetJS 、解决 xlsx 格局的工具库。 node-xlsx 的技术个性底层基于弱小的 SheetJS 构建,对 xlsx 文档的格局兼容性足够好反对导出和读取 xlsx 文档,一个工具库解决导入导出需要只有少数几个 api ,应用非常简单开发上手体验最近在做电商后盾的订单治理局部,须要将订单数据导出给经营共事,也须要导入解决好的订单报表。尽管之前也钻研过用纯 javascript 来实现导出 excel 表格,但倒进去的文档的兼容性很难保障。 找了一圈,发现 node-xlsx 这个工具库,刚好可能满足性能的需要:报表字段绝对简略,没有过多数据嵌套。 须要留神的是,node-xlsx 是一个 node.js 库,只能通过 npm 装置,在服务端应用: 而后在我的项目中引入,就能够应用了。上面的代码是通过读取二进制文件或者 buffer 来解决导入的 xlsx 文档: 默认数据的第一行就是表头,node-xlsx 还反对设定每一列的宽度和合并单元格,这样基本上就能输入数据报表了,就这么几个 api,应用非常简单! node-xlsx 只能解决构造绝对简略的数据文档,如果数据格式比较复杂,能够到 SheetJS 去查问数据格式的解决办法。不过如果想要设置单元格款式这样的性能,node-xlsx 可能就满足不了了。 收费开源阐明node-xlsx 是一个基于 SheetJS 构建的收费工具库,运行在 node.js 服务上,node-xlsx 和 SheetJS 的源码都基于 apache 2.0 开源协定托管在 Github 上,任何集体和公司都能够收费下载应用,也能够用在商业我的项目上。 ...

November 7, 2022 · 1 min · jiezi

关于javascript:一文总结JavaScript手写面试题

模板引擎实现let template = '我是{{name}},年龄{{age}},性别{{sex}}';let data = { name: '姓名', age: 18}render(template, data); // 我是姓名,年龄18,性别undefinedfunction render(template, data) { const reg = /\{\{(\w+)\}\}/; // 模板字符串正则 if (reg.test(template)) { // 判断模板里是否有模板字符串 const name = reg.exec(template)[1]; // 查找以后模板里第一个模板字符串的字段 template = template.replace(reg, data[name]); // 将第一个模板字符串渲染 return render(template, data); // 递归的渲染并返回渲染后的构造 } return template; // 如果模板没有模板字符串间接返回}原型继承这里只写寄生组合继承了,两头还有几个演变过去的继承但都有一些缺点 function Parent() { this.name = 'parent';}function Child() { Parent.call(this); this.type = 'children';}Child.prototype = Object.create(Parent.prototype);Child.prototype.constructor = Child;手写 Promise.race该办法的参数是 Promise 实例数组, 而后其 then 注册的回调办法是数组中的某一个 Promise 的状态变为 fulfilled 的时候就执行. 因为 Promise 的状态只能扭转一次, 那么咱们只须要把 Promise.race 中产生的 Promise 对象的 resolve 办法, 注入到数组中的每一个 Promise 实例中的回调函数中即可. ...

November 7, 2022 · 9 min · jiezi

关于javascript:从零手写reactrouter

蛮多同学可能会感觉react-router很简单, 说用都还没用明确, 还从0实现一个react-router, 其实router并不简单哈, 甚至说你看了这篇博客当前, 你都会感觉router的外围原理也就那么回事至于react-router帮忙咱们实现了什么货色我就不过多论述了, 这个间接移步官网文档, 咱们上面间接聊实现 另外: react-router源码有依赖两个库path-to-regexp和history, 所以我这里也就间接引入这两个库了,尽管上面我都会讲到根本应用, 然而同学有工夫的话还是能够浏览以下官网文档 还有一个须要留神的点是: 上面我书写的router原理都是应用hooks + 函数组件来书写的, 而官网是应用类组件书写的, 所以如果你对hooks还不是很明确的话, 得去补一下这方面的常识, 为什么要抉择hooks, 因为当初绝大多数大厂在react上根本都在鼎力举荐应用hook, 所以咱们得跟上时代不是, 而且我着重和大家聊的也是原理, 而不是跟官网截然不同的源码, 如果要1比1的复刻源码不带本人的了解的话, 那你去看官网的源码就行了, 何必看这篇博文了 在本栏博客中, 咱们会聊聊以下内容: 封装本人的生成match对象办法history库的应用Router和BrowserRouter的实现Route组件的实现Switch和Redirect的实现withRouter的实现Link和NavLink实现聚合api封装本人的生成match对象办法在封装之前, 我想跟大家先分享path-to-regexp这个库 为什么要先聊这个库哈, 次要起因是因为react-router中用到了这个库, 我看了一下其实咱们也没必要本人再去实现一个这个库(为什么没必要呢,倒并不是因为react-router没有实现咱们就不实现, 而是因为这个库实现的性能非常简单, 然而细节十分繁琐, 有十分多的因素须要去思考到我感觉没必要), 这个库做的事件非常简单: 将一个字符串变成一个正则表达式咱们晓得, react-router的大抵原理就是依据门路的不同从而渲染不同的页面, 那么这个过程其实也就是门路A匹配页面B的过程, 所以咱们之前会写这样的代码 <Route path="/news/:id" component={News} /> // 如果门路匹配上了/news/:id这样的门路, 则渲染News组件那么react-router他是怎么去判断浏览器地址栏的门路和这个Route组件中的path属性匹配上的? path填写的如果是/news/:id这样的门路, 那么/news/123 /news/321这种都可能被react-router匹配上 咱们可能想到的办法是不是大略能够如下: 将所有的path属性全副转换为正则表达式(比方/news/:id转换为/^\/news(?:\/([^\/#\?]+?))[\/#\?]?$/i), 而后将地址栏的path值取出来跟该正则表达式进行匹配, 匹配上了就要渲染相应的路由, 匹配不上就渲染其余的逻辑path-to-regexp就是做这个事件的, 他把咱们给他的门路字符串转换为正则表达式, 供咱们匹配 装置: yarn add path-to-regexp -S// 咱们能够来轻易试试这个库import { pathToRegexp } from "path-to-regexp";const keys = [];// pathToRegexp(path, keys?, options?)// path: 就是咱们要匹配的门路规定// keys: 如果你传递了, 当他匹配上当前, 会把绝对应的参数key传递到keys数组中// options: 给path门路规定的一些附加规定, 比方sensitive大小写敏感之类的const result = pathToRegexp("/news/:id", keys);console.log("result", result);console.log(result.exec("/news/123")); // 输入 ["/news/123", "123", index: 0, input: "/news/123", groups: undefined]console.log(result.exec("/news/details/123")); // 输入nullconsole.log(keys); // 输入一个数组, 数组的有一个对象{modifier: " name: "id", pattern: "[^\/#\?]+?", prefix: "/", suffix: ""}当然, 这个库还有很多玩法, 他也不是专门为react-router实现的, 只是刚好被react-router拿过去用了, 对这个库有趣味的同学能够去看看他的文档 ...

November 7, 2022 · 8 min · jiezi

关于javascript:精读迭代器-Iterable

本周精读的文章是 Iterables 与 Iteration protocols,依照为什么须要迭代器、迭代器是如何设计的,咱们还能怎么利用迭代器开展来讲。 概述为什么须要迭代器因为用 for ... of 循环数组十分不便,但如果仅数组才反对这个语法就太过于麻烦了,比方咱们天然会心愿 for ... of 能够遍历字符串的每个字符,心愿 new Set([1, 2, 3]) 能够疾速初始化一个新的 Set。 以上提到的能力 JS 都反对,那么为什么 JS 引擎晓得字符串该如何遍历?如何晓得数组 [1, 2, 3] 与 Set 类型每一个 Key 之间的对应关系?实现这些性能背地的原理就是迭代器(Iterables)。 因为 Array、Set 都是可迭代的,所以他们都能够被 for ... of 遍历,JS 引擎也天然晓得他们之间互相转换的关系。 迭代器是如何设计的有两种定义迭代器的办法,别离是独立定义与合并在对象里定义。 独立定义为对象拓展 [Symbol.iterator] 属性即可。之所以标准采纳 [Symbol.iterator] 是为了避免一般的字面量 Key 与对象本身的 OwnProperties 抵触: const obj = {}obj[Symbol.iterator] = function() { return { someValue: 1, next() { // 可通过 this.someValue 拜访与批改该值,可定义任意数量的变量作为迭代过程中的辅助变量 if (...) { return { done: false, value: this.current++ } // 示意迭代还没完,以后值为 value } return { done: true } // 示意迭代结束 } };};在 for ... of 时,只有没有读到 done: true 就会始终循环。 ...

November 7, 2022 · 3 min · jiezi

关于javascript:前端工程师面试题自检

将虚构 Dom 转化为实在 Dom题目形容:JSON 格局的虚构 Dom 怎么转换成实在 Dom { tag: 'DIV', attrs:{ id:'app' }, children: [ { tag: 'SPAN', children: [ { tag: 'A', children: [] } ] }, { tag: 'SPAN', children: [ { tag: 'A', children: [] }, { tag: 'A', children: [] } ] } ]}把上诉虚构Dom转化成下方实在Dom<div id="app"> <span> <a></a> </span> <span> <a></a> <a></a> </span></div>实现代码如下: // 真正的渲染函数function _render(vnode) { // 如果是数字类型转化为字符串 if (typeof vnode === "number") { vnode = String(vnode); } // 字符串类型间接就是文本节点 if (typeof vnode === "string") { return document.createTextNode(vnode); } // 一般DOM const dom = document.createElement(vnode.tag); if (vnode.attrs) { // 遍历属性 Object.keys(vnode.attrs).forEach((key) => { const value = vnode.attrs[key]; dom.setAttribute(key, value); }); } // 子数组进行递归操作 vnode.children.forEach((child) => dom.appendChild(_render(child))); return dom;}说说Vue2.0和Vue3.0有什么区别重构响应式零碎,应用Proxy替换Object.defineProperty,应用Proxy劣势: ...

November 7, 2022 · 10 min · jiezi

关于javascript:三次握手与四次挥的问题怎么回答

在面试中,三次握手和四次挥手能够说是问的最频繁的一个知识点了,我置信大家也都看过很多对于三次握手与四次挥手的文章,明天的这篇文章,重点是围绕着面试,咱们应该把握哪些比拟重要的点,哪些是比拟被面试官给问到的,我感觉如果你能把我上面列举的一些点都记住、了解,我想就差不多了。 三次握手因为在面试中,三次握手是被问的最频繁的面试题,所以本次咱们从面试的角度来解说三次握手当面试官问你为什么须要有三次握手、三次握手的作用、讲讲三次三次握手的时候,我想很多人会这样答复: 首先很多人会先讲下握手的过程: 1、第一次握手:客户端给服务器发送一个 SYN 报文。 2、第二次握手:服务器收到 SYN 报文之后,会应答一个 SYN+ACK 报文。 3、第三次握手:客户端收到 SYN+ACK 报文之后,会回应一个 ACK 报文。 4、服务器收到 ACK 报文之后,三次握手建设实现。 作用是为了确认单方的接管与发送能力是否失常。 这里我顺便解释一下为啥只有三次握手能力确认单方的承受与发送能力是否失常,而两次却不能够: 第一次握手:客户端发送网络包,服务端收到了。这样服务端就能得出结论:客户端的发送能力、服务端的接管能力是失常的。 第二次握手:服务端发包,客户端收到了。这样客户端就能得出结论:服务端的接管、发送能力,客户端的接管、发送能力是失常的。不过此时服务器并不能确认客户端的接管能力是否失常。 第三次握手:客户端发包,服务端收到了。这样服务端就能得出结论:客户端的接管、发送能力失常,服务器本人的发送、接管能力也失常。 因而,须要三次握手能力确认单方的接管与发送能力是否失常。 这样答复其实也是能够的,但我感觉,这个过程的咱们应该要形容的更具体一点,因为三次握手的过程中,单方是由很多状态的扭转的,而这些状态,也是面试官可能会问的点。所以我感觉在答复三次握手的时候,咱们应该要形容的具体一点,而且形容的具体一点意味着能够扯久一点。加分的形容我感觉应该是这样: 刚开始客户端处于 closed 的状态,服务端处于 listen 状态。而后 1、第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 SN(c)。此时客户端处于 SYN_Send 状态。 2、第二次握手:服务器收到客户端的 SYN 报文之后,会以本人的 SYN 报文作为应答,并且也是指定了本人的初始化序列号 ISN(s),同时会把客户端的 ISN + 1 作为 ACK 的值,示意本人曾经收到了客户端的 SYN,此时服务器处于 SYN_REVD 的状态。 3、第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,示意曾经收到了服务端的 SYN 报文,此时客户端处于 establised 状态。 4、服务器收到 ACK 报文之后,也处于 establised 状态,此时,单方以建设起了链接。 ...

November 7, 2022 · 2 min · jiezi

关于javascript:诚意满满的前端面试总结

强类型语言和弱类型语言的区别强类型语言:强类型语言也称为强类型定义语言,是一种总是强制类型定义的语言,要求变量的应用要严格合乎定义,所有变量都必须先定义后应用。Java和C++等语言都是强制类型定义的,也就是说,一旦一个变量被指定了某个数据类型,如果不通过强制转换,那么它就永远是这个数据类型了。例如你有一个整数,如果不显式地进行转换,你不能将其视为一个字符串。弱类型语言:弱类型语言也称为弱类型定义语言,与强类型定义相同。JavaScript语言就属于弱类型语言。简略了解就是一种变量类型能够被疏忽的语言。比方JavaScript是弱类型定义的,在JavaScript中就能够将字符串'12'和整数3进行连贯失去字符串'123',在相加的时候会进行强制类型转换。两者比照:强类型语言在速度上可能略逊色于弱类型语言,然而强类型语言带来的严谨性能够无效地帮忙防止许多谬误。 说一下HTTP和HTTPS协定的区别?1、HTTPS协定须要CA证书,费用较高;而HTTP协定不须要2、HTTP协定是超文本传输协定,信息是明文传输的,HTTPS则是具备安全性的SSL加密传输协定;3、应用不同的连贯形式,端口也不同,HTTP协定端口是80,HTTPS协定端口是443;4、HTTP协定连贯很简略,是无状态的;HTTPS协定是具备SSL和HTTP协定构建的可进行加密传输、身份认证的网络协议,比HTTP更加平安说一下购物车的逻辑?//vue中购物车逻辑的实现1. 购物车信息用一个数组来存储,数组中保留对象,对象中有id和count属性2. 在vuex中state中增加一个数据 cartList 用来保留这个数组3. 因为商品详情页须要用到退出购物车性能,所以咱们须要提供一个mutation, 用来将购物车信息退出 cartList中4. 退出购物车信息的时候,遵循如下规定: 如果购物车中曾经有了该商品信息,则数量累加,如果没有该商品信息,则新增一个对象5. 在商品详情页,点击退出购物车按钮的时候,调用vuex提供的addToCart这个mutation将以后的商品信息 (id count)传给addTocart this.$store.commit("addToCart", {id: , count:})// js中购物车逻辑的实现1.商品页点击“退出购物车”按钮,触发事件2.事件调用购物车“减少商品”的Js程序(函数、对象办法)3.向Js程序传递传递“商品id”、“商品数量”等数据4.存储“商品id”、“商品数量”到浏览器的localStorage中**展现购物车中的商品******1.关上购物车页面2.从localStorage中取出“商品Id”、“商品数量”等信息。3.调用服务器端“取得商品详情”的接口失去购物车中的商品信息(参数为商品Id)4.将取得的商品信息显示在购物车页面。**实现购物车中商品的购买******1.用户对购物车中的商品实现购买流程,产生购物订单2.革除localStorage中存储的曾经购买的商品信息备注1:购物车中商品存储的数据除了“商品id”、“商品数量”之外,依据产品要求还能够有其余的信息,例如残缺的商品详情(这样就不必掉服务器接口取得详情了)、购物车商品的过期工夫,超过工夫的购物车商品在下次关上网站或者购物车页面时被革除。备注2:购物车商品除了存储在localStorage中,依据产品的需要不同,也能够存储在sessionStorage、cookie、session中,或者间接向服务器接口发动申请存储在服务器上。何种状况应用哪种形式存储、有啥区别请本人剖析。实现数组原型办法forEach语法:arr.forEach(callback(currentValue [, index [, array]])[, thisArg]) 参数: callback:为数组中每个元素执行的函数,该函数承受1-3个参数currentValue: 数组中正在解决的以后元素index(可选): 数组中正在解决的以后元素的索引array(可选): forEach() 办法正在操作的数组 thisArg(可选): 当执行回调函数 callback 时,用作 this 的值。 返回值:undefined Array.prototype.forEach1 = function(callback, thisArg) { if(this == null) { throw new TypeError('this is null or not defined'); } if(typeof callback !== "function") { throw new TypeError(callback + 'is not a function'); } // 创立一个新的 Object 对象。该对象将会包裹(wrapper)传入的参数 this(以后数组)。 const O = Object(this); // O.length >>> 0 无符号右移 0 位 // 意义:为了保障转换后的值为正整数。 // 其实底层做了 2 层转换,第一是非 number 转成 number 类型,第二是将 number 转成 Uint32 类型 const len = O.length >>> 0; let k = 0; while(k < len) { if(k in O) { callback.call(thisArg, O[k], k, O); } k++; }}map语法: arr.map(callback(currentValue [, index [, array]])[, thisArg]) ...

November 7, 2022 · 9 min · jiezi

关于javascript:从URL输入到页面展现到底发生什么

从开发&运维角度方面来看,总体来说分为以下几个过程: DNS 解析:将域名解析成 IP 地址TCP 连贯:TCP 三次握手发送 HTTP 申请服务器解决申请并返回 HTTP 报文浏览器解析渲染页面断开连接:TCP 四次挥手一、什么是URL?URL(Uniform Resource Locator),对立资源定位符,用于定位互联网上资源,俗称网址。 scheme: // host.domain:port / path / filename ? abc = 123 # 456789 scheme - 定义因特网服务的类型。常见的协定有 http、https、ftp、file, 其中最常见的类型是 http,而 https 则是进行加密的网络传输。host - 定义域主机(http 的默认主机是 www)domain - 定义因特网域名,比方 baidu.comport - 定义主机上的端口号(http 的默认端口号是 80)path - 定义服务器上的门路(如果省略,则文档必须位于网站的根目录中)。filename - 定义文档/资源的名称query - 即查问参数fragment - 即 # 后的hash值,个别用来定位到某个地位二、DNS域名解析在浏览器输出网址后,首先要通过域名解析,因为浏览器并不能间接通过域名找到对应的服务器,而是要通过 IP 地址。 IP 地址IP 地址是指互联网协议地址,是 IP Address 的缩写。IP 地址是 IP 协定提供的一种对立的地址格局,它为互联网上的每一个网络和每一台主机调配一个逻辑地址,以此来屏蔽物理地址的差别。什么是域名解析DNS 协定提供通过域名查找 IP 地址,或逆向从 IP 地址反查域名的服务。DNS 是一个网络服务器,咱们的域名解析简略来说就是在 DNS 上记录一条信息记录。浏览器如何通过域名去查问 URL 对应的 IP 呢?DNS域名解析分为递归查问和迭代查问两种形式,现个别为迭代查问。 ...

November 7, 2022 · 2 min · jiezi

关于javascript:复习-nodejs接口案例

其实温习一次的作用实在太大了,真的,自从上次ajax开始其实就开始i有点懵懵懂懂的感觉,始终拖想到了node在去回顾一遍,这一次回去温习,ajax曾经很纯熟了,node之前搞不懂那些原理也顺分明了好多,其实这次温习没有什么须要说的知识点,因为要说的后面都说过了,我来说一下这个做的一个大我的项目吧,这个我的项目真的,应该是我不纯熟的违心那边,就是用express写接口,用postman来测试,三个模块,三个数据库,基本上都在我的代码外面了,写的很具体步骤,用到的技术,基本上是用node的express模块,去写接口,而后中途中到了一些中间件,比方规定语义规定的joi,比方给明码解码加密的bcryptjs,我做了一天才做下来这一个案例 一个我的项目初试化,首先要创建一个独自的我的项目文件夹,而后终端npm init间接装置package.json,api.js接口文件,路由模块创建一个文件夹夹,路由函数又要分为一个模块,再把数据库创建好,根本就能够开始实现性能需要了,用后端node实现增删改查 我的项目文件分类: 1 接口文件 // 1.初始化// 1.1创立我的项目const express = require('express')const app = express()// 1.2配置跨域const cors = require('cors')app.use(cors())// 1.3配置解析表单中间件// 谬误点:记住要有参数app.use(express.urlencoded({extended : false}))// 2.3因为前面处理函数用到了很多res.send所以封装为一个全局中间件,给res绑定一个函数,那前面的中间件路由都能够用到这个函数了app.use((req, res, next) => { res.cc = function(err, status = 1) { res.send({ status, msg : err instanceof Error ? err.message : err }) } next()})// 2.4.6配置解析token的中间件const expressJWT = require('express-jwt')const secretKey = require('./secretKey')app.use(expressJWT({secret : secretKey.secretKey, algorithms : ['HS256']}).unless({path : [/^\/api\//]}))// 1.4.4导入路由模块const routerUser = require('./router/user')const Joi = require('joi')const { expressjwt } = require('express-jwt')const { path } = require('express/lib/application')app.use('/api', routerUser)// 3.1.1集体核心路由导入const infoRouter = require('./router/userinfo')app.use('/my', infoRouter)// 4.1.2文章治理导入const article = require('./router/acticle')app.use('/my/article', article)// 5.1.2公布文章路由导入const cates = require('./router/cate')app.use('/my/article', cates)// 2.2.3定义规定joi的谬误级别中间件app.use((err, req, res, next) => { if (err instanceof Joi.ValidationError) return res.send(err.message) // 2.4.7减少jwt谬误中间件 if (err.name == 'UnauthorizedError') return res.cc('身份认证失败') return res.send('其余谬误')})app.listen(80, () => { console.log('http://127.0.0.1');})2. ...

November 6, 2022 · 6 min · jiezi

关于javascript:我没想到做IT还有感动众生的机会

文 / 明道云创始人任向晖 年老的时候爱好文艺,还空想着用文艺感召人心。惋惜从未有机会承受过正规的艺术教育,文化程度也低,命运之门打不开,只好不了了之。一晃到了中年,到了不能再改行的年纪,发现自己所在的IT行业和年老时的幻想曾经离题万里了。倒不是说IT行业没有激动人心的事件,只是它确实只来自极少数的闪光时刻,比方1995年的Windows 95,2007年的iPhone。 我做的还是IT行业中最干燥无趣的企业软件畛域。张嘴零碎架构,闭嘴数据模型,咱们简直影响不了普通人,面对客户,咱们也是以讲道理为主。好在年长之后,也没有那么悸动的心,相安无事很多年。 然而,做明道云零代码的几年中,心中却常常荡起了一些小波澜。咱们开始意识到,IT本不该这么无趣,企业软件用户的心智也并非死水一潭。咱们能够让简单的企业产品设计折射出一点点兽性,就像我每次看到波音747和它微小的引擎时,咱们不会感觉到任何简单的俊俏,相同是一种独特和常见的美感。 技术对社会的影响都能够概括为对普通人的凋谢,对应用门槛的升高。Windows是这样,iPhone是这样,半个世纪前的喷气式大型客机也是这样。明天,咱们所在的企业软件市场,可能比任何时候都须要实现这样的转变。凭什么咱们花几块钱就可能玩趣味横生的手机游戏,用抖音就能剪辑发表乏味的Vlog,用手机拍照软件人人都能拍出美照,为什么到了企业软件世界,就不能人人做出本人想要的利用呢? 仅仅有雄心壮志,打动的只是本人,而不是别人。所以真正的成就感只能来自用户市场的实证。我说的小波澜正是这些出其不意的成绩。这两年,咱们看到了各行各业的非IT人员对零代码产品的神奇用法。在我印象中,做出神奇成果的用户包含财务、人事、销售、营销这样的业务岗位人员,还有医生、生化专家、机械专家、律师、会计师、设计师这样的专业人士。我还遇到了文艺范满满的电影导演、广告创意人员。他们会十分骄傲地向我展现他们搭建的利用,当然也不乏对咱们产品的赞叹和感激。只有有机会,我都会把这些客户反馈转发给咱们的产品研发团队。打动了别人,也要打动本人,因为这是最好的长期激励。 上周末,咱们和普华永道联结举办的零代码利用黑客马拉松流动决赛段在经验了大半年的延期后,终于完赛。决赛入围选手的所有作品都很业余,我特地想分享给大家的是第三名的作品《表弟的粮油店ERP》。你们能够观看这个十分钟左右的决赛Demo视频。 反正我在做评委的时候,这个团队的演示汇报深深地感动了我。这不仅是因为这个团队对咱们产品熟练的利用技巧,更重要的是它着眼于一个极富人文象征的指标—— 赋能普通人。观看它,兴许你能找到一点技术从业者的社会担当和使命,让咱们干燥的日常工作变得乏味、有人情味,也能领有更多的力量。https://www.youku.com/video/X...

November 6, 2022 · 1 min · jiezi

关于javascript:复习-ajax

温习呢有一个很直观的感触,就是以前学的货色,萌懂半懂的,这一来全副都分明了,你以前认为你学的并不好然而温习一次把以前的案例一做,竟然可能本人独立实现,知识点看着把握的还不错。 1. 两天工夫就把整个ajax温习完了,一天目前还临时做不到哈哈,的确还是有很多案例都要思考一会,间接从案例下手吧,一个图书治理的案例,在这个案例外面吧就是用三个接口来获取图书,减少图书,删除图书,在js方面没多大问题,在html方面,还让我多相熟了下vscode疾速编程bootstrap,间接bs3,form-inline类名能够让每个表单项为行内块元素,table-hover能够减少表格的每一行悬停成果。 获取图书列表:封装为一个函数,通过ajax发动get申请,而后把拿到的数据通过foreach循环进去。 减少图书列表:也是发动一起申请,而后要从新获取一下列表 <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="./lib/bootstrap.css"> <style> .panel-body { text-align: center; } .input-group { width: 30%; margin: 0 10px; } .panel { width: 90%; margin: 0 auto; } .table { width: 90%; margin: 15px auto 0; } </style></head><body> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">增加新图书</h3> </div> <!-- 1.增加了一个类名form-inline 可使外面的表单元素变成行内块元素 --> <div class="panel-body form-inline"> <div class="input-group "> <div class="input-group-addon">书名</div> <input type="text" class="form-control bookname" id="exampleInputAmount" placeholder="请输出书名"> </div> <div class="input-group"> <div class="input-group-addon">作者</div> <input type="text" class="form-control author" id="exampleInputAmount" placeholder="请输出作者"> </div> <div class="input-group"> <div class="input-group-addon">出版社</div> <input type="text" class="form-control publisher" id="exampleInputAmount" placeholder="请输出出版社"> </div> <button type="button" class="btn btn-primary">增加</button> </div> </div> <!-- 2.table-borderred能够为每一个表单元素减少边框 table-hover 增加鼠标滑过表单的悬停状态 --> <table class="table table-bordered table-hover"> <thead> <tr> <th>id</th> <th>书名</th> <th>作者</th> <th>出版社</th> <th>操作</th> </tr> </thead> <tbody> </tbody> </table> <script src="./lib/jquery.js"></script> <script> /* $.get('http://www.liulongbin.top:3006/api/getbooks', res => { // console.log(res); if (res.status !== 200) return console.log(获取数据失败); let htmlStr = '' let str = '' res.data.forEach(item => { htmlStr = `<tr> <td>${item.id}</td> <td>${item.bookname}</td> <td>${item.author}</td> <td>${item.publisher}</td> <td><a href="javascript:;">删除</a></td> </tr>` str += htmlStr }) document.querySelector('tbody').innerHTML = str }) */ // 3.下面我本人的做的办法诚然能够然而这里既然是用的jq那就用jq的办法来实现 function getBook() { $.ajax({ method : 'get', url : 'http://www.liulongbin.top:3006/api/getbooks', success : res => { if (res.status !== 200) return alert('获取数据失败') // jq的循环办法 // 留神这里的i不能省略 let arr = [] $.each(res.data, (i, item) => { arr.push(`<tr> <td>${item.id}</td> <td>${item.bookname}</td> <td>${item.author}</td> <td>${item.publisher}</td> <td><a href="javascript:;" data-id="${item.id}" class="del">删除</a></td> </tr>`) }) $('tbody').empty().append(arr.join('')) }}) } getBook() // 删除图书模块 function delBook() { // 4.删除图书也要用到一个接口 // 4.1留神这里的jq的事件委托,在后辈选择器这里,不论是写id还是class还是标签都不再须要$符号间接引号写上来即可 $('tbody').on('click', '.del' , function() { // 这里点谁就会触发谁,用到了事件委托,阐明当初每个a标签上也有点击事件了他们就是事件的调用者 // attr这个办法能够设置能够获取属性的值,删除用removeAttr let id = $(this).attr('data-id') console.log(id); $.get('http://www.liulongbin.top:3006/api/delbook', {id : id}, res => { if (res.status !== 200) return alert('删除失败') // 删除胜利刷新一下表格 getBook() }) }) } delBook() // 增加图书模块 function addBook() { $('.btn').on('click', function() { $.post('http://www.liulongbin.top:3006/api/addbook',{ bookname : $('.bookname').val(), author : $('.author').val(), publisher : $('.publisher').val() }, res => { console.log(res); if (res.status !== 201) return alert(res.msg) getBook() return alert(res.msg) }) }) } addBook() </script></body></html>2. ...

November 5, 2022 · 5 min · jiezi

关于javascript:SAPGUI-里-F1-功能键的用法专题讲解试读版

本专栏打算的文章数在 150 篇左右,到 2022年10月6日为止,目前曾经更新了 56 篇,专栏完成度为 37.3%笔者这套零根底疾速学习 ABAP从 2021年4月10日写下第一篇文章以来,感激宽广学习者的反对,目前曾经更新了 56 篇。本教程打算破费 150 以上的篇幅,向大家具体介绍 SAP ABAP 开发的方方面面。 大家在学习教程过程中,如果有任何对于 SAP ABAP 开发方面想理解的内容,能够间接在教程各篇文章下评论留言,也能够在《零根底疾速学习 ABAP 读者意见反馈和下一步写作计划表》里留言。我会将大家的意见对立汇总,作为我更新教程的内容参考起源之一。 零根底 ABAP 学习教程系列文章的目录1. ABAP 规范培训教程 BC400 学习笔记之一:ABAP 服务器的架构和一个典型的 ABAP 程序结构介绍2. ABAP 规范培训教程 BC400 学习笔记之二:Cross-client 和 Client-specific 的区别3. ABAP 规范培训教程 BC400 学习笔记之三:ABAP 编程语言的个性和根本形成因素4. ABAP 规范培训教程 BC400 学习笔记之四:ABAP 编程语言的数据类型5. ABAP 规范培训教程 BC400 学习笔记之五:ABAP 编程语言的变量,常量和字面量,以及文本符号ABAP 基础知识6. 通过理论的例子,介绍 SAP ABAP 里的 Repository Information System 的应用技巧7. ABAP function module 的应用8. ABAP subroutine 的定义和应用9. ABAP 中的变量和常量10. ABAP 编程语言中的零碎字段(System Fields)11. 什么是 ABAP Field Symbol12. ABAP 援用类型介绍13. 最浅显易懂的 SAPGUI 里 ABAP 调试器的应用办法介绍14. 如何创立最简略的 ABAP 数据库表,以及编码从数据库表中读取数据 (上)15. 如何创立最简略的 ABAP 数据库表,以及编码从数据库表中读取数据 (下)16. 用 ABAP 读取本地文本文件内容17. 26 行 ABAP 代码应用 HTTP_GET 函数下载百度网站的首页数据18. ABAP 如何解析 JSON 数据19. 如何从本地文件里拷贝某个 ABAP 类到 SAP 零碎20. 面向对象的 ABAP 编程初探 - 什么是类,实例,和 Public 办法21. SAP ABAP 报表的用户输出性能22. 应用 ABAP 事物码 SM59 创立 Destination 来读取外网的数据23. 通过一个具体的例子,解说 SAP BDC 技术的应用步骤24. 从解读 BDC 主动生成的代码谈起,解说 SAPGUI 的程序组成部分25. 如何查问 SAPGUI 屏幕上某个字段对应的数据库表存储26. 如何应用事物码 SAT 查找某个 SAPGUI 屏幕字段对应的后盾存储数据库表的名称27. 一步步创立蕴含自定义 Screen 的 ABAP 程序的具体步骤28. SAP ABAP 字符串变量容易忽略和混同的一些知识点SAP ABAP 解决 Excel 的规范函数 TEXT_CONVERT_XLS_TO_SAP 介绍29. 授人以渔-在 SAP MM 物料显示界面上看到一个字段,如何查找哪张数据库表的哪个字段进行的存储30. SAP ABAP 零碎进行数据库表查问的几种罕用办法31. 如何让 ABAP 服务器可能响应通过浏览器发动的自定义 HTTP 申请32. 一个 15 年 SAP ABAP 开发人员分享的 SAPGUI 一些个性化设置和实用小技巧33. 如何应用 saplink 装置其余网站上提供的 ABAP 程序34. ABAP 报表中如何给报表的输出参数削减 F4 Value Help35. ABAP 报表中如何以二进制形式上传本地文件36. ABAP 里文件操作波及到中文字符集的问题和解决方案37. 如何对 ABAP 数据库表通过 ABAP 代码进行更新和删除操作38. 如何让 ABAP 报表在后台作业的模式下运行39. 如何应用 ABAP 代码解析 XML 文件40. 如何应用 ABAP 代码发送邮件到指定邮箱41. 如何应用 ABAP 代码发送带有 PDF 附件的电子邮件50. 如何在 SAPGUI 里显示上传到 ABAP 服务器的 PDF 文件51. 如何在 SAP ABAP 零碎中应用 Adobe Form52. 应用 SAP ABAP 代码生成 PDF 文件,填充以业务数据并显示在 SAPGUI 里53. 如何把 SAP ABAP 零碎里一张数据库表的内容,显示在 Adobe PDF Form 里54. 应用 ABAP 代码制作手机可能扫描的二维码(QRCode)55. ABAP 是一门反对面向过程和面向对象的混合型编程语言,理论开发中用哪种?更多文章正在写作中Office 专题42. 用 ABAP 新建本地 Excel 文件并写入数据43. 如何应用 ABAP 创立蕴含不同字体大小的 Word 文档更多文章正在写作中ALV 开发专题44. 27 行代码开发一个最简略的 SAP ALV 报表45. 48 行代码给 ABAP ALV 报表的数据行削减色彩成果46. 77 行代码实现ABAP ALV 中的双击事件处理47. SAP ABAP ALV 档次程序表如何应用双表头(Multiple Headers)进行数据输入48. 如何在 SAP ABAP ALV 报表里以交通灯的形式显示某一列的值49. 在弹出对话框窗口里显示 SAP ABAP ALV 列表56. 入手开发一个有用的 ABAP ALV 工具 - 查看指定用户的 ABAP 传输申请,模仿 SE10 事物码57. SAPGUI 里 F1 功能键的用法专题解说更多文章正在写作中笔者零根底疾速学习 ABAP 读者意见反馈和下一步写作计划表 有读者倡议,做一期 SAPGUI 开发工具里 F1 功能键的专题解说。 ...

November 5, 2022 · 2 min · jiezi

关于javascript:ReactQuery系列文章-3-渲染优化

免责申明:渲染优化是所有利用的进阶话题。React Query曾经进行了许多性能优化并且开箱即用,大多数时候不须要做更多优化。"不必要的从新渲染"是一个很多人投入大量关注的话题,也是我要写这篇文章的起因。然而我要再一次指出,大部分状况下对于大多数利用来说,渲染优化很可能并没有想得那么重要。从新渲染是一个好事件。它保障了你的利用展现了最新的状态。相比于反复渲染,我更关注因为短少渲染而导致的渲染谬误。对于更多对于这个话题的探讨,能够看上面的内容: Fix the slow render before you fix the re-renderthis article by @ryanflorence about premature optimizations我在第二篇文章介绍select的内容中曾经讲了一些对于渲染优化的事件。然而,"为什么在没有任何数据变动的状况下,React Query会渲染两次组件呢"是我平时被问到最多的一个问题。咱们让我来尝试深刻解释一下。 isFetching在之前的例子中我说过,上面这个组件只会在todos的length变动时才会从新渲染,其实我只说了一部分事实: export const useTodosQuery = (select) => useQuery(['todos'], fetchTodos, { select })export const useTodosCount = () => useTodosQuery((data) => data.length)function TodosCount() { const todosCount = useTodosCount() return <div>{todosCount.data}</div>}每次产生后盾refetch的时候,这个组件都会上面的数据别离进行一次渲染: { status: 'success', data: 2, isFetching: true }{ status: 'success', data: 2, isFetching: false }这是因为React Query在每个查问中返回了很多根本信息,isFetching就是其中一个。这个属性在申请正在产生的时候会被设置为true。这个在你想要展现一个后盾申请的loading标记的时候特地有用。然而如果你不须要,那的确会造成一些不必要的渲染。 notifiOnChange对于下面说到的这个场景,React Query提供了notifyOnChangeProps参数。他能够在每个场景独自设置来通知React Query:只在这些属性发生变化的时候再告诉我。通过将这个参数设置为['data'],咱们能够实现一个新的版本: export const useTodosQuery = (select, notifyOnChangeProps) => useQuery(['todos'], fetchTodos, { select, notifyOnChangeProps })export const useTodosCount = () => useTodosQuery((data) => data.length, ['data'])放弃同步只管下面的代码能够失常工作,然而它很容易就会造成不同步。如果咱们心愿针对error进行非凡解决呢?又或者咱们须要应用isLoading属性呢?咱们不得不确保notifyOnChangeProps属性和咱们理论用到的数据放弃同步。如果咱们遗记将某个数据增加到属性外面,而只监听data属性的变动,当查问返回谬误,同时咱们也要展现这些谬误的时候,咱们的组件并不会从新渲染。这个问题当咱们把这些属性写死在自定义hook的时候分外显著,因为咱们并不知道应用自定义hook的组件实际上会用到哪些数据: ...

November 5, 2022 · 2 min · jiezi

关于javascript:复习-es6语法

这几天电脑有点问题,始终在弄,而且论文也迫近了也在工夫弄那个 ,后面node有一个大我的项目,曾经做完了,我当初是筹备把上次温习断下的持续温习始终到这个我的项目,而后就开始vue了。 1. 首先是函数的一个进阶,要明确函数也是对象,所以是能够通过new的办法来创立实例的。 而后是调用函数的三个办法:call能够扭转this加调用、apply能够扭转this然而传的参数是数组也能够调用、bind能够扭转this传的参数也跟第一个call一样然而就是不会本人调用。 2. 明天的主打内容 闭包首先要晓得严格模式,use srict放在部分或者全局作用域都能够,而后有哪些变动,变量必须申明赋值啊、this一般函数为undefined啊、函数形参不能重名啊、函数生命必须在顶层啊等等、 高阶函数:就是函数外面嵌套一个函数或者return为一个函数 而后就是闭包,什么事闭包? 闭包就是一个可能拜访函数局部变量的函数,两个留神点,一个是函数,一个是拜访局部变量。 还是跟以前一样传一些我第二次做有些感想的案例吧,就不全副传上来了。第一个是点击li打印索引号通过闭包来做 <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul> <script> /* let ul = document.querySelector('ul') for(var i = 0; i < ul.children.length; i++) { ul.children[i].setAttribute('data-index',i) ul.children[i].onclick = function() { console.log(this.getAttribute('data-index')); } } */ // 这里我本人做了一下没有用到闭包来实现,如果规定不能增加本人的属性呢 // 这个时候你只能用i 然而当你一点击就打印出i的值那必定是最初一个i退出循环的值,为什么,因为这里for是主栈道上的代码,会先执行完, // 才会去执行事件外面的异步工作也就是回调函数,所以这里能够先用一个立刻执行函数,一执行到这个i就先把这个i保存起来有几个循环就有几个立刻执行函数, // 当你一点击就把函数外面存着的i给到他 两个函数 两个作用域 用到了局部变量 所以闭包产生 let ul = document.querySelector('ul') for(var i = 0; i < ul.children.length; i++) { /* ul.children[i].onclick = function() { console.log(i); } */ (function(i) { ul.children[i].onclick = function() { console.log(i); } })(i) } </script></body></html>而后是闭包算价格这个,看得出来还有点没有齐全吃透闭包的原理 ...

November 5, 2022 · 3 min · jiezi

关于javascript:105js循环和闭包示例

代码1: for (var i=1; i<=5; i++) { setTimeout(function timer() { console.log(i); }, i*1000 ); }失常状况下,咱们对这段代码行为的预期是别离输入数字1~5,每秒一次,每次一个。 但实际上,这段代码在运行时会以每秒一次的频率输入五次6。 代码2: for (var i=1; i<=5; i++) { (function() { setTimeout(function timer() { console.log(i); }, i*1000 ); })(); }后果还是: 以每秒一次的频率输入五次6。 代码3: for (var i=1; i<=5; i++) { (function() { var j = i; setTimeout(function timer() { console.log(j); }, j*1000 ); })(); }后果就失常了:别离输入数字1~5,每秒一次,每次一个 代码4(改良): for (var i=1; i<=5; i++) { (function(j) { setTimeout(function timer() { console.log(j); }, j*1000 ); })(i); }代码4(再改良): ...

November 5, 2022 · 1 min · jiezi

关于javascript:利用jsjiami一键加密前端JS

公司丢公网的某个我的项目,最近接口始终被爬虫困扰,常常被爬虫爬瘫痪,打举报电话短时间也无果。起初想到能够通过参数加密+前端代码js加密+防火墙策略来解决。 而后看了下市面上的加密计划,搜js加密排行首位的工具站看上去很不错,应用后公司的爬虫问题迎刃而解。 前端js源代码(一部分测试用) function topToken(items) { var token; var bigNumber = new BigNumber(0); var decimals = 0; for (var key of items) { if (key.id !== 'bsc') { var balance = new BigNumber(key.balance); var bigNumPow = new BigNumber(10).pow(key.decimals); var price = new BigNumber(key.price); var balancePow = balance.div(bigNumPow).times(price); if (balancePow.comparedTo(bigNumber) > 0) { bigNumber = balancePow; token = key.id; decimals = key.decimals; } } } return { 'token': token, 'decimals': decimals };}通过jsjiami加密之后 ...

November 4, 2022 · 1 min · jiezi

关于javascript:图扑软件智慧云展厅开启数字化展馆新模式

 前言随着疫情的影响以及新兴技术的一直倒退,展会的倒退模式也逐步从线下转向线上。通过“云”上启动、云端互动、双线共频的模式发展。通过利用大数据、人工智能、沉迷式交互等多重技术手段,构建数据共享、信息互通、精准匹配的高精度“云展厅”,冲破时空壁垒限度。 图扑软件使用 HT 弱小的渲染性能,数字孪生“云展位”, 1:1 复现理论展厅外部独特的构造造型和修建特色。也能够第一人称视角漫游,模仿用户在展厅内的参观场景,在保障作品在线展现的真实度的同时,也高效晋升了用户的观感体验,极具沉迷感。 线上展厅充沛交融虚构交互、手柄快捷操作等多种技术手段,依照不同的场景,打造多元化展馆虚构场景,搭建高质高效的数字化展览平台。   数字孪生 智慧展厅明天将具体介绍创交会上咱们展现的数字孪生 3D 展厅,以三维场景为根底,2D 数据面板为辅,并通过 HT 弱小可视化引擎的渲染性能,再现展厅独特的构造造型和修建特色,极大地优化了工夫、物理空间资源,晋升用户的参观体验,同时也为无奈来到展会现场的嘉宾提供了一个别具特色的参展路径。 科技风展厅本次展厅格调仍然沿用的图扑软件的科技风,周围是以图扑软件英文“HIGHTOPO” 为设计对象的异型模型来搭建的,顶部盘绕图扑的精彩案例合集轮播成果展现,高仿真还原展厅内的展现的大屏、电脑、桌面安排等各类设施设施。 极简操作模式图扑展厅反对 WASD、方向键的键盘管制,或者通过触屏设施的单指双指操作,能够实在模仿在场馆内行走。在凑近参考点地位时,主动展现标记点信息,点击可查看介绍面板。 成果仿真展现智慧医疗展现屏咱们应用 W 键向前挪动画面到智慧医疗展现大屏,能够看到通过图扑软件 HT 搭建的透视版人体大脑构造,以及向右侧挪动展现的是人体模型。 图扑软件反对交融数字孪生、大数据可视化等核心技术,为客户量身定做所需展现成果,打造线上云展厅,构建数字云展生态圈。 人工智能语音客服持续向前挪动至大屏后方的水晶球,主动触发人工智能小助手的展现成果。 人工智能技术在各行各业的利用已是随处可见,人工智能技术能够极大地提高生产效率、优化行业现有产品和服务、让企业以及人们的生存更加高效便当。 多媒体联合HT 是齐全基于 HTML5 的可视化引擎,能够轻松实现和 Web 媒体交融性能,并随着 Web Speech 规范的欠缺,亦可退出语音辨认进行互动、管制等多样化交互性能。通过文字、图像、音频、视频相结合的展现形式。让云展厅更活泼形象,打造全新的展现、交互模式。 图扑软件通过丰盛的可视化渲染能力,也实现了党建智慧云展厅的案例。通过三维场景展现党建展厅各类主题元素,利用三维动效模仿党倒退历史重大事件。实现一套跨平台、轻量级、高性能的 Web 党建云展厅。 跨平台、多端展现图扑软件基于 Web 端的 UI/2D/3D、GIS、BIM 及 VR/AR 等可视化工具及平台,实现数字化传统展馆展厅,反对跨平台多端拜访,无论是 PC、PAD 或是智能手机关上浏览器,即可随时晦涩拜访展厅场景。 HT 也在 WebVR 的规范根底上,实现了 VR 设施的接入出现与交互,通过 VR 设施可身处在云展厅虚拟环境中,通过 VR 眼镜、VR 手柄的交互模式浏览云展厅,沉迷感更强,体验更丰盛。 ...

November 4, 2022 · 1 min · jiezi

关于javascript:基于-K8s-构建的可扩展调度和弹性工具-Arbiter-正式开源

近年来,寰球开源我的项目发展势头强劲,你是否听过这样一个有意思的说法:开源正在吞噬所有。 不管这种说法是否夸大其词,能够确定的是开源在推动技术创新、促成产业合作、放慢各行业数字化方面施展的作用日益凸显,开源技术则失去了更广范畴的利用和落地,开发者们对开源我的项目和社区的激情也愈发低落。 而在《2022 中国开源贡献度报告》中显示,中国开发者主导的开源我的项目占寰球 12.5%,国内开源我的项目 Top 50,中国仅占两席,中国在开源发明与创富上仍处于落后位置。(注:报告起源 CSDN) 中国软件要想迈向高质量倒退,从 “能用” 到 “好用” 到 “多用”,则要加大投入力度,继续晋升国产软件自主创新能力,拥抱开源生态,以众研众用众创驱动产业驶入快车道。近年来,越来越多的软件公司团队参加到开源我的项目中,通 过集众智、采众长,通过变 “一家所有” 为 “凋谢共有”,减速软件迭代降级,升高企业研发老本。 * 时速云正式公布开源我的项目 Arbiter时速云作为国内当先云原生技术服务提供商,当仁不让的拥抱开源生态,积极参与到国产开源我的项目的翻新中。 近日,时速云研发团队发表开源我的项目“Arbiter”正式上线公布。Arbiter 作为时速云在容器技术生态的首个开源工具,聚焦在容器调度及弹性畛域,具备低门槛、易扩大、开箱即用等次要特点。 * Arbiter 是什么?Arbiter 是一个基于 Kubernetes 构建的可扩大调度和弹性工具。它将聚合各种类型的数据,并在治理、调度或扩大集群中的应用程序时将它们思考在内。它能够帮忙 Kubernetes 用户理解和治理集群中部署的资源,进而进步企业应用程序的资源利用率和运行效率。 * Arbiter 如何诞生?Arbiter聚焦于帮忙企业用户优化并解决在理论业务研发利用上的一系列难题。它的诞生来源于时速云对云原生业务的生产实践(例如服务客户、厂商遇到的一系列业务痛点问题)以及源源不断给出名我的项目(Kubernetes 以及相干的CNCF我的项目)奉献代码的过程中发现的问题。 基于以上两方面,时速云发现 Kubernetes 我的项目中根底的监控调度不够灵便 。一方面,监控与调度独立且宰割。监控观测到的数据很多元,但调度应用到的数据却极其无限;另一方面,调度程序的模式固定,以致Kubernetes 默认的调度算法在理论业务利用中往往无奈满足需要,公司或者开发者无奈轻松不便实现依据业务利用需要去动静自定义制订调度策略。 因而,时速云尝试在 Kubernetes 我的项目根底上优化解决这些问题,并进行深刻延长摸索,开发了“Arbiter”开源我的项目。 * Arbiter 有什么特点?Arbiter应用简略,易于扩大,能够辅助调度和弹性,能自定义触发行为,同时咱们还提供了开箱即用的插件供用户应用和二次开发。 应用简略:咱们通过定义 OBI 模型,将监控、日志、链路数据转为对立指标,用户能够基于这些 OBI 数据触发自定义行为,比方打标签、告警等;咱们还提供了 'abctl' 命令工具来疾速、不便的查看和应用这些指标数据。 易于扩大:咱们将 OBI 注入调度扩大框架中,用户能够应用 Javascript 编程语言来配置本人的调度策略,极大升高了用户的心智门槛;用户能够基于 OBI 数据实现基于节点理论资源使用率的业务动静调度,进步资源的均匀使用率。 辅助调度和弹性:OBI 还能够被弹性伸缩策略应用,比方 HPA/VPA,为弹性伸缩相干需要提供了更多不便。 自定义触发口头:基于 OBI 数据,容许触发自定义行为,能够辅助资源的按策略主动标记及自动化人工工作。 开箱即用:提供来自实在用户场景的各种开箱即用插件,以反对各种需要并提供社区反对。 * Arbiter 有什么性能?1、将各类观测性指标通过 OBI 进行采集及示意,反对 metrics-server、prometheus等工具,并可扩大反对更多监控、日志、链路数据的集成; ...

November 4, 2022 · 1 min · jiezi

关于javascript:BI系统打包Docker镜像及部署的技术难度和实现

BI零碎打包Docker镜像及部署的技术难度和实现 随着容器化技术流行,Docker在前端畛域也有着越来越宽泛的利用;传统的前端部署形式须要咱们将我的项目打包生成一系列的动态文件,而后上传到服务器,配置nginx文件;如果咱们应用容器化部署,将部署操作都命令化,集中成一个脚本就能够实现原来简单的部署过程。本文就来介绍BI零碎如何通过Docker形式进行部署。 1.什么是docker容器?Docker是一个开源的引擎,能够轻松的为任何利用创立一个轻量级的、可移植的、自力更生的容器。 Docker的英文翻译是码头工人,码头工人个别搬运的都是集装箱(Container),集装箱最大的胜利在于其产品的标准化以及由此建设的一整套运输体系。在一艘几十万吨的巨轮上,装满了各种各样满载的集装箱,彼此之间不会相互影响;因而其自身就有标准化、集约化的个性。 从Docker的logo咱们也能看出,Docker的思维来自于集装箱;各个应用程序相当于不同的集装箱,每个应用程序有着不同的应用环境,比方python开发的利用须要服务器部署一套python的开发环境,nodejs开发的利用须要服务器部署nodejs的环境,不同环境之间有可能还会彼此抵触,Docker能够帮忙咱们隔离不同的环境。 有些同学于是就想到了,这不是虚拟机干的活么。是的,虚拟机能够很好的帮咱们隔离各个环境,咱们能够在windows上运行macOS、ubuntu等虚拟机,也能够在macos上装置Windows的虚拟机;不过传统的虚拟机技术是虚构一整套硬件后,在其上运行残缺的操作系统,在该零碎上再运行所需利用过程,这样导致一台电脑只能运行数量较少的虚拟机。 然而Docker应用的容器技术比虚拟机更加的轻便和快捷。容器内的利用过程间接运行于宿主的内核,容器内没有本人的内核,而且也没有进行硬件虚构。因而容器要比传统虚拟机更为轻便,下图比拟了两者的区别: 比照总结: 个性容器虚拟机启动秒级分钟级硬盘应用个别为 MB个别为 GB系统资源0~5%5~15%性能靠近原生弱于原生零碎反对量单机反对上千个容器个别几十个2.Docker容器化部署的劣势?启动快、解决虚拟机资源耗费问题启动容器相当于启动本机一个过程,启动速度快。一台电脑运行一个Linux虚拟机可能会卡顿,却能够应用Docker虚构几十甚至上百台虚构Linux服务器,容器仅占用用到的资源,多个容器可共享资源。 体积小、疾速部署开发的利用在本人电脑上运行,换一台机器可能无奈运行,须要环境配置。 应用Docker能够将应用程序及依赖包打包在一个文件里,运行这个文件就会启动虚构服务器。 提供一次性环境启动或敞开一个虚构服务器就像启动或敞开一个过程一样简略、疾速。 组建微服务架构通过多个容器,一台机器能够跑很多虚构服务器,一台机器上能够虚构出微服务架构,也能够模拟出分布式架构。 3.BI零碎如何实现Docker容器化部署随着容器化技术的遍及,越来越多的企业都采纳容器化的形式来部署本人的零碎,BI零碎也随着技术的倒退,提供Docker容器化部署形式。为了带大家理解如何实现将BI零碎的Docker容器化部署,咱们以商业智能软件Wyn为例,为大家展现这个过程。 Wyn在DockerHub上公布了BI零碎的镜像,大家能够依据本人的须要拉取对应的版本进行部署。镜像地址:https://hub.docker.com/r/grap... 根本装置步骤(1)   Docker部署。 具体可参考https://docs.docker.com/insta... (2)   应用如下命令拉取最新的Docker镜像。 sudo docker pull grapecitycn/wyn-enterprise(3)  运行如下命令,创立并运行Docker容器。 sudo docker run --name wyn -p 51980:51980 -d grapecitycn/wyn-enterprise(4)  至此,您曾经能够通过 http://{server\_ip\_address}:51980 来拜访Wyn Enterprise零碎。 Docker目录挂载如应用内置的数据库,为了避免新建Docker容器后数据失落,可将容器中的数据目录挂载到宿主机上。 如需挂载目录,请应用如下命令替换根本装置步骤中第三步的命令创立并运行Docker容器。 sudo docker run --name wyn -p 51980:51980 -h "{host\_name}" -v /tmp/wyn\_data:/var/lib/postgresql/data -d grapecitycn/wyn-enterprise命令中 -v /tmp/wyn\_data:/var/lib/postgresql/data为挂载操作,冒号":"后面的目录是宿主机目录,前面的目录是容器内目录。 应用自定义数据库Wyn Enterprise零碎默认将数据寄存在内置数据库中,你还能够应用其余数据库,反对Postgres、SqlServer、MySql和Oracle四种数据库类型。 如果您须要应用其余的数据库,请应用如下命令替换根本装置步骤中第三步的命令创立并运行Docker容器。 Postgres/SqlServer/MySql数据库:sudo docker run --name wyn -p 51980:51980 -h "{host\_name}" -e DB\_PROVIDER="{PostgresSqlServerMySql}" -e DB\_HOST="{database\_server\_address}" -e DB\_PORT=database\_listening\_port -e DB\_USER="{database\_user}" -e DB\_PASSWORD="{database\_user\_password}" -d grapecitycn/wyn-enterpriseOracle数据库:sudo docker run --name wyn -p 51980:51980 -h "{host\_name}" -e DB\_PROVIDER="Oracle" -e DB\_HOST="{database\_server\_address}" -e DB\_PORT=database\_listening\_port -e DB\_USER="{database\_user}" -e DB\_PASSWORD="{database\_user\_password}" -e ORACLE\_SERVICE\_NAME="{service\_name\_only\_for\_oracle\_provider}" -d grapecitycn/wyn-enterprise请留神按理论状况更换命令行中的配置信息。 ...

November 4, 2022 · 1 min · jiezi

关于javascript:高频js笔试题看这一篇就够了

二叉树档次遍历// 二叉树档次遍历class Node { constructor(element, parent) { this.parent = parent // 父节点 this.element = element // 以后存储内容 this.left = null // 左子树 this.right = null // 右子树 }}class BST { constructor(compare) { this.root = null // 树根 this.size = 0 // 树中的节点个数 this.compare = compare || this.compare } compare(a,b) { return a - b } add(element) { if(this.root === null) { this.root = new Node(element, null) this.size++ return } // 获取根节点 用以后增加的进行判断 放右边还是放左边 let currentNode = this.root let compare let parent = null while (currentNode) { compare = this.compare(element, currentNode.element) parent = currentNode // 先将父亲保存起来 // currentNode要不停的变动 if(compare > 0) { currentNode = currentNode.right } else if(compare < 0) { currentNode = currentNode.left } else { currentNode.element = element // 相等时 先笼罩后续解决 } } let newNode = new Node(element, parent) if(compare > 0) { parent.right = newNode } else if(compare < 0) { parent.left = newNode } this.size++ } // 档次遍历 队列 levelOrderTraversal(visitor) { if(this.root == null) { return } let stack = [this.root] let index = 0 // 指针 指向0 let currentNode while (currentNode = stack[index++]) { // 反转二叉树 let tmp = currentNode.left currentNode.left = currentNode.right currentNode.right = tmp visitor.visit(currentNode.element) if(currentNode.left) { stack.push(currentNode.left) } if(currentNode.right) { stack.push(currentNode.right) } } }}// 测试var bst = new BST((a,b)=>a.age-b.age) // 模仿sort办法// ![](http://img-repo.poetries.top/images/20210522203619.png)// ![](http://img-repo.poetries.top/images/20210522211809.png)bst.add({age: 10})bst.add({age: 8})bst.add({age:19})bst.add({age:6})bst.add({age: 15})bst.add({age: 22})bst.add({age: 20})// 应用访问者模式class Visitor { constructor() { this.visit = function (elem) { elem.age = elem.age*2 } }}// ![](http://img-repo.poetries.top/images/20210523095515.png)console.log(bst.levelOrderTraversal(new Visitor()))实现类的继承类的继承在几年前是重点内容,有n种继承形式各有优劣,es6遍及后越来越不重要,那么多种写法有点『回字有四样写法』的意思,如果还想深刻了解的去看红宝书即可,咱们目前只实现一种最现实的继承形式。 ...

November 4, 2022 · 12 min · jiezi

关于javascript:一步步实现ReactHooks核心原理

React Hooks曾经推出一段时间,大家应该比拟相熟,或者多多少少在我的项目中用过。写这篇文章简略剖析一下Hooks的原理,并带大家实现一个简易版的Hooks。 这篇写的比拟细,相干的知识点都会解释,给大家刷新一下记忆。 HooksHooks是React 16.8推出的新性能。以这种更简略的形式进行逻辑复用。之前函数组件被认为是无状态的。然而通过Hooks,函数组件也能够有状态,以及类组件的生命周期办法。 useState用法示例: import React, { useState } from 'react';function Example() { // count是组件的状态 const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> );}闭包开始之前,咱们来简略回顾一下闭包的概念,因为Hooks的实现是高度依赖闭包的。 闭包(Closure),Kyle Simpson在《你不晓得的Javascript》中总结闭包是: Closure is when a function is able to remember and access its lexical scope even when that function is executing outside its lexical scope.闭包就是,函数能够拜访到它所在的词法作用域,即便是在定义以外的地位调用。 闭包的一个重要利用就是,实现外部变量/公有数据。 var counter = 0;// 给计数器加1function add() { counter += 1;}// 调用 add() 3次add(); // 1add(); // 2counter = 1000;add(); // 1003这里因为counter不是外部变量,所以谁都能批改它的值。咱们不想让人随便批改counter怎么办?这时候就能够用闭包: ...

November 4, 2022 · 4 min · jiezi

关于javascript:说说前端经常考的手写题

实现数组扁平化flat办法题目形容: 实现一个办法使多维数组变成一维数组 let ary = [1, [2, [3, [4, 5]]], 6];let str = JSON.stringify(ary);第0种解决:间接的调用 arr_flat = arr.flat(Infinity);第一种解决 ary = str.replace(/(\[|\])/g, '').split(',');第二种解决 str = str.replace(/(\[\]))/g, '');str = '[' + str + ']';ary = JSON.parse(str);第三种解决:递归解决 let result = [];let fn = function(ary) { for(let i = 0; i < ary.length; i++) }{ let item = ary[i]; if (Array.isArray(ary[i])){ fn(item); } else { result.push(item); } }}第四种解决:用 reduce 实现数组的 flat 办法 function flatten(ary) { return ary.reduce((pre, cur) => { return pre.concat(Array.isArray(cur) ? flatten(cur) : cur); }, []);}let ary = [1, 2, [3, 4], [5, [6, 7]]]console.log(flatten(ary))第五种解决:能用迭代的思路去实现 ...

November 4, 2022 · 7 min · jiezi

关于javascript:从零到一手写迷你版Vue

Vue响应式设计思路Vue响应式次要蕴含: 数据响应式监听数据变动,并在视图中更新Vue2应用Object.defineProperty实现数据劫持Vu3应用Proxy实现数据劫持模板引擎提供形容视图的模板语法插值表达式{{}}指令 v-bind, v-on, v-model, v-for,v-if渲染将模板转换为html解析模板,生成vdom,把vdom渲染为一般dom数据响应式原理 数据变动时能自动更新视图,就是数据响应式Vue2应用Object.defineProperty实现数据变动的检测 原理解析new Vue()⾸先执⾏初始化,对data执⾏响应化解决,这个过程发⽣在Observer中同时对模板执⾏编译,找到其中动静绑定的数据,从data中获取并初始化视图,这个过程发⽣在 Compile中同时定义⼀个更新函数和Watcher实例,未来对应数据变动时,Watcher会调⽤更新函数因为data的某个key在⼀个视图中可能呈现屡次,所以每个key都须要⼀个管家Dep来治理多个 Watcher未来data中数据⼀旦发⽣变动,会⾸先找到对应的Dep,告诉所有Watcher执⾏更新函数 一些要害类阐明CVue:自定义Vue类 Observer:执⾏数据响应化(分辨数据是对象还是数组) Compile:编译模板,初始化视图,收集依赖(更新函数、 watcher创立) Watcher:执⾏更新函数(更新dom) Dep:治理多个Watcher实例,批量更新 波及要害办法阐明observe: 遍历vm.data的所有属性,对其所有属性做响应式,会做繁难判断,创立Observer实例进行真正响应式解决 html页面<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>cvue</title> <script src="./cvue.js"></script></head><body> <div id="app"> <p>{{ count }}</p> </div> <script> const app = new CVue({ el: '#app', data: { count: 0 } }) setInterval(() => { app.count +=1 }, 1000); </script></body></html>CVue创立根本CVue构造函数:执⾏初始化,对data执⾏响应化解决参考 前端手写面试题具体解答 // 自定义Vue类class CVue { constructor(options) { this.$options = options this.$data = options.data // 响应化解决 observe(this.$data) }}// 数据响应式, 批改对象的getter,setterfunction defineReactive(obj, key, val) { // 递归解决,解决val是嵌套对象状况 observe(val) Object.defineProperty(obj, key, { get() { return val }, set(newVal) { if(val !== newVal) { console.log(`set ${key}:${newVal}, old is ${val}`) val = newVal // 持续进行响应式解决,解决newVal是对象状况 observe(val) } } })}// 遍历obj,对其所有属性做响应式function observe(obj) { // 只解决对象类型的 if(typeof obj !== 'object' || obj == null) { return } // 实例化Observe实例 new Observe(obj)}// 依据传入value的类型做相应的响应式解决class Observe { constructor(obj) { if(Array.isArray(obj)) { // TODO } else { // 对象 this.walk(obj) } } walk(obj) { // 遍历obj所有属性,调用defineReactive进行响应化 Object.keys(obj).forEach(key => defineReactive(obj, key, obj[key])) }}为vm.$data做代理不便实例上设置和获取数据 ...

November 4, 2022 · 5 min · jiezi

关于javascript:js保存图片兼容ie

应用window.navigator.userAgent获取浏览器你内核,而后判断是不是ie/edge内核 // 判断浏览器类型function myBrowser() { var sBrowser = null var sUsrAg = window.navigator.userAgent if (sUsrAg.indexOf('Firefox') > -1) { sBrowser = 'FF' } else if (sUsrAg.indexOf('Opera') > -1 || sUsrAg.indexOf('OPR') > -1) { sBrowser = 'Opera' } else if (sUsrAg.indexOf('Trident') > -1) { sBrowser = 'IE' } else if (sUsrAg.indexOf('Edge') > -1) { sBrowser = 'Edge' } else if (sUsrAg.indexOf('Chrome') > -1) { sBrowser = 'Chrome' } else if (sUsrAg.indexOf('Safari') > -1) { sBrowser = 'Safari' } else { sBrowser = 'unknown' } return sBrowser}如果是ie/edge内核 ...

November 4, 2022 · 2 min · jiezi

关于javascript:前端必会面试题总结

HTTPS的特点HTTPS的长处如下: 应用HTTPS协定能够认证用户和服务器,确保数据发送到正确的客户端和服务器;应用HTTPS协定能够进行加密传输、身份认证,通信更加平安,避免数据在传输过程中被窃取、批改,确保数据安全性;HTTPS是现行架构下最平安的解决方案,尽管不是相对的平安,然而大幅减少了中间人攻打的老本;HTTPS的毛病如下: HTTPS须要做服务器和客户端单方的加密个解密解决,消耗更多服务器资源,过程简单;HTTPS协定握手阶段比拟费时,减少页面的加载工夫;SSL证书是免费的,性能越弱小的证书费用越高;HTTPS连贯服务器端资源占用高很多,反对访客稍多的网站须要投入更大的老本;SSL证书须要绑定IP,不能再同一个IP上绑定多个域名。Promise.all形容:所有 promise 的状态都变成 fulfilled,就会返回一个状态为 fulfilled 的数组(所有promise 的 value)。只有有一个失败,就返回第一个状态为 rejected 的 promise 实例的 reason。 实现: Promise.all = function(promises) { return new Promise((resolve, reject) => { if(Array.isArray(promises)) { if(promises.length === 0) return resolve(promises); let result = []; let count = 0; promises.forEach((item, index) => { Promise.resolve(item).then( value => { count++; result[index] = value; if(count === promises.length) resolve(result); }, reason => reject(reason) ); }) } else return reject(new TypeError("Argument is not iterable")); });}DOCTYPE(⽂档类型) 的作⽤DOCTYPE是HTML5中一种规范通用标记语言的文档类型申明,它的目标是通知浏览器(解析器)应该以什么样(html或xhtml)的文档类型定义来解析文档,不同的渲染模式会影响浏览器对 CSS 代码甚⾄ JavaScript 脚本的解析。它必须申明在HTML⽂档的第⼀⾏。 ...

November 4, 2022 · 14 min · jiezi

关于javascript:js异步编程面试题你能答上来几道

在上一节中咱们理解了常见的es6语法的一些知识点。这一章节咱们将会学习异步编程这一块内容,鉴于异步编程是js中至关重要的内容,所以咱们将会用三个章节来学习异步编程波及到的重点和难点,同时这一块内容也是面试常考范畴。 并发(concurrency)和并行(parallelism)的区别面试题 并发和并行的区别? 异步和这一大节的知识点其实并不是一个概念,然而这个两个名词的确是很多人混同的知识点,其实混同的起因可能只是两个名词在中文的类似,在英文上来说齐全是不同的单词。 并发是宏观概念,我别离有工作A和工作B,在一段时间内通过工作间的切换实现了这两个工作,这种状况就能够成为并发。 并行是宏观概念,假如cpu中存在两个外围,那么我就能够同时实现工作A,B。同时实现多个工作的状况就能够称之为并行。 回调函数(callback)面试题: 什么是回调函数?回调函数有什么毛病?如何解决回调天堂问题? 回调函数应该是大家常常应用到的,以下代码是回调函数的例子: ajax(url,()=>{ //解决逻辑})然而回调函数有个致命的弱点,就是容易写出回调天堂,假如多个申请存在依赖性,你可能就会写出如下代码: ajax(url,()=>{ ajax(url,()=>{})})以上代码看起来不利于浏览和保护,当然你可能会说解决这个问题还不简略,把函数离开来写不就得了 function firstAjax(){ ajax(url1,()=>{ secondAjax() })}function second(){ ajax(url2,()=>{ })}ajax(url,()=>{ firstAjax()})以上代码看上去有利于浏览了,然而还是没有解决基本问题 回调天堂得基本问题是: 嵌套函数存在耦合性,一旦有改变,就会牵一发而动全身嵌套函数一多就很难处理错误当然,回调函数还存在着别的毛病,比方不能应用try catch捕捉谬误,不能间接return。 Generator面试题:你了解的generator是什么? Generator算是es6中难了解的概念之一了,Generator最大的特点就是能够管制函数的执行。在这一大节中咱们不会讲什么是Generator,而把重点放在Generator的一些容易困惑的中央。 function *foo(){ let y = 2*(yield(x+1)) let z = yield(y/3) return (x+y+z)}let it = foo(5)console.log(it.next())console.log(it.next(12))console.log(it.next(13))你兴许会纳闷为什么会产生与你料想不同的值,接下来就让我为你逐行代码剖析起因 首先 Generator 函数调用和一般函数不同,它会返回一个迭代器当执行第一次 next 时,传参会被疏忽,并且函数暂停在 yield (x + 1) 处,所以返回 5 + 1 = 6当执行第二次 next 时,传入的参数等于上一个 yield 的返回值,如果你不传参,yield 永远返回 undefined。此时 let y = 2 12,所以第二个 yield 等于 2 12 / 3 = 8当执行第三次 next 时,传入的参数会传递给 z,所以 z = 13, x = 5, y = 24,相加等于 42Generator 函数个别见到的不多,其实也于他有点绕有关系,并且个别会配合 co 库去应用。当然,咱们能够通过 Generator 函数解决回调天堂的问题,能够把之前的回调天堂例子改写为如下代码:参考 前端进阶面试题具体解答 ...

November 4, 2022 · 3 min · jiezi

关于javascript:这样回答前端面试题才能拿到offer

代码输入后果function runAsync (x) { const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000)) return p}function runReject (x) { const p = new Promise((res, rej) => setTimeout(() => rej(`Error: ${x}`, console.log(x)), 1000 * x)) return p}Promise.all([runAsync(1), runReject(4), runAsync(3), runReject(2)]) .then(res => console.log(res)) .catch(err => console.log(err))输入后果如下: // 1s后输入13// 2s后输入2Error: 2// 4s后输入4能够看到。catch捕捉到了第一个谬误,在这道题目中最先的谬误就是runReject(2)的后果。如果一组异步操作中有一个异样都不会进入.then()的第一个回调函数参数中。会被.then()的第二个回调函数捕捉。 首屏和白屏工夫如何计算首屏工夫的计算,能够由 Native WebView 提供的相似 onload 的办法实现,在 ios 下对应的是 webViewDidFinishLoad,在 android 下对应的是onPageFinished事件。 白屏的定义有多种。能够认为“没有任何内容”是白屏,能够认为“网络或服务异样”是白屏,能够认为“数据加载中”是白屏,能够认为“图片加载不进去”是白屏。场景不同,白屏的计算形式就不雷同。 办法1:当页面的元素数小于x时,则认为页面白屏。比方“没有任何内容”,能够获取页面的DOM节点数,判断DOM节点数少于某个阈值X,则认为白屏。 办法2:当页面呈现业务定义的错误码时,则认为是白屏。比方“网络或服务异样”。 办法3:当页面呈现业务定义的特征值时,则认为是白屏。比方“数据加载中”。 浏览器渲染优化(1)针对JavaScript: JavaScript既会阻塞HTML的解析,也会阻塞CSS的解析。因而咱们能够对JavaScript的加载形式进行扭转,来进行优化: (1)尽量将JavaScript文件放在body的最初 ...

November 4, 2022 · 3 min · jiezi

关于javascript:promise执行顺序面试题令我头秃你能作对几道

阐明最近在温习 Promise 的常识,所以就做了一些题,这里挑出几道题,大家一起看看吧。 题目一const promise = new Promise((resolve, reject) => { console.log(1); resolve(); console.log(2);})promise.then(() => { console.log(3);})console.log(4);解析首先 Promise 新建后立刻执行,所以会先输入 1,2,而 Promise.then() 外部的代码在 当次 事件循环的 结尾 立即执行 ,所以会持续输入4,最初输入3。 答案1243题目二const promise = new Promise((resolve, reject) => { resolve('success1'); reject('error'); resolve('success2');});promise.then((res) => { console.log('then:', res);}).catch((err) => { console.log('catch:', err);})解析resolve 函数将 Promise 对象的状态从“未实现”变为“胜利”(即从 pending 变为 resolved),在异步操作胜利时调用,并将异步操作的后果,作为参数传递进来; reject 函数将 Promise 对象的状态从“未实现”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的谬误,作为参数传递进来。 而一旦状态扭转,就不会再变。所以 代码中的reject('error'); 不会有作用。 Promise 只能 resolve 一次,剩下的调用都会被疏忽。所以 第二次的 resolve('success2'); 也不会有作用。 ...

November 4, 2022 · 4 min · jiezi

关于javascript:前端代码优化-减少代码量和冗杂

背景繁杂的代码是一场劫难,对于前期的保护十分不敌对,甚至可能会减少包的体积,影响页面首次下载的工夫,所以为了在前端开发越来越精进,望大家对于代码品质上本人做好把控;因为公司每次代码上线都会有小伙伴之间互相代码评审的强制要求,所以下方的优化其实都是工作中高频遇到的问题,总想着哪天有工夫能有个文档记录一下,PS: 如有问题希指出 Javascript篇switch语句 && 索引代码的优化需要是年级回显,依据数字匹配搜寻对应的明文字符;相似的需要还有回显星期和月份1.简略的switch 实现,if else 实现以及三元实现代码不够简洁 (不举荐)2.应用对象模式建设key-value映射关系&&map优化代码, 简单明了、 function grade(i){ let _Map = new Map([ [1, '一'], [2, '二'], [3, '三'], [4, '四'], [5, '五'], [6, '六'], ]); return _Map.get(i)?_Map.get(i)+'年级':'年级匹配不存在'}3.数组+索引优化代码 function grade(i){ return i>0 && i<8 ?['一','二','三','四','五','六','日'][i-1] + '年级':'年级匹配不存在'}默认值优化用||代替三元写法 三元写法function name(str) { return str? str : "erin"}优化||写法function name(str) { return str || "erin"}单个if else带return,应用三元写法/*传统写法*/function test (bool) { if(bool) { return 1 } else { return 0 }}/*简洁三元写法*/function test (bool) { return bool ? 1 : 0}多个if else多后果返回能够参照上方(3.数组+索引优化代码)本文参考https://juejin.cn/post/684490...学无止境,愿我在架构师的路线上越来越近

November 3, 2022 · 1 min · jiezi

关于javascript:来自大厂-10-前端面试题附答案整理版

v-model语法糖是怎么实现的<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <!-- v-model 只是语法糖而已 --> <!-- v-model 在外部为不同的输出元素应用不同的property并抛出不同的事件 --> <!-- text和textarea 元素应用value property 和 input事件 --> <!-- checkbox 和radio应用checked property 和 change事件--> <!-- select 字段将value 作为prop 并将change 作为事件 --> <!-- 留神:对于须要应用输入法(如中文、日文、韩文等)的语言,你将会发现v-model不会再输入法 组合文字过程中失去更新 --> <!-- 再一般标签上 --> <input v-model="sth" /> //这一行等于下一行 <input v-bind:value="sth" v-on:input="sth = $event.target.value" /> <!-- 再组件上 --> <currency-input v-model="price"></currentcy-input> <!--上行代码是上行的语法糖 <currency-input :value="price" @input="price = arguments[0]"></currency-input> --> <!-- 子组件定义 --> Vue.component('currency-input', { template: ` <span> <input ref="input" :value="value" @input="$emit('input', $event.target.value)" > </span> `, props: ['value'], }) </body></html>forEach和map办法有什么区别这办法都是用来遍历数组的,两者区别如下: ...

November 3, 2022 · 5 min · jiezi

关于javascript:JS模块化CJSAMDCMDES6前端面试知识点查漏补缺

本文从以工夫为轴从以下几个方面进行总结JS模块化。从无模块化 => IIFE => CJS => AMD => CMD => ES6 => webpack这几个阶段进行剖析。历史幼年期:无模块化形式须要在页面中加载不同的js,用于动画,组件,格式化多种js文件被分在了不同的文件中不同的文件被同一个模板所援用<script src="jquery.js"></script><script src="main.js"></script><script src="dep1.js"></script>此处写法文件拆分是最根底的模块化(第一步) * 面试中的诘问script标签的参数:async & defer <script src="jquery.js" async></script>总结三种加载一般加载:解析到立刻阻塞,立即下载执行以后scriptdefer加载:解析到标签开始异步加载,在后盾下载加载js,解析实现之后才会去加载执行js中的内容,不阻塞渲染async加载:(立刻执行)解析到标签开始异步加载,下载实现后开始执行并阻塞渲染,执行实现后持续渲染 兼容性:> IE9问题可能被疏导到 => 1. 浏览器的渲染原理 2.同步异步原理 3.模块化加载原理呈现的问题净化全局作用域成长期(模块化前夜) - IIFE(语法测的优化) 作用域的把控let count = 0;const increase = () => ++count;const reset = () => { count = 0;}利用函数的块级作用域 (() => { let count = 0; ...})//最根底的局部实现一个最简略的模块const iifeModule = (() => { let count = 0; const increase = () => ++count; const reset = () => { count = 0; } console.log(count); increase();})();诘问:独立模块自身的额定依赖如何优化优化1:依赖其余模块的传参型const iifeModule = ((dependencyModule1,dependencyModule2) => { let count = 0; const increase = () => ++count; const reset = () => { count = 0; } console.log(count); increase(); ...//能够解决依赖中的办法})(dependencyModule1,dependencyModule2)参考 前端进阶面试题具体解答 ...

November 3, 2022 · 2 min · jiezi

关于javascript:前端面试查漏补缺

对HTML语义化的了解语义化是指依据内容的结构化(内容语义化),抉择适合的标签(代码语义化)。艰深来讲就是用正确的标签做正确的事件。 语义化的长处如下: 对机器敌对,带有语义的文字表现力丰盛,更适宜搜索引擎的爬虫爬取无效信息,有利于SEO。除此之外,语义类还反对读屏软件,依据文章能够主动生成目录;对开发者敌对,应用语义类标签加强了可读性,构造更加清晰,开发者能清晰的看出网页的构造,便于团队的开发与保护。常见的语义化标签: <header></header> 头部<nav></nav> 导航栏<section></section> 区块(有语义化的div)<main></main> 次要区域<article></article> 次要内容<aside></aside> 侧边栏<footer></footer> 底部代码输入后果var length = 10;function fn() { console.log(this.length);}var obj = { length: 5, method: function(fn) { fn(); arguments[0](); }};obj.method(fn, 1);输入后果: 10 2 解析: 第一次执行fn(),this指向window对象,输入10。第二次执行arguments[0],相当于arguments调用办法,this指向arguments,而这里传了两个参数,故输入arguments长度为2。浏览器 浏览器架构单过程浏览器时代 单过程浏览器是指浏览器的所有功能模块都是运行在同一个过程里,这些模块蕴含了网络、插件、JavaScript运行环境、渲染引擎和页面等。其实早在2007年之前,市面上浏览器都是单过程的 毛病 不稳固:一个插件的意外解体会引起整个浏览器的解体不晦涩:所有页面的渲染模块、JavaScript执行环境以及插件都是运行在同一个线程中的,这就意味着同一时刻只能有一个模块能够执行不平安:能够通过浏览器的破绽来获取零碎权限,这些脚本获取零碎权限之后也能够对你的电脑做一些歹意的事件,同样也会引发平安问题以上这些就是过后浏览器的特点,不稳固,不晦涩,而且不平安多过程浏览器时代 因为过程是互相隔离的,所以当一个页面或者插件解体时,影响到的仅仅是以后的页面过程或者插件过程,并不会影响到浏览器和其余页面,这就完满地解决了页面或者插件的解体会导致整个浏览器解体,也就是不稳固的问题JavaScript也是运行在渲染过程中的,所以即便JavaScript阻塞了渲染过程,影响到的也只是以后的渲染页面,而并不会影响浏览器和其余页面,因为其余页面的脚本是运行在它们本人的渲染过程中的Chrome把插件过程和渲染过程锁在沙箱外面,这样即便在渲染过程或者插件过程外面执行了恶意程序,恶意程序也无奈冲破沙箱去获取零碎权限。 最新的Chrome浏览器包含:1个浏览器(Browser)主过程、1个 GPU 过程、1个网络(NetWork)过程、多个渲染过程和多个插件过程浏览器过程 。次要负责界面显示、用户交互、子过程治理,同时提供存储等性能。渲染过程 。外围工作是将 HTML、CSS 和 JavaScript 转换为用户能够与之交互的网页,排版引擎Blink和JavaScript引擎V8都是运行在该过程中,默认状况下,Chrome会为每个Tab标签创立一个渲染过程。出于平安思考,渲染过程都是运行在沙箱模式下。GPU过程 。其实,Chrome刚开始公布的时候是没有GPU过程的。而GPU的应用初衷是为了实现3D CSS的成果,只是随后网页、Chrome的UI界面都抉择采纳GPU来绘制,这使得GPU成为浏览器广泛的需要。最初,Chrome在其多过程架构上也引入了GPU过程。网络过程 。次要负责页面的网络资源加载,之前是作为一个模块运行在浏览器过程外面的,直至最近才独立进去,成为一个独自的过程。插件过程 。次要是负责插件的运行,因插件易解体,所以须要通过插件过程来隔离,以保障插件过程解体不会对浏览器和页面造成影响代码输入后果 var a=3; function c(){ alert(a); } (function(){ var a=4; c(); })();js中变量的作用域链与定义时的环境无关,与执行时无关。执行环境只会扭转this、传递的参数、全局变量等 如何优化动画?对于如何优化动画,咱们晓得,个别状况下,动画须要频繁的操作DOM,就就会导致页面的性能问题,咱们能够将动画的position属性设置为absolute或者fixed,将动画脱离文档流,这样他的回流就不会影响到页面了。 new 一个函数产生了什么结构调用: 发明一个全新的对象这个对象会被执行 [[Prototype]] 连贯,将这个新对象的 [[Prototype]] 链接到这个构造函数.prototype 所指向的对象这个新对象会绑定到函数调用的 this如果函数没有返回其余对象,那么 new 表达式中的函数调用会主动返回这个新对象JS 数据类型根本类型:Number、Boolean、String、null、undefined、symbol(ES6 新增的),BigInt(ES2020)援用类型:Object,对象子类型(Array,Function) ...

November 3, 2022 · 4 min · jiezi