-
HTML5 提供了丰富的 input 类型,每个都有特定的用途和浏览器支持。<input>标签作为HTML表单中用户输入数据的核心元素,通过type属性的不同取值,能实现多样化的输入功能。下面我将从各常见取值的功能、使用场景、代码示例等方面,为你详细介绍<input>标签的type属性值: 一、引言在Web开发中,<input>标签是构建表单、获取用户输入的基础组件。而type属性作为<input>标签的核心属性,通过赋予不同的值,能够将<input>标签呈现为多种输入控件类型,满足多样化的用户输入需求。从简单的文本输入到复杂的文件上传、日期选择等,了解并熟练运用<input>标签常见的type属性值,是开发者打造高效、易用表单的关键。二、文本类输入类型2.1 text功能:text是<input>标签的默认type值,用于创建单行文本输入框,用户可以在其中输入任意字符串内容,如用户名、简单描述等。使用场景:广泛应用于用户注册登录页面的用户名输入、搜索框、简单信息填写等场景。示例代码:12<label for="username">用户名:</label><input type="text" id="username" name="username" placeholder="请输入用户名">2.2 password功能:创建密码输入框,用户输入的内容会以掩码形式(如星号*或圆点•)显示,以保护用户密码隐私。使用场景:主要用于登录页面的密码输入、涉及密码修改或确认密码的表单。示例代码:12<label for="password">密码:</label><input type="password" id="password" name="password" placeholder="请输入密码">2.3 textarea(严格来说不属于<input>标签,但常与<input>协同使用)功能:虽然textarea是独立的HTML标签,但在文本输入方面常与<input>对比。它用于创建多行文本输入区域,用户可输入大量文本内容,如评论、文章内容等。使用场景:博客文章编辑、用户评论提交、反馈意见填写等需要输入较长文本的场景。示例代码:12<label for="comment">用户评论:</label><textarea id="comment" name="comment" rows="5" cols="50" placeholder="请留下您的宝贵意见"></textarea>2.4 email 邮箱输入1234567<input type="email" id="email" name="email" placeholder="user@example.com" multiple pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" required>属性说明:multiple:允许输入多个邮箱(逗号分隔)浏览器会自动验证邮箱格式2.5 tel 电话号码1234567<input type="tel" id="phone" name="phone" placeholder="13800138000" pattern="^1[3-9]\d{9}$" maxlength="11" inputmode="numeric">国际电话号码支持:12345<!-- 使用国际电话格式 --><input type="tel" name="international-phone" placeholder="+86 138 0013 8000" pattern="^\+[1-9]\d{0,3}\s?\d{4,14}$">5. 2.5 url URL输入123456<input type="url" id="website" name="website" placeholder="https://example.com" pattern="https?://.+" required>三、选择类输入类型3.1radio功能:创建单选按钮,多个具有相同name属性值的radio按钮构成一组,用户只能在一组中选择一个选项。使用场景:用于选择唯一答案的场景,如性别选择(男/女)、学历选择(小学/中学/大学等)。示例代码:123<label for="gender-male">性别:</label><input type="radio" id="gender-male" name="gender" value="male"> 男<input type="radio" id="gender-female" name="gender" value="female"> 女3.2checkbox功能:创建复选框,用户可以同时选择多个选项,多个checkbox可以具有不同的name属性值。使用场景:用于选择多个选项的场景,如兴趣爱好选择(音乐、运动、阅读等)、订阅服务选择等。示例代码:1234<label for="hobby-music">兴趣爱好:</label><input type="checkbox" id="hobby-music" name="hobby" value="music"> 音乐<input type="checkbox" id="hobby-sports" name="hobby" value="sports"> 运动<input type="checkbox" id="hobby-reading" name="hobby" value="reading"> 阅读3.3select(<select>标签搭配<option>标签,与<input>协同使用)功能:创建下拉选择框,通过<option>标签定义可选选项,用户点击下拉菜单选择一个或多个选项(可通过multiple属性实现多选)。使用场景:适用于选项较多且需要节省页面空间的选择场景,如国家选择、城市选择、商品类别选择等。示例代码:123456<label for="country">选择国家:</label><select id="country" name="country"> <option value="china">中国</option> <option value="usa">美国</option> <option value="uk">英国</option></select>四、数值与日期类输入类型4.1 number功能:创建数值输入框,限定用户只能输入数字,还可通过min、max、step等属性设置数值的范围和步长。使用场景:用于输入年龄、数量、价格等数值的场景,如商品购买数量输入、年龄填写等。示例代码:12<label for="quantity">购买数量:</label><input type="number" id="quantity" name="quantity" min="1" max="100" step="1" value="1">4.2 date功能:创建日期选择器,用户可通过可视化界面选择日期,输入格式符合ISO 8601标准(如YYYY-MM-DD)。使用场景:适用于需要用户选择日期的场景,如生日填写、会议日期选择、订单日期选择等。示例代码:12<label for="birthdate">出生日期:</label><input type="date" id="birthdate" name="birthdate">4.3 datetime-local功能:创建日期和时间选择器,用户可以同时选择日期和时间,格式为YYYY-MM-DDTHH:MM(T为分隔符)。使用场景:适用于预约时间选择、活动开始/结束时间设置等场景。示例代码:12<label for="appointment-time">预约时间:</label><input type="datetime-local" id="appointment-time" name="appointment-time">五、其他特殊输入类型5.1 file功能:创建文件选择框,用户可以选择本地文件上传到服务器,通常需要配合表单的enctype="multipart/form-data"属性使用。使用场景:用于文件上传功能,如图片上传、文档上传、简历上传等。示例代码:12345<form action="upload.php" method="post" enctype="multipart/form-data"> <label for="upload-file">上传文件:</label> <input type="file" id="upload-file" name="upload-file"> <input type="submit" value="上传"></form>5.2 submit功能:创建提交按钮,点击该按钮会将表单数据按照<form>标签指定的action和method提交到服务器。使用场景:所有需要提交表单数据的场景都需要使用submit按钮。示例代码:1234<form action="process.php" method="post"> <!-- 表单其他输入元素 --> <input type="submit" value="提交表单"></form>5.3 reset功能:创建重置按钮,点击该按钮会将表单内所有输入元素的值恢复到初始状态。使用场景:在需要用户重新填写表单的场景中使用,但由于可能导致用户误操作丢失已输入数据,实际应用中使用频率较低。示例代码:1234<form action="process.php" method="post"> <!-- 表单其他输入元素 --> <input type="reset" value="重置表单"></form>5.4 button功能:创建普通按钮,本身不具备提交表单或重置表单的功能,需要配合JavaScript为其添加事件处理逻辑,如点击触发弹窗、执行特定函数等。使用场景:常用于需要自定义交互功能的场景,如触发数据加载、显示隐藏元素等。示例代码:1<button type="button" onclick="alert('按钮被点击了!')">点击我</button>六、HTML5新增类型6.1 移动端优化类型 type="text" + inputmode12345678<!-- 不同的输入模式 --><input type="text" inputmode="text" placeholder="文本键盘"><input type="text" inputmode="numeric" placeholder="数字键盘"><input type="text" inputmode="decimal" placeholder="小数键盘"><input type="text" inputmode="tel" placeholder="电话键盘"><input type="text" inputmode="email" placeholder="邮箱键盘"><input type="text" inputmode="url" placeholder="URL键盘"><input type="text" inputmode="search" placeholder="搜索键盘">6.2 特殊用途类型123456789101112131415161718192021222324252627282930313233343536373839404142434445<!-- 地址表单 --><form id="address-form"> <div class="form-group"> <label for="fullname">姓名</label> <input type="text" id="fullname" name="fullname" required> </div> <div class="form-group"> <label for="phone">电话</label> <input type="tel" id="phone" name="phone" pattern="^1[3-9]\d{9}$" required> </div> <div class="form-group"> <label for="email">邮箱</label> <input type="email" id="email" name="email" required> </div> <div class="form-group"> <label for="province">省份</label> <select id="province" name="province" required> <option value="">请选择</option> <option value="beijing">北京</option> <option value="shanghai">上海</option> </select> </div> <div class="form-group"> <label for="address">详细地址</label> <input type="text" id="address" name="address" required> </div> <div class="form-group"> <label for="postcode">邮编</label> <input type="text" id="postcode" name="postcode" pattern="\d{6}" required> </div> <div class="form-group"> <label> <input type="checkbox" name="default_address" value="1"> 设为默认地址 </label> </div> <button type="submit">保存地址</button></form>
-
大部分前端开发,一提到“文件上传校验”,脑子里立刻蹦出三件事:校验 MIME 类型校验文件大小再加一堆出错提示、兜底逻辑、边界处理然后——自然地把这些事全扔给 JavaScript。看起来很专业,对不对?直到有一天,我上传了一个文件,还没等它到后端,就被自己前端逻辑搞崩了。于是我开始往代码里疯狂加条件、加双重判断、加“测试用特例”, 结果越补越乱,越写越心虚。也就是在那段时间,我无意间翻出一个自己“从来没当回事”的 HTML 小特性。这个小东西,直接改变了我处理文件上传的方式。今天就把这个发现,从头讲给你听。那个悄悄毁掉你上传体验的“常见写法”大部分人处理上传,基本都是这样写:1<input type="file" id="ImageUpload" />然后再配套一段 JavaScript 做校验:123456789const fileInput = document.getElementById('ImageUpload'); fileInput.addEventListener('change', (e) => { const inputFile = e.target.files[0]; if (!inputFile.type.startsWith("image/")) { alert("You can upload only images."); }});写完之后,内心是有点成就感的:“你看,我可以提示用户:你选错文件类型啦~”但问题来了:用户 已经点了按钮已经打开系统文件选择器已经在一大堆文件里翻来翻去已经选好了一个文件然后你跳出来说:“不行哦,这个传不上来。”这就是典型的——事后教育式交互。 拖慢体验不说,错误率还高得离谱。更扎心的是: 即便你写了这段 JavaScript 校验, 依然会遇到各种奇奇怪怪的测试样例:MIME 类型标错的文件看起来是 image,实则不是图片随便起了个后缀的二进制垃圾文件把 PDF 假装成 PNG 的伪装文件也就是说:你费劲写了一堆前端验证, 但它既拦不住真高手,也常常在烦普通用户。直到我遇见今天的主角。改变一切的 HTML 小特性:accept我说的就是这个东西:1<input type="file" accept="image/*" />一个几乎所有人都见过、 却没几个人认真用过的属性:**accept**。它小到只有几个字符, 但给上传体验带来的改变,是维度级别的:在文件选择器里,自动隐藏所有不支持的文件用户甚至 看不到错误类型可以选自动根据 MIME 类型和后缀做过滤兼容一大堆后台规定和浏览器格式细节能轻松帮你砍掉 50%–60% 的上传校验代码一句话:用户选不到错的文件, 你就少写一半“事后骂人”的 JavaScript。真正的魔法:让用户一开始就没机会选错当你这么写:1<input type="file" accept="image/*" />接下来会发生什么?用户点击上传按钮打开系统的选文件窗口窗口里只会展示“被认定为图片”的文件诸如 PDF、DOC、乱七八糟的其他格式,统统隐藏在这个阶段, 你的 JavaScript 甚至还没出场, 用户就已经被温柔地“拦在正确的范围里”。如果你要上传的是 PDF 呢?1<input type="file" accept="application/pdf" />再复杂一点,比如: 你想允许用户上传 多种类型:图片 + PDF:1<input type="file" accept=".png, .jpg, .jpeg, .pdf" />只想要视频?1<input type="file" accept="video/*" />只要音频?1<input type="file" accept="audio/*" />只要 Office 文件(Word / Excel / PPT)?1<input type="file" accept=".docx, .xlsx, .pptx" />这些全都只是 HTML 在帮你干活。 你甚至不需要写一行 JS, 就能把 90% 的“明显错误文件”挡在门外。那如果我需要更精细的控制呢?当然,现实项目里,你往往不只关心“格式对不对”。 比如:“必须是 PDF,且不能超过 2MB。”这时候你就不用搞“二选一”——不是“要么用 accept”, 也不是“只用 JS 校验”。最聪明的做法,是:两者叠加使用。先用 HTML 把格式错得离谱的全部挡掉, 再用 JavaScript 做更细节的逻辑,比如文件大小。举个简化版例子:1<input type="file" id="resumeFile" accept=".pdf" />12345678document.getElementById("resumeFile").addEventListener("change", (e) => { const file = e.target.files[0]; if (file.size > 2 * 1024 * 1024) { alert("You can upload the file of maximum 2MB only."); e.target.value = ""; // 清空选择 }});这样一来:HTML 帮你挡掉 非 PDF 的所有文件JS 再帮你筛掉 超过 2MB 的那部分到了后端,你再进行最终验证:再判断 MIME再判断大小再检验文件内容是否真的是你要的类型这才是一个真正安全又顺滑的上传流程:第一道关:accept(友好 + 直观)第二道关:前端 JS(体验 + 提前反馈)第三道关:后端校验(绝对安全兜底)多种文件类型的“精确过滤”,完全不需要第三方库很多时候,你上传的不是“所有图片”, 而是特定格式,比如只要 PNG 和 MP4。以前很多人第一反应是: “写个复杂点的正则吧。”但其实,只要这样写就够了:1<input type="file" accept="image/png, video/mp4" />再比如,你的后台只接受 CSV:1<input type="file" accept=".csv, text/csv" />这背后复杂的 MIME 映射、兼容性细节、各种边界情况, 浏览器已经帮你扛了大半。你只要静静地写对 accept 里的字符串就行。不用上第三方组件, 不用写一堆莫名其妙的兼容代码, HTML 本身就足够强。浏览器支持情况:能跑的地方,几乎都能用很多人听到这里,第一个问题是:“这么好用,会不会只在个别浏览器有效?”简单给你一句话版结论:accept 属性,在主流平台上几乎是全量支持:Chrome ✔Firefox ✔Safari ✔Edge ✔iOS Safari ✔Android Chrome ✔也就是说: 你可以非常安心地在正常项目里,上这个属性。再强调一次:不是说不要 JS,而是别让 JS 做本不该它做的事我并不是说:“用 HTML 就够了,JavaScript 都删掉吧。”JavaScript 在上传逻辑里,依然非常重要:尺寸校验多文件规则上传进度条异步请求、重试机制各种复杂业务约束这些都是 HTML 做不到的地方。我想说的是:有些事情,HTML 已经帮你想好了, 你再用 JS 去重复造轮子, 不仅费力,还容易写出 bug。有时候,一行写错的 JS, 能让你整个上传逻辑直接翻车; 而一个正确的 HTML 属性, 则可以在问题发生之前,就悄悄帮你挡掉一半错误输入。常见文件类型对应的MIME类型:文件类型扩展名MIME类型JPEG图像.jpg, .jpegimage/jpegPNG图像.pngimage/pngGIF图像.gifimage/gifWebP图像.webpimage/webpSVG图像.svgimage/svg+xmlPDF文档.pdfapplication/pdfWord文档.docapplication/mswordWord文档.docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.documentExcel文件.xlsapplication/vnd.ms-excelExcel文件.xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetPPT文件.pptapplication/vnd.ms-powerpointPPT文件.pptxapplication/vnd.openxmlformats-officedocument.presentationml.presentation文本文件.txttext/plainHTML文件.html, .htmtext/htmlCSS文件.csstext/cssJavaScript.jsapplication/javascriptJSON文件.jsonapplication/jsonXML文件.xmlapplication/xmlZIP压缩.zipapplication/zipRAR压缩.rarapplication/x-rar-compressed7Z压缩.7zapplication/x-7z-compressedMP3音频.mp3audio/mpegWAV音频.wavaudio/wavOGG音频.oggaudio/oggMP4视频.mp4video/mp4AVI视频.avivideo/x-msvideoMOV视频.movvideo/quicktime最后的小结:学会用好这一行,你会讨厌你以前的写法如果你今天只能带走一件事,那就是:下次写 <input type="file"> 的时候, 先想想:“我到底允许什么类型?”然后,老老实实写上 accept。从此以后,你会发现:用户不再频繁选错文件你的错误弹窗少了一半你可以删掉一堆啰嗦的前端类型校验上传流程变得“自然顺滑”,而不是“处处设陷阱”HTML 没有突然变聪明。 只是我们过去很多年, 把它当成了“只能画表单的塑料壳”, 忘了它其实有很多细腻的小能力,可以让体验变得更优雅。写得越久,我越服的一句话是:代码不一定要写得花哨, 但一定要优先把 已有的好工具,用明白。accept 就是这样的工具之一。用过一次,你就再也不会回去写那种: “上来不设限制、事后狂 alert 用户”的上传逻辑了。accept 属性是提高用户体验的重要工具,但需要注意:不是安全措施:可以被绕过,必须进行服务器验证提供良好UX:帮助用户快速找到正确文件结合其他属性:与 multiple、capture 等属性配合使用现代浏览器支持:大部分浏览器都支持,但移动端行为可能不同
-
刚学前端那会儿,我处理外链的方式简单粗暴:1<a href="https://example.com">随便一个外链</a>点一下,当前标签直接跳走。 用户刚打开好不容易进来的页面,下一秒——嗖地没了。后来我发现 target="_blank" 这个“神器”:1<a href="https://example.com" target="_blank">在新标签打开的外链</a>从此以后,外链都乖乖在新标签里打开:原页面留在那儿新内容另起一页体验一下子顺眼了很多,我自己也用得很爽。 直到有一天,我才知道:只加 target="_blank",你其实给自己埋了一个安全坑。问题不在“新标签”,而在它背后悄悄多出的那根“线”当你用 target="_blank" 打开一个新标签时, 浏览器会在两个页面之间,悄悄建立一条 JavaScript 通道。具体来说:新开的页面,可以通过一个叫 window.opener 的对象, 直接“反向操作”你的原页面。就像这样简单粗暴的一行:1window.opener.location = 'https://a-new-page.com';意思就是:“把原来的那一页,重定向到我指定的这个新地址。”这种操作,有个专业(但听起来就很阴间)的名字:tabnabbing(标签劫持)。你以为你只是好心把外链丢到新标签页, 结果人家顺着这条“绳子”,直接把你的原页面拖走了。更可怕的是——用户根本意识不到发生了什么。刚才还在你的后台系统里操作刷一下,页面“看起来差不多”,其实已经换了站点继续输入密码、填表单、点击按钮……全程没警觉,你的平台就这样被“借壳上演了一场骗局”。哪些场景尤其危险?这种“标签劫持”风险,对下面这些场景尤其致命:管理后台(Admin 面板)支付系统 / 充值页面邮箱 / 账号登录页SaaS 后台、数据控制台政府、医疗、教育等敏感业务页面只要你的用户:在你这个页面里登录过输入过敏感信息做过对账号有影响的操作那一旦被人利用 window.opener 做文章,你和用户就一起掉坑里了。一行就能补上的安全大洞:rel="noopener noreferrer"好消息是,修这个问题,真的只要 加一小段属性:1<a href="https://example.com" target="_blank" rel="noopener noreferrer">更安全的外链</a>就这一行:1rel="noopener noreferrer"后面这两个值,分别干这些事:noopener:直接剪断那根“控制原页面”的线rel="noopener" 的作用是:告诉浏览器: “新开的那一页,不允许通过 window.opener 访问/控制我。”也就是说:新标签页依然能正常打开但它不再有权限反向操作你的原页面window.opener 变成 null,这条路被你堵死了tabnabbing 这条攻击链,直接被斩断。noreferrer:顺带把“我是谁”也隐藏掉rel="noreferrer" 做的事情是:在跳转时,不再把“从哪个页面来的”这个信息, 通过 HTTP Referer 头部传给目标站点。简单说:对方拿不到你页面的 URL 作为来源某些老浏览器里,不加这个就没法同时兼容 noopener也顺手给用户多了一层隐私保护两个属性一起用,就是现在业界推荐的“标配”:1rel="noopener noreferrer"它们一起做到了:不给对方远程控制权不乱暴露用户从哪儿来的还顺便补上老浏览器的坑你付出的成本? 不过就是在 <a> 标签里,多敲了 20 来个字符而已。“浏览器不是已经帮我自动加 noopener 了吗?”确实,部分现代浏览器 在某些场景里, 会自动为 target="_blank" 的外链加上 noopener。但问题有两个:并不是所有浏览器都这么做你也不能保证将来改动、第三方组件、特殊环境里不会漏掉作为一个开发者, 在这种“成本极低、收益极大”的地方, 与其赌浏览器,不如自己写死。亲手多写 1 行, 好过哪天追着用户说:“这个问题是浏览器的问题,不是我。”什么时候该用?什么时候不必用?这对组合,也不是“逢 <a> 必加”。可以简单记住一条:给“外链”加上它指向你无法完全信任的站点跳到第三方支付、第三方内容平台跳到合作方、广告方、外部工具这些地方,一律建议:1<a href="https://third-party.com" target="_blank" rel="noopener noreferrer">第三方页面</a>内部导航,正常情况下不用加如果你的链接是:同一域名下的页面之间跳转同一 SPA 应用内部用 <a> 做路由(而不是 window.open)必须依赖 window.opener 做明确的、可信的双向通信那就不必强行加 noopener。 在同一个受控环境下,相互通信本身就是设计的一部分。但有一点可以坚守:只要是 “点了就跳出我控制范围” 的链接, 我都会习惯性补上这两个属性。顺手一个小优化:用 CSS 标记所有“会开新标签的外链”为了给用户一点“视觉提示”, 我还习惯顺带加一点点 CSS:123456789a[target="_blank"] { cursor: pointer;} a[target="_blank"]::after { content: "↗"; font-size: 0.8em; margin-left: 0.25em;}这样用户一眼就能看出来:这个链接点了会开新标签跳出当前站点,不是普通内部导航UX 更清晰,安全感也更足一点。最后一句:真正“专业”的前端,很多时候就藏在这种小细节里rel="noopener noreferrer" 看起来只是一个不起眼的小属性。页面不加照样能跑一般用户也察觉不到区别控制台也不会给你报红可它解决的是一个:“安安静静存在了很多年,但一旦被利用就很致命”的问题。你多写这一行:用户更安全你的站更难被拿去当“跳板”或钓鱼工具安全审计时看你的代码,也会多一丝尊重成本几乎为零,收益却相当可观。所以,下次你再写:1<a href="https://example.com" target="_blank">外链</a>不妨养成一个小习惯,顺手补上这一段:1rel="noopener noreferrer"就这一行, 让外链安全了一大截。链接类型处理表格链接类型targetrel属性说明内部链接不设置或_self(无需)站内导航内部资源_blanknoopenerPDF、下载文件等可信外部_blanknoopener noreferrer合作伙伴、参考资料用户内容_blankugc nofollow noopener noreferrer评论、论坛帖子广告链接_blanksponsored nofollow noopener noreferrer付费广告、推广社交媒体_blanknoopener noreferrer分享按钮登录/注册_blanknoopener noreferrerOAuth认证等
-
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <button type="button" onclick="addRow()">添加</button> <button type="button" onclick="delRow()">删除</button> <div style="height: 50vh;"> <table> <thead><tr><td>表头</td></tr></thead> <tbody id="tb"></tbody> </table> </div> </body><script> function addRow(){ var html = '' for (let i = 0; i < 100000; i++) { html += '<tr><td>'+i+'</td></tr>' } document.getElementById('tb').innerHTML = html } function delRow(){ document.getElementById('tb').innerHTML = '' }</script></html>一段简单的表格添加行代码,为什么刚开始我在谷歌浏览器的任务管理器上看到的标签页内存占用是30M,然后点击添加后内存变成510M,点击删除后内存占用还有500M,而且刷新页面内存还是占用500M,想问下有没有解决方法(不使用虚拟滚动)。下图为内存占用情况
-
JavaScript 是一种广泛使用的编程语言,主要用于网页开发,使网页具有交互性和动态功能。以下是 JavaScript 的主要特点和用途:1. 基本概念脚本语言:JavaScript 是一种解释型语言,代码在浏览器中直接执行,无需编译。跨平台:支持所有主流浏览器(如 Chrome、Firefox、Safari、Edge)和操作系统。动态类型:变量类型在运行时确定,无需提前声明。2. 主要用途前端开发:与 HTML 和 CSS 结合,用于创建动态网页,如表单验证、动画、内容更新等。后端开发:通过 Node.js,JavaScript 也可用于服务器端编程,处理数据库操作和 API 开发。移动应用开发:借助 React Native 等框架,JavaScript 可用于开发跨平台移动应用。桌面应用开发:通过 Electron 等框架,JavaScript 可用于构建跨平台桌面应用。3. 核心特性事件驱动:通过事件监听和回调函数响应用户操作,如点击、键盘输入等。异步编程:支持 Promise 和 async/await,便于处理异步操作,如网络请求。面向对象:支持基于原型的面向对象编程,允许创建类和对象。4. 基本语法变量声明:使用 var、let 或 const 声明变量。函数:使用 function 关键字定义函数,支持箭头函数。条件与循环:支持 if、else、switch 等条件语句,以及 for、while 等循环结构。5. DOM 操作文档对象模型 (DOM):JavaScript 可以操作 DOM,动态修改网页内容和结构。选择元素:使用 document.getElementById、document.querySelector 等方法选择元素。修改内容:通过 innerHTML、textContent 等属性修改元素内容。6. 工具与框架开发工具:常用工具包括 Chrome DevTools、VS Code 等。前端框架:流行的框架有 React、Angular、Vue.js 等。构建工具:常用工具有 Webpack、Babel 等。7. 示例代码javascript复制// 简单的 JavaScript 示例let message = "Hello, World!";console.log(message);// 函数示例function greet(name) { return "Hello, " + name + "!";}// 事件监听示例document.getElementById("myButton").addEventListener("click", function() { alert("Button clicked!");});8. 学习资源MDN Web Docs:提供全面的 JavaScript 文档和教程。JavaScript.info:适合初学者的教程网站。Codecademy:提供互动式 JavaScript 课程总结:JavaScript 是现代 Web 开发的核心语言,掌握它将为你在前端、后端及全栈开发领域提供坚实的基础。
-
前端开发是构建网页和Web应用程序用户界面的过程,主要涉及HTML、CSS和JavaScript等技术。以下是对这些技术的简要介绍:1. HTML(超文本标记语言)HTML是前端开发的基础,用于定义网页的结构和内容。它通过标签(tags)来标记文本、图像、链接等元素,使浏览器能够正确解析和显示网页内容。基本结构:html复制<!DOCTYPE html><html><head> <title>页面标题</title></head><body> <h1>这是一个标题</h1> <p>这是一个段落。</p></body></html> 运行 HTML常用标签:<h1> 到 <h6>:标题标签,表示不同级别的标题。<p>:段落标签。<a>:超链接标签,用于创建链接。<img>:图像标签,用于插入图片。<div> 和 <span>:容器标签,用于布局和样式控制。2. CSS(层叠样式表)CSS用于控制网页的样式和布局,使网页内容更加美观和易于阅读。它通过选择器(selectors)来指定需要样式化的HTML元素,并通过属性和值来定义样式。基本语法:css复制h1 { color: blue; font-size: 24px;}常用属性:color:文本颜色。font-size:字体大小。margin 和 padding:外边距和内边距。display:控制元素的显示方式(如块级、内联等)。flexbox 和 grid:用于创建复杂的布局。3. JavaScriptJavaScript是一种脚本语言,用于实现网页的交互功能。它可以在浏览器中动态地修改HTML和CSS,处理用户输入,以及与服务器进行通信。基本语法:javascript复制document.getElementById("demo").innerHTML = "Hello, World!";常用功能:DOM操作:通过JavaScript可以动态地修改HTML元素的内容、属性和样式。事件处理:可以为HTML元素添加事件监听器,响应用户的点击、输入等操作。AJAX:通过异步JavaScript和XML(AJAX)技术,可以在不重新加载页面的情况下与服务器进行数据交换。ES6+:现代JavaScript引入了许多新特性,如箭头函数、模板字符串、解构赋值、Promise、async/await等,使代码更加简洁和易于维护。4. 前端框架和库为了提高开发效率和代码质量,前端开发者通常会使用一些流行的框架和库:React:由Facebook开发的一个用于构建用户界面的JavaScript库,采用组件化开发模式。Vue.js:一个轻量级、易上手的JavaScript框架,适合构建单页应用(SPA)。Angular:由Google开发的一个全面的前端框架,适合构建大型应用。5. 前端工具前端开发中还涉及到许多工具,用于代码的构建、调试和优化:包管理器:如npm和Yarn,用于管理项目依赖。构建工具:如Webpack和Parcel,用于打包和优化代码。版本控制:如Git,用于代码的版本管理和协作开发。调试工具:如Chrome DevTools,用于调试和优化网页性能。6. 响应式设计响应式设计是一种使网页能够适应不同设备和屏幕尺寸的技术。通过使用CSS媒体查询(Media Queries)和弹性布局(Flexbox、Grid),可以确保网页在桌面、平板和手机等设备上都能良好显示。媒体查询示例:css复制@media (max-width: 600px) { body { background-color: lightblue; }}7. 前端性能优化前端性能优化是提升网页加载速度和用户体验的关键。常见的优化手段包括:减少HTTP请求:通过合并文件、使用CSS Sprites等方式减少请求次数。压缩资源:压缩HTML、CSS、JavaScript和图片等资源,减少文件大小。使用CDN:通过内容分发网络(CDN)加速静态资源的加载。懒加载:延迟加载非关键资源,如图片和视频,直到用户滚动到它们的位置。总结前端开发涉及多种技术和工具,HTML、CSS和JavaScript是基础,而框架、库和工具则帮助开发者更高效地构建复杂的Web应用。
-
【问题来源】黑龙江农信社【问题简要】开发 vxml 版本自助语音流程时,使用grammer 标签 的 src 属性上送语法文件是,流程跟踪日志中,提示异常【问题类别】vxml 版本自主语音流程开发【AICC解决方案版本】AICC 版本:AICC 22.200.0【问题现象描述】页面中通过 grammar 标签 读取项目中一个 grammar.xml 文件流程文件中提示异常 There was a DEFINE_GRAMMAR failure 语法文件内容如下
-
当涉及到网页元素的实时尺寸变化监测时,element-resize-detector 是一个值得推荐的开源库,本文主要介绍了element-resize-detector监听普通元素的实现示例,感兴趣的可以了解一下目录说明:在进行后台系统开发时,经常会用到一些图表展示,当改变浏览大小后,这些图表本身是没有响应式的,可以借助第三方插件element-resize-detector来监听窗口的变化一、element-resize-detector 安装当涉及到网页元素的实时尺寸变化监测时,element-resize-detector 是一个值得推荐的开源库。它能以惊人的速度实现跨浏览器的元素大小调整监听,比传统方法快了约37倍。让我们深入了解这个神器。1npm install element-resize-detectorelement-resize-detector 使用了两种不同的监听策略:对象方式:修改元素CSS属性使其触发布局更新,从而捕获尺寸变化。滚动方式(默认):通过在元素内部创建滚动区域并监听滚动事件,达到无闪烁、高性能的监控效果。该库在处理性能和兼容性方面做了大量工作,包括:对于静态定位(position: static)的元素,会自动转换为相对定位。添加隐藏元素作为内部监听器,以确保在所有浏览器中的稳定运行。二、插件使用1.插件引入1import elementResizeDetectorMaker from "element-resize-detector";2.创建实例对象1234567let erd = elementResizeDetectorMaker();//如果有快速滚动,如果没有不需要进行如下配置let erdUltraFast = elementResizeDetectorMaker({ strategy: "scroll"});3.监听元素12345678910erd.listenTo( document.getElementById("endlistenEartagEchart"), //第一个参数是要监听的dom function (element) { setTimeout(() => { // that.chartBoxW = // document.getElementById("endlistenEartagEchart").offsetWidth - 30; // that.setEchart(); }, 0); } //第二个参数回调 执行dom变化执行的方法 );到此这篇关于element-resize-detector监听普通元素的实现示例的文章就介绍到这了转载自https://www.jb51.net/javascript/3235458vu.htm
-
介绍 使用 Swagger 你只需要按照它的规范去定义接口及接口相关的信息,就可以做到生成接口文档,以及在线接口调试页面官网: swagger.io/ Knife4j 是为 Java MVC 框架集成 Swagger 生成 Api 文档的增强解决方案 使用方式 1. 导入坐标 <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> </dependency> 2. 在配置类中加入 knife4j 相关配置 /** * 通过knife4j生成接口文档 * @return */ @Bean public Docket docket() { ApiInfo apiInfo = new ApiInfoBuilder() .title("苍穹外卖项目接口文档") .version("2.0") .description("苍穹外卖项目接口文档") .build(); Docket docket = new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo) .select() .apis(RequestHandlerSelectors.basePackage("com.sky.controller")) .paths(PathSelectors.any()) .build(); return docket; } 3. 设置静态资源映射,否则接口文档页面无法访问 /** * 设置静态资源映射 * @param registry */ protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); } 常用注解 查看效果 附完整配置类代码: package com.sky.config;import com.sky.interceptor.JwtTokenAdminInterceptor;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;import springfox.documentation.builders.ApiInfoBuilder;import springfox.documentation.builders.PathSelectors;import springfox.documentation.builders.RequestHandlerSelectors;import springfox.documentation.service.ApiInfo;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;/** * 配置类,注册web层相关组件 */@Configuration@Slf4jpublic class WebMvcConfiguration extends WebMvcConfigurationSupport { @Autowired private JwtTokenAdminInterceptor jwtTokenAdminInterceptor; /** * 注册自定义拦截器 * * @param registry */ protected void addInterceptors(InterceptorRegistry registry) { log.info("开始注册自定义拦截器..."); registry.addInterceptor(jwtTokenAdminInterceptor) .addPathPatterns("/admin/**") .excludePathPatterns("/admin/employee/login"); } /** * 通过knife4j生成接口文档 * @return */ @Bean public Docket docket() { log.info("准备生成接口文档..."); ApiInfo apiInfo = new ApiInfoBuilder() .title("苍穹外卖项目接口文档") .version("2.0") .description("苍穹外卖项目接口文档") .build(); Docket docket = new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo) .select() .apis(RequestHandlerSelectors.basePackage("com.sky.controller")) .paths(PathSelectors.any()) .build(); return docket; } /** * 设置静态资源映射 * @param registry */ protected void addResourceHandlers(ResourceHandlerRegistry registry) { log.info("开始设置静态资源映射..."); registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); }} ———————————————— 原文作者:全网第一菜鸡 转自链接:https://learnku.com/articles/85427 版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。
-
网站>网站用于集中提供各种相关的网页。网页>主页,指网站中的首页,通常命名为index.*。当URL中不包含文件名时,即访问网站的主页。HTML文档> 超文本标记语言或超文本链接标示语言(标准通用标记语言下的一个应用)HTML(HyperText Mark-up Language)是一种制作万维网页面的标准语言,是万维网浏览器使用的一种语言,它消除了不同计算机之间信息交流的障碍。 它是目前网络上应用最为广泛的语言,也是构成网页文档的主要语言。HTML文件是由HTML命令组成的描述性文本,HTML命令可以说明文字、图形、动画、声音、表格、链接等。HTML文件的结构包括头部(Head)、主体(Body)两大部分,其中头部描述浏览器所需的信息,而主体则包含所要说明的具体内容。<!DOCTYPE html><html><head><meta charset="UTF-8"><title>页面标题</title></head><body>我是快乐的小男孩<img src="images/boy.gif" /></body></html>经浏览器解析后呈现为超媒体页面,如图:
-
【问题来源】黑龙江农信社【问题简要】开发 vxml 版本自助语音流程时,本地修改代码后,服务器疑似存在缓存问题【问题类别】vxml 版本自主语音流程开发【AICC解决方案版本】AICC 版本:AICC 8.0.71【问题现象描述】在本地开发 vxml 版本自助语音流程时,通过华为配置管理系统,将流程文件连接到本地项目。华为服务器疑似存在缓存问题。如:在原有main请求响应代码中,播放音频文件 1050.wav,本地修改代码为 busy.wav后,通过电话拨号。提示音依旧播放的是 1050.wav 内容重启华为服务器 或过了不确定时长的时间后,才能生效变成 busy.wav还有个问题,如下图:经常不定时的出现 这个错误,造成电话直接挂机麻烦帮忙定位下造成这两个问题的原因,谢谢
-
在开发h5项目的时候 经常需要使用window.open 来打开新页面,但有时会出现失效的情况。 问题复现: 在接口请求完成后,根据返回的结果调用window.open 失效 原因:浏览器出于安全的考虑,会拦截掉非用户操作打开的新页面;实际上,在异步的方法中以及非用户操作打开的新页面都会被拦截(不同浏览器不同版本表现不同,不是所有情况都会被拦截,但是任然需要做兼容处理) 例如: fetch(url,option).then(res=>{ window.open('http://www.test.com')})setTimeout(() => { window.open(this.url, '_blank')}, 100)。。。if (success) window.open(data);解决方案:1、尽量让将调用window.open的方法 写在用户事件中,例如: if (success) { Dialog.alert({ content: '即将跳转单证链接', onConfirm: () => { window.open(data); }, }); }交互上的小修改,这样写需要用户手动确定才会跳转2、 使用a标签进行跳转ajax().then(res => { asyncOpen(res.url)})function asyncOpen(url) { var a = document.createElement('a') a.setAttribute('href', url) a.setAttribute("target", "_blank"); a.setAttribute("download", 'name'); document.body.appendChild(a); a.click(); a.remove();}3、使用中转页面一定要把window.open定义在接口请求的外部,保证新开空白窗口不会被拦截。var newWin = window.open('loading page') ajax().then(res => { newWin.location.href = 'target url'}).catch(() => { newWin.close()})———————————————— 版权声明:本文为CSDN博主「MissXu666」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/MissXu666/article/details/129210313
-
1 前言 网页端一般会遇到各种文件,比如:txt、doc、docx、pdf、xml、xls、xlsx、ppt、pptx、zip、png、jpg等等。 有时候我们不想要把文件下载下来,而是想在线打开文件预览 ,这个时候如果每一种格式都需要我们去写代码造轮子去实现预览功能就太复杂了,并且自己实现的话会有很多兼容性问题。 这个时候 kkFileView 的出现就解决了我们的问题。 2 kkFileView介绍 kkFileView为文件文档在线预览解决方案,该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等 kkFileView 官网 kkFileView 码云地址官网 kkFileView github地址官网 3 kkFileView安装 自 v4.1.0 版本开始 kkFileView 不再免费提供 Windows 和 Linux 的发行安装包了,以前旧版本的安装包也取消了下载入口,要下载安装包还要花99块钱进那个KK开源社区群获取。不过我之前下载过 v4.0.0 版,也够用了,为了方便大家我已经上传百度云了,你可以通过下面文章中的链接进行下载,本文的安装使用教程也是基于 v4.0.0 版本进行操作 。 部署指南参考kkFileView - 在线文件预览 下面介绍Windows、Linux、docker三种安装方式。 3.1 下载Windows或Linux的 v4.0.0 安装包 3.1.1 Windows安装包下载 链接:https://pan.baidu.com/s/1YsuYcYB7oGK4w-byM5VUuQ 提取码:jer1 3.1.2 Linux安装包下载 链接:https://pan.baidu.com/s/1saGMphibd7434GNy5L5Lfw 提取码:axnu 3.2 在Windows或Linux上安装 3.2.1 Windows上安装 第一步:下载的 zip 压缩包解压后进入 bin 目录,双击 startup.bat 启动 kkFileView,如图: 第二步:30秒后进入 log 目录查看 kkFileView.log 日志,打印【kkFileView 服务启动完成,耗时:26.8350973s,演示页请访问: http://127.0.0.1:8012 】则说明启动成功。 3.2.2 Linux上安装(centos为例) 第一步:root用户下将 kkFileView-4.0.0.tar.gz 上传到服务器 ,使用命令 tar -zxvf kkFileView-4.0.0.tar.gz 解压,开放 8012 端口。 第二步:root用户下解压后进入 kkFileView-4.0.0/bin 目录,执行 ./startup.sh 开始安装和启动,安装过程中会下载需要的组件需要输入y 第三步:安装字体。若不安装字体转化出的pdf文件可能会因为缺少字体乱码。字体下载(链接:http://kkfileview.keking.cn/fonts.zip)或者 百度云下载(链接:https://pan.baidu.com/s/1TESdE8Xi02NqtnnKlp0BvQ 提取码:lfw5 ) 将下载的字体fonts.zip上传到 /usr/share/fonts 目录解压后执行命令 mkfontscale 若 mkfontscale 提示没有命令则先 yum install mkfontscale 安装命令 再分别依次执行 mkfontscale、mkfontdir、fc-cache 命令。 第四步: 安装完成后 kkFileView-4.0.0/bin/ 目录下使用命令 ./showlog.sh 查看日志 如果出现: 【kkFileView 服务启动完成,耗时:5.99157928s,演示页请访问: http://127.0.0.1:8012 】,则表示安装启动成功。 第五步: 如果日志提示报错信息【找不到office组件,请确认’office.home’配置是否有误 】,则需要下载LibreOffice组件安装。 LibreOffice下载 (链接:https://downloadarchive.documentfoundation.org/libreoffice/old/7.1.4.2/rpm/x86_64/) 或者 百度云下载(链接:https://pan.baidu.com/s/1aRY66KlzZD9UJSo8Gjf2Fg 提取码:6exh ) 将 LibreOffice_7.1.4.2_Linux_x86-64_rpm.tar.gz 上传服务器,然后解压后进入RPMS目录执行 yum localinstall *.rpm 进行安装。 第六步:如果日志提示报错信息【Caused by: java.lang.IllegalStateException: a process with acceptString ‘socket,host=127.0.0.1,port=2001’ is already running】 (1)用 ps -ef|grep java 命令查询出Java相关运行的进程,然后关闭kkFileView相关的进程, 并查看2001和2002端口的进程并关闭该进程。然后再执行 ./startup.sh 启动并查看日志。 (2)如果是安装在Linux上并且关闭了kkFileView相关的进程以及2001和2002端口,启动日志任 然存在该问题,那么可能是你远程连接服务器的软件导致的这个问题,改用window的cmd, 用ssh连接服务器启动程序尝试。 第七步: 如果日志提示报错信息【Caused by: org.artofsolving.jodconverter.office.OfficeException: could not establish connection】,可参考 centos下启动失败:启动office组件失败,请检查office组件是否可用 3.2.3 通过docker安装 第一步:拉取镜像: docker pull keking/kkfileview 第二步:运行: docker run -dit -p 8012:8012 keking/kkfileview 第三步:进入运行起来的容器中,然后可以进入 /opt/kkFileView-4.1.0-SNAPSHOT/bin 安装目录, 运行命令 ./showlog.sh 查看日志 4 kkFileView的配置修改 4.1 修改启动脚本 测试发现如果 kkfileview 安装在 Windows 上预览 txt 文件会乱码,所以需要修改 kkfileview 的 bin 目录下的 startup.bat 脚本。 在最后一行的 java 后添加 -Dfile.encoding=UTF-8 修改后如下: @echo offset "KKFILEVIEW_BIN_FOLDER=%cd%"cd "%KKFILEVIEW_BIN_FOLDER%"echo Using KKFILEVIEW_BIN_FOLDER %KKFILEVIEW_BIN_FOLDER%echo Starting kkFileView...echo Please check log file in ../log/kkFileView.log for more informationecho You can get help in our official homesite: https://kkFileView.keking.cnecho If this project is helpful to you, please star it on cid:link_0/stargazersjava -Dfile.encoding=UTF-8 -Dspring.config.location=..\config\application.properties -jar kkFileView-4.0.0.jar -> ..\log\kkFileView.log4.2 关闭演示页面 kkFileView安装启动成功后可以打开 http://安装的ip:8012 (或者本机 http://127.0.0.1:8012) 查看演示页面上传文件以及查看预览效果。 如果项目上线后为了安全要关闭演示页面,可以在修改kkFileView安装目录的config文件夹中的 application.properties配置文件,将file.upload.disable设置为false禁用演示首页文件上传。 其他配置可根据 官网配置说明 进行配置。 5 kkFileView的使用 只需要创建一个html文件,再加上如下代码: <html> <head> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/js-base64@3.6.0/base64.min.js"></script> </head> <script> var url = 'https://public.fuyingy.com/79e5c202204201011493290.jpg'; //图片随便写了一个 window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(url))); </script></html>转载自https://blog.csdn.net/qq_37284798/article/details/129377354?spm=1001.2014.3001.5502
-
一、箭头函数的介绍 1.1 什么是箭头函数 ES6中允许使用=>来定义函数。箭头函数相当于匿名函数,并简化了函数定义。 1.2 基本语法 // 箭头函数 let fn = (name) => { // 函数体 return `Hello ${name} !`; }; // 等同于 let fn = function (name) { // 函数体 return `Hello ${name} !`; }; 箭头函数在语法上比普通函数简洁多。箭头函数就是采用箭头=>来定义函数,省去关键字function。 函数的参数放在=>前面的括号中,函数体跟在=>后的花括号中 1.3 箭头函数的参数 ①如果箭头函数没有参数,写空括号 //没有参数,写空括号 let fn = () => { console.log('hello'); }; ②如果箭头函数有一个参数,也可以省去包裹参数的括号 //只有一个参数,可以省去参数括号 let fn = name => { console.log(`hello ${name}!`) }; ③如果箭头函数有多个参数,将参数依次用逗号(,)分隔,包裹在括号中。 let fn = (val1, val2, val3, val4) => { return [val1, val2, val3, val4]; } 1.4 箭头函数的函数体 ①如果箭头函数的函数体只有一句执行代码,简单返回某个变量或者返回一个简单的js表达式,可以省去函数体花括号{ } //返回某个简单变量val let f = val => val; // 等同于 let f = function (val) { return val }; //返回一个简单的js表达式num1+num2 let sum = (num1, num2) => num1 + num2; // 等同于 let sum = function(num1, num2) { return num1 + num2; }; ②如果箭头函数的函数体只有一句代码,返回的不是变量和简单的js表达式,而是一个对象。 //错误写法—花括号会被解释为函数体 let getItem = id => { id: id, name: 'gaby' }; //正确写法 let getItem = id => ({ id: id, name: 'gaby' }); ③如果箭头函数的函数体只有一条语句且不需要返回值(最常用于回调函数),加上void关键字 let fn = () => void doesNotReturn(); 1 箭头函数用于回调函数,常见简洁 //栗子1 //普通函数 [1, 2, 3].map(function (x) { return x + x; }); //ES6箭头函数 [1, 2, 3].map(x => x + x); //栗子2 //普通函数 var result = [2, 4, 5, 1, 6].sort(function (a, b) { return a - b; }); //ES6箭头函数 var result = [2, 4, 5, 1, 6].sort((a, b) => a - b); 二、箭头函数的this指向规则 2.1 箭头函数没有原型prototype,因此箭头函数没有this指向 let fn = () => { console.log('Hello World !') }; console.log(fn.prototype); // undefined 2.2 箭头函数不会创建自己的this,如果存在外层第一个普通函数,在定义的时候会继承它的this 箭头函数没有自己的this指向,它会捕获自己定义所处的外层执行环境,并且继承这个this值。箭头函数的this指向在被定义的时候就确定了,之后永远都不会改变。(!永远) (1)栗子1 var id = 'Global'; //普通函数 function fn1() { setTimeout(function () { console.log(this.id) }, 1000); } //箭头函数 function fn2() { setTimeout(() => { console.log(this.id) }, 1000); } fn1.call({ id: 'obj' });//Global fn2.call({ id: 'obj' });//obj 解析:普通函数的setTimeout 一秒后执行是在全局作用域,所有this指向window对象,this.id指向了全局变量id,输出Golbal。箭头函数的this在定义的时候就确定了,继承fn2的执行环境中的this,fn2的this指向被call方法改变绑定到obj这个对象 (2)栗子2 var id = 'Global'; var obj = { id: 'OBJ', a: function () { console.log(this.id) },//方法a普通函数定义 b: () => { console.log(this.id) }//方法b用箭头函数定义 }; obj.a();//OBJ obj.b();//Global 解析:普通函数作为对象的方法调用,this指向所属的对象(谁调用它就指向谁),this.id 就是obj.id;箭头函数继承定义它的执行环境的this,指向window对象,指向全局变量,输出Global。花括号{}无法形成一个单独的执行环境,所有它依然在全局中。 2.3 箭头函数的this是继承而来的永远不会变,call/apply/bind也无法改变 .call()/.apply()/.bind()方法可以用来动态修改函数执行时this的指向,但由于箭头函数的this定义时就已经确定且永远不会改变 var name = 'gaby' var person = { name: 'gabrielle', say: function () { console.log('say hello', this.name) }, //普通函数 say2: () => { console.log('say2 hello', this.name) } //箭头函数 } person.say.call({ name: 'Mike' }) person.say2.call({ name: 'Amy' }) 解析:say的普通函数通过call调用已经改变this指向。say2箭头函数调用call绑定尝试改变this指向,但是仍然打印出外一层普通函数的this指向,window对象的全局变量name。 2.4 箭头函数this指向只能间接修改 间接修改:修改被继承的普通函数的this指向,箭头函数的this指向也会跟着改变。 箭头函数的this指向定义时所在的外层第一个普通函数,跟使用的位置没有关系。 let al let aObj = { msg: 'a的this指向' }; bObj = { msg: 'b的this指向' }; a.call(aObj); //将a的this指向aObj b.call(bObj); //将b普通函数的this指向bObj 箭头函数内部的this指向也会指向bObj function b() { al(); } function a() { al = () => { console.log(this, 'this指向定义时外层第一个普通函数 ') }; } 2.5 箭头函数外层没有函数,严格模式和非严格模式下它的this都会指向window全局对象 箭头函数的this指向继承自外层第一个普通函数的this,那么如果没有外层函数,它的this指向哪里? this的绑定规则:非严格模式下,默认绑定的this指向全局对象,严格模式下this指向undefined。 如果箭头函数外层没有普通函数继承,箭头函数在全局作用域下,严格模式和非严格模式下它的this都会指向window(全局对象) 2.6 多层嵌套函数this指向 箭头函数中的this引用的是最近作用域中的this,是向外层作用域中,一层层查找this,直到有this的定义。 2.7 箭头函数不能作为构造函数使用new 构造函数做了什么? ①JS内部首先会先生成一个对象 ②再把函数中的this指向该对象 ③然后执行构造函数中的语句 ④最终返回该对象实例 箭头函数没有自己的this,this继承外层执行环境中的this,且this永远不会改变。new会报错 let fn = (name, age) => { this.name = name; this.age = age; }; let person = new fn('gaby', 20) 2.8 箭头函数不支持new.target ES6新引入的属性,普通函数可以通过new调用,new.target返回该函数的引用。用于确定构造函数是否为new调用。箭头函数并不能作为构造函数使用new,自然也不支持new.targer。 (1)箭头函数的this指向全局对象,在箭头函数中使用箭头函数会报错 let fn = () => { console.log(new.target) }; fn() (2)箭头函数的this指向普通函数,它的new.target就是指向该普通函数的引用 new fn2(); function fn2() { let fn = () => { console.log(new.target) }; fn(); } 三、箭头函数的arguments规则 3.1 箭头函数没有自己的arguments (1)箭头函数处于全局作用域中 箭头函数的this指向全局对象,会报arguments未声明的错。 let fn = name => { console.log(arguments) } let fn2 = function (name) { console.log(arguments) } //fn() fn2() let fn = name => { console.log(arguments) } let fn2 = function (name) { console.log(arguments) } fn() fn2() 解析:普通函数可以打印arguments,箭头函数报错。因为箭头函数处于全局作用域中,在全局作用域没有arguments的定义,箭头函数本身没有arguments,所以报错。 (2)箭头函数的this如果指向普通函数,它的argumens继承于该普通函数 let fn2 = function (name) { console.log('fn2:', arguments) let fn = name => { console.log('fn:', arguments) } fn() } fn2('gaby') 解析:两个函数打印的argument相同,都是fn2函数的arguments。 总结 箭头函数没有自己的arguments对象。在箭头函数中访问arguments实际上获得的是外层局部(函数)执行环境中的值。 3.2 可以用rest替代,rest参数获取函数的多余参数 rest是ES6的API,用于获取函数不定数量的参数数组。这个API可以用来替代arguments。 (1)基本用法 //形式是...变量名 let fn = (first, ...arr) => { console.log(first, arr); } fn(1, 2, 3, 4); 解析:rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。获取函数的第一个确定的参数,以及用一个变量接收其他剩余函数的实例。 (2)使用注意事项 ①rest必须是函数的最后一位参数 let a = (first, ...rest, three) => { console.log(first, rest, three); }; a(1, 2, 3, 4); ②函数的length属性不包括rest (3)rest和arguments函数比较 ①箭头函数和普通函数都可以使用rest参数,而arguments只能普通函数用。 ②接收参数rest比arguments更加灵活,完全可以自定义。 ③rest是一个真正的数组可以使用数组API,arguments只是一个类数组。 3.3 箭头函数不支持重复函数参数的名称 function fn(name, name) { console.log('fn2:', name) } let fn2 = (name, name) => { console.log('fn:', name) } fn('wang', 'gaby') fn2('wang', 'gaby') 3.4 箭头函数不能用作Generator,不能使用yeild关键字 四、箭头函数的注意事项 ①函数箭头一条语句返回对象字面量,需要加括号。 ②箭头函数在参数和箭头之间不能换行 ③箭头函数的解析顺序相对||靠前 五、箭头函数不适用场景 (1)对象方法,且方法使用了this 对象无法构造单独的作用域 var name = 'gaby' var person = { name: 'gabrielle', say: function () { console.log('say hello', this.name) }, //普通函数 say2: () => { console.log('say2 hello', this.name) } //箭头函数 } person.say() person.say2() 解析:person.say2()方法是一个箭头函数,调用person.say2()的时候this指向全局对象,达不到预期。对象无法构成单独的作用域,定义say2()箭头函数的时候作用域在全局作用域。 (2)回调函数的动态this var button = document.querySelector('.btn'); button.addEventListener('click', () => { this.classList.toggle('on'); }); 解析:报错。按钮点击是一个回调函数,而箭头函数内部的this指向外一层普通函数的this,在这里就是window,所以报错。改成普通函数就不会报错 六、箭头函数与普通函数简单区别总结 (1)箭头函数语法更简洁清晰,快捷。 (2)箭头函数没有原型prototype,并不会自己创建this,并且this不能被修改,call等都不能修改到。只能间接修改被继承的this (3)箭头函数的this在定义时就定了,继承外一层的普通函数 (4)如果箭头函数外一层再外一层都不能找到普通函数,在严格和非严格情况下都会指向window对象 (5)箭头函数的this指向全局,使用arguments会报未声明的错误 (6)箭头函数的this指向外一层的普通函数,使用argument继承该普通函数 (7)箭头函数不能构造函数,不能new.target,不能new,没有constructor (8)箭头函数不支持重复命名参数,普通函数可以重复命名参数 ———————————————— 版权声明:本文为CSDN博主「傲娇味的草莓」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_45709829/article/details/123931582
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签