前端知识二

前端知识二

html,js,css前端三大件

不管你是使用市面上的热门的框架还是公司自己开发的框架,都离不开这个要素,在深入学习框架源码前,这是都是需要熟能上手,再去阅读框架源码!框架的作用是工程化,快速开发,将dom,js,css编译成码流!借助浏览器的哈希和history等来完成页面的跳转,原生传统的是搭建.html页面,现在还在使用的多为某些公司的线上商城,利于seo优化排名,随着vue,react慢慢发展也开始出现便于seo优化的方法!没有过多深入研究不在赘述。

前端的改变

互联网快速发展的时代,逐渐出现各种框架,将前后端直接分离,各司其职,框架的出现将后端使用的单页面直接搬到前端,经过框架的编译压缩,变成一个个js文件,所需要的页面全以代码的形式封存在js文件中,这也就是你看到的.html页面只有一个的原因

三大件之一的html

发展历史
html发展历史1980年,物理学家蒂姆·伯纳斯-李在欧洲核子研究中心(CERN)在承包工程期间,为使CERN的研究人员使用并共享文档,他提出并创建原型系统ENQUIRE。1989年,伯纳斯-李在一份备忘录中提出一个基于互联网的超文本系统。他规定HTML并在1990年底写出浏览器和服务器软件。同年,伯纳斯-李与CERN的数据系统工程师罗伯特·卡里奥联合为项目申请资助,但未被CERN正式批准。在他的个人笔记中伯纳斯-李列举“一些使用超文本的领域”,并把百科全书列为首位。
HTML的首个公开描述出现于一个名为“HTML标签”的文件中,由蒂姆·伯纳斯-李于1991年底提及。它描述18个元素,包括HTML初始的、相对简单的设计。除了超链接标签外,其他设计都深受CERN内部一个以标准通用标记语言(SGML)为基础的文件格式SGMLguid的影响。这些元素在HTML 4中仍有11个存在。
伯纳斯-李认为HTML是SGML的一个应用程序。1993年中期互联网工程任务组(IETF)发布首个HTML规范的提案:“超文本标记语言(HTML)”互联网草案,由伯纳斯-李与丹·康纳利撰写。其中包括一个SGML文档类型定义来定义语法[11]。草案于6个月后过期,不过值得注意的是其对NCSA Mosaic浏览器自定义标签从而将在线图像嵌入的行为的认可,这反映IETF把标准立足于成功原型的理念。同样,戴夫·拉格特在1993年末提出的与之竞争的互联网草案“HTML+(超文本标记格式)”建议规范已经实现的功能,如表格与填写表单。
在HTML和HTML+的草案于1994年初到期后,IETF创建一个HTML工作组,并在1995年完成”HTML 2.0”,这是第一个旨在成为对其后续实现标准的依据的HTML规范。
在IETF的主持下,HTML标准的进一步发展因竞争利益而遭受停滞。自1996年起,HTML规范一直由万维网联盟(W3C)维护,并由商业软件厂商出资。不过在2000年,HTML也成为国际标准(ISO/ IEC15445:2000)。HTML 4.01于1999年末发布,进一步的勘误版本于2001年发布。2004年,网页超文本应用技术工作小组(WHATWG)开始开发HTML5,并在2008年与W3C共同交付,2014年10月28日完成标准化。
二、版本时间线
1995年11月24日
HTML 2.0作为IETF RFC 1866发布。追加RFC的附加功能:
1995年11月25日:RFC 1867(基于表单的文件上传)
1996年5月:RFC 1942(表格)
1996年8月:RFC 1980(客户端图像映射)
1997年1月:RFC 2070(国际化)
1997年1月14日
HTML 3.2 作为W3C推荐标准发布。
这是首个完全由W3C开发并标准化的版本,因IETF于1996年9月12日关闭它的HTML工作组。
最初代号为“威尔伯”(Wilbur),HTML 3.2 完全去除数学公式,协调各种专有扩展,并采用网景设计的大多数视觉标记标签。由于两家公司达成了协议,网景的闪烁元素和微软的滚动元素被移除。HTML对数学公式的支持最后成为另外一种被称为MathML的标准。
1997年12月18日
HTML 4.0作为W3C推荐标准发布。它提供三种变化:
严格,过时的元素被禁止。
过渡,过时的元素被允许。
框架集,大多只与框架相关的元素被允许。
最初代号“美洲狮”(Cougar), HTML 4.0采用许多特定浏览器的元素类型和属性,并试图淘汰网景的视觉标记功能,将其标记为不赞成使用。HTML 4是遵循ISO 8879 - SGML的SGML应用程序。
1998年4月24日
HTML 4.0进行微调,不增加版本号。
1999年12月24日
HTML 4.01作为W3C推荐标准发布。它同样提供三种变化,最终勘误版于2001年5月12日发布。
2000年5月
ISO/IEC 15445:2000(”ISO HTML”,基于HTML 4.01严格版)作为ISO/IEC国际标准发布。在ISO中这一标准位于ISO/IEC JTC 1/SC 34域(ISO/IEC联合技术委员会1、小组委员会34 – 文档描述与处理语言)。
2014年10月28日
HTML 5作为W3C推荐标准发布。
三、草案时间线
1991年10月
HTML标签,一个非正式CERN文件首次公开18个HTML标签。
1992年6月
HTML DTD的首个非正式草案, 后续有七个修订版(7月15日,8月6日,8月18日,11月17日,11月19日,11月20日,11月22日)。
1992年11月
HTML DTD 1.1(首个版本号,基于RCS修订版,版本号从1.1开始而非1.0),非正式草案。
1993年6月
超文本标记语言由IETF IIIR工作小组作为互联网草案(一个粗略的建议标准)。在被第二版取代一个月后,IETF又发布6个草案,最终在RFC1866中发布HTML 2.0。
1993年11月
HTML+由IETF作为互联网草案发布,是超文本标记语言草案的一个竞争性提案。它于1994年5月到期。
1995年4月 (1995年3月编写)
HTML 3.0被提议作为IETF的标准,但直到提案在五个月过期后(1995年9月28日)仍没有进一步的行动。它包含许多拉格特HTML+提案的功能,如对表格的支持、围绕数据的文本流和复杂的数学公式的显示。W3C开始开发自己的Arena浏览器作为HTML 3和层叠样式表的试验台[,但HTML 3.0并没有获得成功。浏览器厂商,包括微软和网景,选择实现HTML3草案功能的不同子集并引入它们自己的插件(见浏览器大战)。
2008年1月
HTML5由W3C作为工作草案(链接)发布。虽然HTML5的语法非常类似于SGML,但它已经放弃任何成为SGML应用程序的尝试,除了一种替代的基于XML的HTML5序列,它已明确定义自己的“HTML”序列。
2011年 HTML5 – 最终征求
2011年5月,工作小组将HTML5推进至“最终征求”(Last Call)阶段,邀请W3C社区内外人士以确认本规范的技术可靠性。W3C开发一套综合性测试包来实现完整规范的广泛交互操作性,完整规范的目标日期为2014年。2011年1月,WHATWG将其“HTML5”活动标准重命名为“HTML”。W3C仍然继续其发布HTML5的项目。
2012年 HTML5 – 候选推荐
2012年7月,WHATWG和W3C的工作产生一定程度的分离。W3C继续HTML5规范工作,重点放在单一明确的标准上,这被WHATWG称为“快照”。WHATWG组织则将HTML5作为一个“活动标准”(Living Standard)。活动标准的概念是从未完成但永远保持更新与改进,可以蒂姆加新特性,但功能点不会被删除。
2012年12月,W3C指定HTML5作为候选推荐阶段。 该阶段的标准为“两个100%完成,完全实现交互操作”。
2014年 HTML5 – 提案推荐与推荐
2014年9月,HTML5进入提案推荐阶段。
2014年10月28日,HTML5作为稳定W3C推荐标准发布,这意味着HTML5的标准化已经完成。
四、XHTML版本
XHTML是使用XML 1.0改写自HTML 4.01的独立语言。它不再被作为单独标准开发。
XHTML 1.0, 2000年1月26日作为W3C推荐标准发布。修订版于2002年8月1日发布,它提供与HTML 4.0和4.01相同的三个变化,这些变化被重新在XML中制定。
XHTML 1.1,基于XHTML 1.0 严格版,2001年5月31日 作为W3C推荐标准发布。修订版可使用模块化XHTML的模块,2001年4月10日作为W3C推荐标准发布。
XHTML 2.0为工作草案,但为支持HTML5与XHTML5的工作,此草案被放弃。 XHTML 2.0与XHTML 1.x不兼容,因此更确切的说这是一个XHTML风格的新语言而不是XHTML 1.x的更新。
在HTML5草案中规定一个XHTML语法,称为“XHTML5.1”。

html的标签 从头开始解读

为什么要从头开始呢!你在工作中的时候虽然知道这些标签,但是花费时间深入去了解的时间较少!只有慢慢工作的时间长了,才会一点点知道!在此也算是做记录!

HTML 指的是超文本标记语言: HyperText Markup Language
HTML 不是一种编程语言,而是一种标记语言
标记语言是一套标记标签 (markup tag)
HTML文档的后缀名
.html
.htm
以上两种后缀名没有区别,都可以使用。

DOCTYPE html> 

<html lang="zh-cn" style="--olcb-folder-code-block-max-height:80vh;">


<head>

    <meta charset="utf-8">
    
    
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <meta name="referrer" content="origin-when-cross-origin">
    
    <meta name="description" content="元素创建的三种方式 为了提高用户的体验 1. document.write(&quot;标签的代码以及内容&quot;); 页面加载的时候创建,是没有问题的:document.write(&quot;">
    
    <meta property="og:description" content="元素创建的三种方式 为了提高用户的体验 1. document.write(&quot;标签的代码以及内容&quot;); 页面加载的时候创建,是没有问题的:document.write(&quot;">
    
    <meta http-equiv="Cache-Control" content="no-transform">
    
    <meta http-equiv="Cache-Control" content="no-siteapp">
    
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    
    <meta ke="X-UA-Compatible" content="IE=edge">
    
    <meta name="keywords" content="HTML DOM Link 对象">
    <title>页面名称title>
    
    <link id="favicon" rel="shortcut icon"href="//common.cnblogs.com/favicon.svg"type="image/svg+xml">
    
    <title>图片地址(runoob.com)title> 
<base href="http://www.runoob.com/images/" target="_blank">
    <script type="text/javascript" src="https://common.cnblogs.com/script/encoder.js">script>		
    
head>
<body class="skin-codinglife has-navbar">
<iframe src="https://a3e7ca4361cd17e3300b9a64d2d4b6c9.safeframe.googlesyndication.com/safeframe/1-0-38/html/container.html" style="visibility: hidden; display: none;">iframe>


<div>div>
<a href="http://">a>
<a href="http://" target="_blank" rel="noopener noreferrer">a>
<a href="mailto:">a>
<a href="tel:">a>
<a :href="`${完整的下载地址}`" target="downloadFile">{{文件名称}}a>
<a href="#two" name="one">底部a>
<a href="#one" name="two">顶部a>
<a href="javascript:while(1){alert('循环')}">点我,javacsript死循环a>
<br />
<hr />
<code>计算机输出code>
<kbd>键盘输入kbd>
<tt>打字机文本tt>
<samp>计算机代码样本samp>
<var>计算机变量var>
<b>注释:b>这些标签常用于显示计算机/编程代码。
<pre>
此例演示如何使用 pre 标签
对空行和    空格
进行控制
pre>
<strong>这个文本是加粗的strong>
<big>这个文本字体放大big>
<em>这个文本是斜体的(语气的)em>
<i>这个文本是斜体的i>
<small>这个文本是缩小的small>
这个文本包含
<sub>下标sub>
这个文本包含
<sup>上标sup>
<address>
地址标签
Written by <a href="mailto:[email protected]">Jon Doea>.<br> 
Visit us at:<br>
Example.com<br>
Box 564, Disneyland<br>
USA
address>

<abbr title="etcetera">etc.abbr>

<acronym title="World Wide Web">WWWacronym>
<bdo dir="rtl">该段落文字从右到左显示。bdo>
<p>块引用: 
<q>Build a future where people live in harmony with nature.q>
We hope they succeed.p>
<p>此例演示如何标记删除文本和插入文本。(css也可以实现) <del>bluedel> <ins>redins>!p>
 body>
html>

新增元素 说明
viode 表示一段视频并提供播放的用户界面
audio 表示音频
canvas 表示位图区域
source 为video和audio提供数据源
track 为video和audio指定字母
svg 定义矢量图
code 代码段
figure 和文档有关的图例
figcapton 图例的说明
main main标签规定文档的主要内容,main的主要目的是将ARIA的地标性作用main映射到HTML中的元素,这可以帮助那些屏幕阅读
time 日期和时间值
mark 高亮的引用文字
datalist 提供给其他控件的预定义选项
keygen 秘钥对生成器控件
output 计算值
progress 进度条
menuitem 用户可点击的菜单项
menu 菜单
template 元素模板
section 选中的文本样式
nav 标签定义导航链接的部分
aside aside元素用来定义当前页面或者文章的附属信息部分,它可以包含与当前页面或主要内容相关的引用、侧边栏、广告、导航条等其他类似的有别于主要内容的部分。
article 标签定义的内容本身必须是有意义的且必须是独立于文档的其余部分。
footer 底部标签
progress 标签用于定义文档中的进度条
header 头部标签

lang语言代码想了解更多点击:语言代码
unicode编码也叫字符集:UTF-8、UTF-7、UTF-16、UnicodeLittle、UnicodeBig
ogp.me(官网):地址

css:

css是层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。css是建立网站不可缺少的样式。
96年左右的时候css还不成熟,标签上经常width和height的标签属性,有些完成不了的就直接使用标签代替,并且没有语义化,使用操作频繁,更改个颜色和大小都使用到这个标签,整合html是无处不在,直到后来w3c万维网联盟用css的font-size和color代替这标签,页面标签量骤然缩减,逐步的更新替代旧的css。

c3新增前端知识二_第1张图片

样式类
1.圆角 radius(border-radius:50%)
2.三角型(不给盒子宽高,左右给边框,颜色为透明,上边框给颜色即可)

3.阴影 box-shadow(box-shadow: X轴偏移量 Y轴偏移量 [阴影模糊半径] [阴影扩展半径] [阴影颜色] [投影方式(inset或省略)];)

4.背景色透明度 background:rgba(165,42,42,.5)【提示:opacity属性透明度会传递给后代元素,而rgba的后代元素不会继承透明】

5.渐变色彩 background: linear-gradient(to bottom, red, yellow);

6.文本阴影 text-shadow: X轴偏移量 Y轴偏移量 模糊半径 阴影颜色(text-shadow: 2px 2px 0 #E4F1FF;)

7.溢出文本用text-overflow,用(…)省略标记。(text-overflow:ellipsis;要有超出区域不显示,overflow:hidden)

8.border-image使用图片来创建边框
9.background-size指定背景图片尺寸与
background-size: contain; 缩小图片以适合元素(维持像素长宽比)

background-size: cover; 扩展元素以填补元素(维持像素长宽比)

background-size: 100px 100px; 缩小图片至指定的大小

background-size: 50% 100%; 缩小图片至指定的大小,百分比是相对包 含元素的尺寸

10.background-origin:指定背景图片从哪里开始显示,背景图片可以放置于 content-box、padding-box 或 border-box 区域
background-origin: border-box; 从border开始计算background-position

background-origin: padding-box; 从padding开始计算background-position

background-origin: content-box; 从content开始计算background-position

11.background-clip:指定背景图片从什么位置开始裁剪
12.word-wrap:文字自动换行
13.text-overflow: ellipsis;文字在固定区域内显示不完整加省略号需要配合overflow: hidden;使用,多用于文本描述显示区域有限,配合title使用,也可使用第三方的插件来实现鼠标移入显示完整信息的效果!
鼠标移入效果图
clip:修剪文本

ellipsis:显示省略符号来代表被修剪的文本
14.background-break
元素可以被分成几个独立的盒子(如使内联元素span跨越多行),background-break 属性用来控制背景怎样在这些不同的盒子中显示

background-break: continuous; 默认值。忽略盒之间的距离(也就是像元素没有分成多个盒子,依然是一个整体一样)

background-break: bounding-box; 把盒之间的距离计算在内;

background-break: each-box; 为每个盒子单独重绘背景

15.text-decoration
CSS3里面开始支持对文字的更深层次的渲染,具体有三个属性可供设置:

text-fill-color: 设置文字内部填充颜色

text-stroke-color: 设置文字边界填充颜色

text-stroke-width: 设置文字边界宽度

16.颜色
css3新增了新的颜色表示方式rgba与hsla

rgba分为两部分,rgb为颜色值,a为透明度

hala分为四部分,h为色相,s为饱和度,l为亮度,a为透明度

css3新增动画效果

1、transform变换效果:

css3提供了元素变形效果,也叫做变换。它可以将元素实现旋转、缩放和平移的功能。

属性值:(1)transform ;(2)transform-origin:transform-origin 属性可以设置变换的起点。默认情况下,使用元素的中心作为起点。
transform: translate(120px, 50%):位移

transform: scale(2, 0.5):缩放

transform: rotate(0.5turn):旋转

transform: skew(30deg, 20deg):倾斜

2、animation动画效果

CSS3 提供了类似 Flash 关键帧控制的动画效果,通过 animation 属性实现。那么之前的 transition 属性只能通过指定属性的初始状态和结束状态来实现动画效果,有一定的局限性。

animation 实现动画效果主要由两个部分组成:1、通过类似 Flash 动画中的关键帧声明一个动画;2、在 animation 属性中调用关键帧声明的动画。

css3新增过渡效果

1、transition过渡效果

过渡效果一般是通过一些简单的 CSS 动作触发平滑过渡功能,比如::hover、:focus、:active、:checked 等。CSS3 提供了 transition 属性来实现这个过渡功能。

对于css3新增的过渡内容和css新增动画效果大家也可以参考CSS3 最新版参考手册。

animation 动画

动画这个平常用的也很多,主要是做一个预设的动画。和一些页面交互的动画效果,结果和过渡应该一样,让页面不会那么生硬

animation也有很多的属性

animation-name:动画名称

animation-duration:动画持续时间

animation-timing-function:动画时间函数

animation-delay:动画延迟时间

animation-iteration-count:动画执行次数,可以设置为一个整数,也可以设置为infinite,意思是无限循环

animation-direction:动画执行方向

animation-paly-state:动画播放状态

animation-fill-mode:动画填充模式

布局

一.flex弹性布局
前端知识二_第2张图片

1、flex-direction用来控制子项整体布局方向,是从左往右还是从右往左,是从上往下还是从下往上
row

默认值,显示为行。方向为当前文档水平流方向,默认情况下是从左往右。

row-reverse

显示为行。但方向和row属性值是反的

column

显示为列

column-reverse

显示为列。但方向和column属性值是反的
2、flex-wrap用来控制子项整体单行显示还是换行显示。
nowrap

默认值,表示单行显示,不换行。

wrap

宽度不足换行显示

wrap-reverse

宽度不足换行显示,但是是从下往上开始,也就是原本换行在下面的子项现在跑到上面。
flex-flow属性是flex-direction和flex-wrap的缩写,表示flex布局的flow流动特性。第一个值表示方向,第二个值表示换行,中间用空格隔开。
3、justify-content属性决定了主轴方向上子项的对齐和分布方式。 常用
flex-start

默认值,表现为起始位置对齐。

flex-end

表现为结束位置对齐。

center

表现为居中对齐。

space-between

表现为两端对齐。between是中间的意思,意思是多余的空白间距只在元素中间区域分配。

space-around

around是环绕的意思,意思是每个flex子项两侧都环绕互不干扰的等宽的空白间距,最终视觉上边缘两侧的空白只有中间空白宽度一半。

space-evenly

evenly是匀称、平等的意思。也就是视觉上,每个flex子项两侧空白间距完全相等。

4、align-items中的items指的就是flex子项们,因此align-items指的就是flex子项们相对于flex容器在侧轴方向上的对齐方式。
stretch

默认值,flex子项拉伸。

flex-start

表现为容器顶部对齐。

flex-end

表现为容器底部对齐。

center

表现为垂直居中对齐。
5、align-content可以看成和justify-content是相似且对立的属性,如果所有flex子项只有一行,则align-content属性是没有任何效果的。
stretch

默认值。每一行flex子元素都等比例拉伸。例如,如果共两行flex子元素,则每一行拉伸高度是50%。

flex-start

表现为起始位置对齐。

flex-end

表现为结束位置对齐。

center

表现为居中对齐。

space-between

表现为两端对齐。

space-around

每一行元素上下都享有独立不重叠的空白空间。

space-evenly

每一行元素都完全上下等分。

作用在flex子项上的CSS属性

1、order

可以通过设置order改变某一个flex子项的排序位置。所有flex子项的默认order属性值是0。

2、flex-grow

属性中的grow是扩展的意思,扩展的就是flex子项所占据的宽度,扩展所侵占的空间就是除去元素外的剩余的空白间隙。默认值为0。

3、flex-shrink

属性中的shrink是“收缩”的意思,flex-shrink主要处理当flex容器空间不足时候,单个元素的收缩比例。默认值是1。

4、flex-basis

flex-basis定义了在分配剩余空间之前元素的默认大小。

5、flex

flex属性是flex-grow,flex-shrink和flex-basis的缩写。

6、align-self

align-self指控制单独某一个flex子项的垂直对齐方式。

二.Grid栅格布局
Grid布局是一个二维的布局方法,纵横两个方向同时存在。
前端知识二_第3张图片
我有点懒的写就直接放格栅的连接吧!写的不错

CSS3新增选择器

  1. 关系选择器

    兄弟选择器:选择该元素后面的同级的兄弟元素
    例如:

    h1~p:选择h1元素后面的所有同级p元素。

    p~p:选择p元素后面的所有同级p元素,除了第一个p元素

  2. 属性选择器
    E[att] 选择具有att属性的E元素
    E[att="val’'] 选择具有att属性且属性值等于val的E元素
    E[att^=“val”] 匹配具有att属性且值以val开头的E元素
    E[att$=“val”] 匹配具有att属性且值以val结尾的E元素
    E[att*=“val”] 匹配具有att属性且值中含有val的E元素
    3.伪类选择器
    E:first-child 匹配父元素中的第一个子元素E
    E:last-child 匹配父元素中的最后一个E元素
    E:nth-child(n) 匹配父元素中的第n个子元素E 仅支持正整数
    E:first-of-type 指定类型E的第一个
    E:last-of-type 指定类型E的最后一个
    E:nth-of-type(n) 指定类型E的第n个 仅支持正整数
    E:nth-last-child(n) 从父元素的最后一个子元素开始算
    E:nth-last-of-child(n) 指定类型E的第n个,但是是从父元素的最后一个子元素开始算
    :root 根选择器,匹配E元素所在文档的根元素,在HTML文档中,根元素始终是
    :not 否定选择器,选择除某个元素之外的所有元素
    :empty 用来选择没有任何内容的元素
    :target 目标选择器,用来匹配文档(页面)url的某个标志符的目标元素,鼠标点击后变化
    :only-child 父元素中只有一个子元素,且只有唯一的一个子元素
    :only-of-type 选择的是一个元素是它的父元素的唯一一个相同类型的子元素
    :enabled 表单元素状态可用
    :disabled 表单元素状态不可用。使用时需要在表单元素的HTML中设置“disabled”属性
    :checked 选中状态,选中后样式改变
    :read-only 用于指定处于只读状态的元素的样式,元素中需要设置readonly=“readonly”
    :read-write 用于指定当元素处于非只读状态的样式
    4.伪元素选择器
    ::selection 用来匹配突出显示的文本(用鼠标选择文本时的文本)
    ::before 在元素内部的前面插入内容
    ::after 在元素内部的后面插入内容
    ::placeholder 改变表单元素中的文字的样式

JavaScript 是属于 HTML 和 Web 的编程语言

js经过漫长的发展,已经不单单局限于前端,开始向后端延伸
Node.js发布于2009年5月,由Ryan Dahl开发,是一个基于Chrome V8引擎的JavaScript运行环境,使用了一个事件驱动、非阻塞式I/O模型,让JavaScript 运行在服务端的开发平台,它让JavaScript成为与PHP、Python、Perl、Ruby等服务端语言平起平坐的脚本语言。
扩展:随着前端的快速发展,js开始向着各个领域进发,混合式应用开发(物联网),游戏端(前几年比较火的网页网游),桌面级应用(vscode),bim模型,服务器搭建,移动端(小程序,web app,安卓apk,小游戏 例如:赚钱赚爆了的游戏 羊了个羊),插件开发,pc端,多媒体端(电梯广告屛),公司业务方向不同,你所用的js偏向性不同。技术深度也不可能同日而语!

一、dom(html文档节点)

当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)
JavaScript 能改变页面中的所有 HTML 元素
JavaScript 能改变页面中的所有 HTML 属性
JavaScript 能改变页面中的所有 CSS 样式
JavaScript 能删除已有的 HTML 元素和属性
JavaScript 能添加新的 HTML 元素和属性
JavaScript 能对页面中所有已有的 HTML 事件作出反应
JavaScript 能在页面中创建新的 HTML 事件
通俗一点讲就是dom就是让js增删改查dom元素

二、浏览器对象模型(Browser Object Model (BOM))

不存在浏览器对象模型(BOM)的官方标准。

现代的浏览器已经(几乎)实现了 JavaScript 交互相同的方法和属性,因此它经常作为 BOM 的方法和属性被提到。

注:简单的不在赘述,讲述一些用的极少功能
Navigator
Navigator 接口表示用户代理的状态和标识。它允许脚本查询它和注册自己进行一些活动。
1、navigator.userAgent获取当前设备浏览器信息
获取设备系统和型号

DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <title> 获取设备信息 《封装》title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no">
    <meta name="Generator" content="EditPlus">
    <meta name="Author" content="">
    <meta name="Keywords" content="">
    <meta charset="utf-8" />
    <meta name="Description" content="">



head>

<body>



    
    <script src="./js/mobile-detect.min.js">script>
    <script>

        var GetDevice = function () {

            /* 版本信息获取 */
            // 各主流浏览器
            var getBrowser = function () {
                var u = navigator.userAgent
                var bws = [{
                    name: 'sgssapp',
                    it: /sogousearch/i.test(u)
                }, {
                    name: 'wechat',
                    it: /MicroMessenger/i.test(u)
                }, {
                    name: 'weibo',
                    it: !!u.match(/Weibo/i)
                }, {
                    name: 'uc',
                    it: !!u.match(/UCBrowser/i) || u.indexOf(' UBrowser') > -1
                }, {
                    name: 'sogou',
                    it: u.indexOf('MetaSr') > -1 || u.indexOf('Sogou') > -1
                }, {
                    name: 'xiaomi',
                    it: u.indexOf('MiuiBrowser') > -1
                }, {
                    name: 'baidu',
                    it: u.indexOf('Baidu') > -1 || u.indexOf('BIDUBrowser') > -1
                }, {
                    name: '360',
                    it: u.indexOf('360EE') > -1 || u.indexOf('360SE') > -1
                }, {
                    name: '2345',
                    it: u.indexOf('2345Explorer') > -1
                }, {
                    name: 'edge',
                    it: u.indexOf('Edge') > -1
                }, {
                    name: 'ie11',
                    it: u.indexOf('Trident') > -1 && u.indexOf('rv:11.0') > -1
                }, {
                    name: 'ie',
                    it: u.indexOf('compatible') > -1 && u.indexOf('MSIE') > -1
                }, {
                    name: 'firefox',
                    it: u.indexOf('Firefox') > -1
                }, {
                    name: 'safari',
                    it: u.indexOf('Safari') > -1 && u.indexOf('Chrome') === -1
                }, {
                    name: 'qqbrowser',
                    it: u.indexOf('MQQBrowser') > -1 && u.indexOf(' QQ') === -1
                }, {
                    name: 'qq',
                    it: u.indexOf('QQ') > -1
                }, {
                    name: 'chrome',
                    it: u.indexOf('Chrome') > -1 || u.indexOf('CriOS') > -1
                }, {
                    name: 'opera',
                    it: u.indexOf('Opera') > -1 || u.indexOf('OPR') > -1
                }]
                for (var i = 0; i < bws.length; i++) {
                    if (bws[i].it) {
                        return bws[i].name
                    }
                }

                return 'other'
            };
            // 系统区分
            var getOS = function () {
                var u = navigator.userAgent
                if (!!u.match(/compatible/i) || u.match(/Windows/i)) {
                    return 'windows'
                } else if (!!u.match(/Macintosh/i) || u.match(/MacIntel/i)) {
                    return 'macOS'
                } else if (!!u.match(/iphone/i) || u.match(/Ipad/i)) {
                    return 'ios'
                } else if (u.match(/android/i)) {
                    return 'android'
                } else if (u.match(/Ubuntu/i)) {
                    return 'Ubuntu'
                } else {
                    return 'other'
                }
            };
            //判断数组中是否包含某字符串
            Array.prototype.contains = function (needle) {
                for (i in this) {
                    if (this[i].indexOf(needle) > 0)
                        return i;
                }
                return -1;
            }

            var device_type = navigator.userAgent; //获取userAgent信息
            // document.write(device_type); //打印到页面
            var md = new MobileDetect(device_type); //初始化mobile-detect
            var os = md.os(); //获取系统
            console.log(os)
            var model = "";
            if (os == "iOS") { //ios系统的处理
                os = +md.version("iPhone");
                console.log(os)
                model = md.mobile();
            } else if (os == "AndroidOS") { //Android系统的处理
                os = md.os() + md.version("Android");
                var sss = device_type.split(";");
                var i = sss.contains("Build/");
                if (i > -1) {
                    model = sss[i].substring(0, sss[i].indexOf("Build/"));
                }
            }
            else {
                os = getOS();
                model = getBrowser();
            }
            //alert(os + "---" + model);//打印系统版本和手机型号
            //console.log(model + '||' + os, '打印系统版本和手机型号')
            return { "os": os, "dev": model }
        }

      
        document.write("
设备信息:"
+JSON.stringify(GetDevice())); // 获取手机类型结束
script> body> html>

--------------------------分割线-------------------------------------------------

pc

DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

    <head>
        <title> 获取PC设备信息 title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no">
        <meta name="Generator" content="EditPlus">
        <meta name="Author" content="">
        <meta name="Keywords" content="">
        <meta charset="utf-8" />
        <meta name="Description" content="">

        <script id=clientEventHandlersJS language=javascript>
            /******************************************下为浏览器信息************************************************/
            //获取浏览器相关信息
            function allinfo() {
                var appName = navigator.appName; //浏览器的正式名称
                var appVersion = navigator.appVersion; //浏览器的版本号
                var cookieEnabled = navigator.cookieEnabled; // 返回用户浏览器是否启用了cookie
                var cpuClass = navigator.cpuClass; //返回用户计算机的cpu的型号,通常intel芯片返回"x86"(火狐没有)

                var mimeType = navigator.mimeTypes; // 浏览器支持的所有MIME类型的数组
                var platform = navigator.platform; // 浏览器正在运行的操作系统平台,包括Win16(windows3.x)  
                //   Win32(windows98,Me,NT,2000,xp),Mac68K(Macintosh 680x0)
                //     和MacPPC(Macintosh PowerPC)
                var plugins = navigator.plugins; //  安装在浏览器上的所有插件的数组
                var userLanguage = navigator.userLanguage; // 用户在自己的操作系统上设置的语言(火狐没有)
                var userAgent = navigator.userAgent; //包含以下属性中所有或一部分的字符串:appCodeName,appName,appVersion,language,platform
                var systemLanguage = navigator.systemLanguage; // 用户操作系统支持的默认语言(火狐没有)

                var info = "";var type ="";if(isIe()){
                    type ="IE浏览器";}elseif(isFireFox()){
                    type ="火狐浏览器";}
                info +="";

                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";
                info +="";//info += "";
                info +="
浏览器类型:" + type + "
浏览器属性信息:" + userAgent + "
浏览器的正式名称:" + appName + "
浏览器的版本号:" + appVersion + "
浏览器的是否启用了cookie:" + cookieEnabled + "
cpu等级:" + cpuClass + "
浏览器的MIME类型:" + mimeType.length + "
系统平台:" + platform + "
安装的插件:" + plugins + "
插件的数量:" + plugins.length + "
插件的名称:" + getPluginName() + "
用户设置的操作系统语言:" + userLanguage + "
操作系统支持的默认语言:" + systemLanguage + "
Director:" + checkePlugs("Director") + "
javaEnabled:" + navigator.javaEnabled() + "
是否有quickTime:" + checkePlugs("QuickTime") + "
flash插件情况:" + checkePlugs('Shockwave Flash') + "
是否有MediaPlayer:" + checkePlugs("MediaPlayer") + "
是否有realPlayer:" + checkePlugs("RealPlayer") + "
屏幕分辨率高度:" + window.screen.height + "
屏幕分辨率宽度:" + window.screen.width + "
颜色质量:" + window.screen.colorDepth + "位
像素:" + window.screen.deviceXDPI + "像素/英寸
字体是否平滑:" + window.screen.fontSmoothingEnabled + "
规定浏览器是否启用数据污点:" + navigator.taintEnabled() + "
"
; document.getElementById("elInfo").innerHTML = info; return info; //director var appCodeName = navigator.appCodeName; //与浏览器相关的内部代码名 var appMinorVersion = navigator.appMinorVersion; //辅版本号(通常应用于浏览器的补丁或服务包) var language = navigator.language; //浏览器支持的语言 (IE没有) var onLine = navigator.onLine; //返回浏览器是否处于在线模式(IE4以上版本) var opsProfile = navigator.opsProfile; // 未定义 (IE、火狐没有) var oscpu = navigator.oscpu; //浏览器正在运行的操作系统,其中可能有CPU的信息(IE没有) var product = navigator.product; // 浏览器的产品名(IE没有) var productSub = navigator.productSub; //关于浏览器更多信息(IE没有) var securityPolicy = navigator.securityPolicy; // 浏览器支持的加密类型(IE没有) var userProfile = navigator.userProfile; // 返回一个UserProfile对象,它存储用户的个人信息(火狐没有) var vender = navigator.vender; // 浏览器厂商名称(IE、火狐没有) var vendorSub = navigator.vendorSub; // 关于浏览器厂商更多的信息 } //获取插件所有的名称 function getPluginName() { var info = ""; var plugins = navigator.plugins; if (plugins.length > 0) { for (i = 0; i < navigator.plugins.length; i++) { info += navigator.plugins[i].name + ";"; } } return info; } //检查是否安装了某插件,如果安装了返回版本号 function checkePlugs(pluginname) { var f = "-" var plugins = navigator.plugins; if (plugins.length > 0) { for (i = 0; i < navigator.plugins.length; i++) { if (navigator.plugins[i].name.indexOf(pluginname) >= 0) { f = navigator.plugins[i].description.split(pluginname)[1]; return f; break; } } } return false; } //判断是否IE function isIe() { var i = navigator.userAgent.toLowerCase().indexOf("msie"); return i >= 0; } //判断是否firefox function isFireFox() { var i = navigator.userAgent.toLowerCase().indexOf("firefox"); return i >= 0; } /******************************************以上为浏览器信息,以下为pc信息************************************************/ var locator = new ActiveXObject("WbemScripting.SWbemLocator"); var service = locator.ConnectServer("."); function cpuInfo() { //CPU 信息 var properties = service.ExecQuery("SELECT * FROM Win32_Processor"); var e = new Enumerator(properties); var info = ""; info +="";for(;!e.atEnd(); e.moveNext()){var p = e.item(); info +=""; info +=""; info +=""; info +=""; info +=""; info +=""; info +=""; info +=""; info +="";} info +="
CPU 信息
CPU序列号:" + p.ProcessorID + "
" + p.Caption + "
CPU编号:" + p.DeviceID + "
CPU型号:" + p.Name + "
CPU状态:" + p.CpuStatus + "
CPU可用性:" + p.Availability + "
CUP Level:" + p.Level + "
主机名称:" + p.SystemName + "
Processor Type:" + p.ProcessorType + "
"
; return info; } function softDisk() { //软盘信息 var properties = service.ExecQuery("SELECT * FROM Win32_FloppyDrive"); var e = new Enumerator(properties); var info = ""; info +="";for(;!e.atEnd(); e.moveNext()){var p = e.item(); info +=""; info +=""; info +=""; info +="";} info +="
软盘信息
" + p.Description + "
" + p.DeviceID + "
" + p.Status + "
" + p.Manufacuturer + "
"
; return info; } function RomInfo() { //CD-ROM 信息 var properties = service.ExecQuery("SELECT * FROM Win32_CDROMDrive"); var e = new Enumerator(properties); var info = ""; info +="";for(;!e.atEnd(); e.moveNext()){var p = e.item(); info +=""; info +=""; info +=""; info +=""; info +="";} info +="
CD-ROM 信息
驱动器名称:" + p.Caption + "
描述:" + p.Description + "
盘符:" + p.Drive + "
驱动器状态:" + p.Status + "
是否在使用:" + p.MediaLoaded + "
"
; return info; } function keyBoardInfo() { //键盘信息 var properties = service.ExecQuery("SELECT * FROM Win32_Keyboard"); var e = new Enumerator(properties); var info = ""; info +="";for(;!e.atEnd(); e.moveNext()){var p = e.item(); info +=""; info +=""; info +="";} info +="
键盘信息
键盘描述:" + p.Description + "
键盘名称:" + p.Name + "
键盘状态:" + p.Status + "
"
; return info; } function mainBoard() { //主板信息 var properties = service.ExecQuery("SELECT * FROM Win32_BaseBoard"); var e = new Enumerator(properties); var info = ""; info +="";for(;!e.atEnd(); e.moveNext()){var p = e.item(); info +=""; info +=""; info +=""; info +=""; info +=""; info +="";} info +="
主板信息
主板ID:" + p.SerialNumber + "
" + p.HostingBoard + "
制造商:" + p.Manufacturer + "
是否开启:" + p.PoweredOn + "
型号:" + p.Product + "
版本:" + p.Version + "
"
; return info; } function disk() { //硬盘序列号 信息 var properties = service.ExecQuery("SELECT * FROM Win32_DiskDrive"); var e = new Enumerator(properties); var info = ""; info +="";for(;!e.atEnd(); e.moveNext()){var p = e.item(); info +="";} info +="
硬盘信息
硬盘序列号:" + p.signature + "
"
; return info; } //获取Ram信息 function raminfo() { var system = new Enumerator(service.ExecQuery("SELECT * FROM Win32_ComputerSystem")).item(); var physicMenCap = Math.ceil(system.TotalPhysicalMemory / 1024 / 1024); //内存信息 var memory = new Enumerator(service.ExecQuery("SELECT * FROM Win32_PhysicalMemory")); for (var mem = [], i = 0; !memory.atEnd(); memory.moveNext()) { mem[i++] = { cap: memory.item().Capacity / 1024 / 1024, speed: memory.item().Speed }; } var info = ""; info +=""; info +=""; info +=""; info +="
内存信息
内存总量:" + (mem[0].cap + mem[1].cap) + "M
可用物理内存:" + physicMenCap + "M
"
; return info; } //获取网络连接信息 function ipinfo() { var properties = service.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration Where IPEnabled=TRUE"); var e = new Enumerator(properties); var info = ""; info +="";var i =1;for(;!e.atEnd(); e.moveNext()){var p = e.item(); info +=""; info +=""; i++;} info +="
网络连接信息:
MAC地址" + i + ":" + p.MACAddress + "
IP地址" + i + ":" + p.IPAddress(0) + "
"
; return info; } function pcInfo() { //所有信息 var info = cpuInfo(); info += disk(); info += raminfo(); info += mainBoard(); info += ipinfo(); info += keyBoardInfo(); info += RomInfo(); info += softDisk(); document.getElementById('elInfo').innerHTML = info; return info; } /******************************************以上为pc信息************************************************/
script> head> <body> <INPUT id="Button1" type="button" value="浏览器所有信息" name="Button1" language=javascript onclick="allinfo()"> <INPUT id="Button1" type="button" value="客户端pc信息" name="Button1" language=javascript onclick="pcInfo()"> <div id="elInfo"> div> body> html>

2、Navigator.battery获取一些电池充电状态的信息
3、 NetworkInformation 获取设备的网络连接信息。
4、Navigator.geolocation访问设备的地理位位置信息
5、NavigatorConcurrentHardware.hardwareConcurrency (en-US)获取可用的逻辑处理器核心数
6、NavigatorPlugins.javaEnabled (en-US)返回 Boolean (en-US) 表明浏览器是否支持 Java。
7、Navigator.keyboard 只读 实验性
返回一个 Keyboard 对象,该对象提供对以下功能的访问:检索键盘布局图和切换从物理键盘捕获按键的功能。
8、NavigatorLanguage.language (en-US) 只读
返回 DOMString 表示用户的首先语言,通常是浏览器用户界面的语言。当未知的时,返回 null
9、NavigatorPlugins.mimeTypes (en-US) 只读 实验性
返回 MimeTypeArray (en-US) 数组用于列举浏览器所支持的 MIME 类型。
10、NavigatorOnLine.onLine (en-US) 只读
返回 Boolean (en-US) 来表明浏览器是否联网。
11、NavigatorPlugins.plugins (en-US) 只读 实验性
返回 PluginArray (en-US) 数组用于列举出浏览器安装的插件。

由于web页面运行在用户电脑,所以浏览器为了用户数据安全,禁止本地读写数据!nodejs应用于服务器端,则有读写的权限!

script标签

异步加载
首先,script如果没有 defer和 async,那么浏览器会立即加载并执行脚本,也就是说,会阻塞后面的文档元素的加载和渲染。

有 defer属性的话,会异步加载js文件,即和加载渲染后续文档元素并行进行。加载完成后并不一定是立即执行,而是要等到所有元素解析完成后(图片是在之后解析完成),在 DOMContentLoaded事件触发之前完成

有 async属性的话,会异步加载js文件。加载完成会立即执行,阻塞后面的文档元素的加载和渲染。所以不一定按顺序执行,谁先加载完成就谁先执行。

<script defer src="https://g.csdnimg.cn/common/csdn-toolbar/csdn-toolbar.js" type="text/javascript" >script>
<script async src="https://g.csdnimg.cn/common/csdn-toolbar/csdn-toolbar.js" type="text/javascript" >script>

let、const

对于字符串数值类型不允许更改,对于复杂类型的列入数组对象和函数,能修改复杂数据类型中的值,不允许修改地址,例如:
let a = 1不允许 let a = 2,const同样

//声明a
let a = 1
//更改赋值,不被允许,const同样
let a = 2
//声明一个对象
let O = {
	name:'小张'
}
//可以更改对象中变量的值
O.name:'李四'
//不可以改变地址如:
O = {
sex:'男'
}

function

//声明一个函数
 let username = function (Name){
 	return Name
 }
 function show (){
 	let person = {
  		name:username
	}
	return person 
}
//这种情况浏览器的内存回收机制不会对username函数销毁,尽量避免这样去写代码

+=和 前置++、后置++

var a = 10
a+=1 //会立即执行-=同样
var b = 10
function num(){
b++
console.log(b)//当你遇到某些环境下数值不正确的时候查看这里
//可更改为
++b
console.log(b)//数值在控制台测试一样,但区别与环境,之所以列出来是因为在vue中遇到这个问题
}
num()

toString.call()

快速的做类型检测

//js的宽松是出了名的,比如说你要封装一个公共函数,多地方使用,可以使用这个方法做数据类型检测
console.log(toString.call({}))
// [object Object]
console.log(toString.call(1))
// [object Number]
console.log(toString.call(function(){}))
// [object Function]
console.log(toString.call(false))
// [object Boolean]
console.log(toString.call([]))
// [object Array]
//另外的一种方法就是typeof 它不会检测name详细,一股脑的会返回给你
typeof null
// "object"
 
typeof [8]
// "object"
 
typeof {}
// "object"
 
typeof function(){}
// "function"
typeof 2
//"number"
 
typeof ""
//"string"
 
typeof true
//"boolean"
 
typeof undefined
//"undefined"
 
typeof Symbol(2)
// "symbol"
//typeof 无法区分null 数组和对象,通常我们会区分判断Array和Object 有时会用instanceof 来判断是不是一个对象的实例子
[] instanceof Array
 // true 这种方法可以判断数组,不能区分对象
[] instanceof Object
// true
 
null instanceof Object
// false 也不能区分null

toSting.call()实际上是
Object.prototype.toString.call()
    function isType(type) {
     	let type = Object.prototype.toString.call(type)
     	if(type==='[object Function]'){
     	//填写逻辑
     	}else if(type==='[object Array]'){
     	//填写逻辑
     	}else if(type==='[object String]'){
     	//填写逻辑
     	}else if(type==='[object Number]'){
		//填写逻辑
		}else if(type==='[object Boolean]'){
		//填写逻辑
		}else if(type==='[object Symbol]'){
		//填写逻辑
		}else if(type==='[object Object]'){
			//填写逻辑
		}else {
			try {
				if(type==='[object Null]'||type==='[object Undefined]'){
				alert('传入的参数错误')
				}
			} catch(err) {
 				console.error("错误信息:" + err.message);
			}
		}
    }

try catch错误捕获显示样式

变量赋值

//先检查sessionStorage.a是否有值,没有就赋值1
var a = sessionStorage.a||1//sessionStorage.a有值则是sessionStorage.a,没值则是1
var a = sessionStorage.a??1//sessionStorage.a有值则是sessionStorage.a,没值则是1
function num(type =1){
	return  {
		num:type
	}
}
num()//{num:1}
num(11)//{num:11}
//规避赋值为null方法

async await

//使用async await让接口同步,完成在进行下行代码运行
export function log(data){
	//模拟接口1
	console.log(123)
	return axios({
		url:'xxxx/xxx/xx--/ss',
		method:'post',
		data
	})
}
export function log2(params){
//模拟接口2
	console.log(123)
	return axios({
		url:'xxxx/xxx/xx--/ss',
		method:'get',
		params
	})
}
async function init(){
let params = {id:1}
	await log(params).then(res=>{}).catch(error=>{})
	let {code,message,result} = await log2({id:1})
}

js创建dom,没有闭合标签

var dom = document.createElement('video')
//这部特别重要,以下步骤,会将创建闭合标签,没有这一步,当你使用innerHTML插入闭合标签,使用appendChild插入会报错
dom.innerText = '您的浏览器不支持视频播放'
xx.innerHTML = dom
xx.appendChild(dom)

eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行。

eval("x=10;y=20;console.log(x*y)"); // 200
console.log(eval("2+2")); // 4
console.log(eval(x+17)); // 27
console.log(eval(18)); // 18
// 相当于直接调用console.log
let msg = "hello world";
eval("console.log(msg)"); // hello world
// 相当于函数声明
eval("function sayHi() { console.log('hi'); }");

const obj = {
  a: {
    b: {
      c: 1,
    }
  }
}
function get(str) {
  console.log(eval(str)) // 1,相当于console.log(obj.a.b.c)
}
get('obj.a.b.c')

此方法和innerHTML慎用,如果有黑客察觉并恶意使用,会造成损失

原生delete方法

var nun = [1,2,3,4,5,6]
delete(nun[0])
console.log(nun)
VM1001:3 (6) [empty, 2, 3, 4, 5, 6]//会出现这种结果,可以使用遍历删除

创建Array和Object

var arr = []
var array = new Array([1,1,3])
var obj = {}
var object = new Object({name:'123'})

iframe跨域通信

父传子

// 父页面
<iframe id="iframe" src="http://test.com/childrenCrossDomain.html" name="childrenName"></iframe>
   
<script>
      let iframe = document.getElementById('iframe');
      function sendToChildren(){
          iframe.contentWindow.postMessage('hello啊,在吗', 'http://test.com')
      }
</script>
 
// 子页面
<script>
      window.addEventListener("message", function(e){
          console.log(e.data)
      });
</script>

子传父

// 父页面
window.addEventListener('message',function(e){
    console.log(e.data)
})
 
// 子页面
window.parent.postMessage('不在', 'http://父域名');

if的语法简写,不建议使用,阅读性差

var a = 1
if(a) console.log(1)


你可能感兴趣的:(冷门前端知识,前端,javascript,html)