整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

外国人眼中的古都南京:历史文化和现代生活融为一体

媒称,南京是一座现代化城市,但它有一种古老的蕴味,这座城市的历史遗韵使建筑与自然环境很和谐。

据英国广播公司网站5月13日报道,南京首次建都于公元229年,长期以来是中国最重要(和最大)的内河港口之一,也是公认的中国四大古都之一。这里发现了距今约60万年的直立人化石;明朝时期环绕这座城市的石头城墙距今已有600年的历史,而今仍然与现代的摩天大楼屹立在一起,使这座城市跟其复杂多变的过去有了永恒的视觉联系。

原籍英格兰设菲尔德、现居住在南京的中学教师弗雷娅·德鲁说:“从北京西路附近民国时期的低层建筑、新街口附近高耸的摩天大楼到老浦口蜿蜒的陋屋小巷,南京的建筑千差万别。”

<iframe data-filtered="filtered" frameborder="0" height="0" src="http://cpro.baidustatic.com/cpro/ui/c.html" width="0"></iframe>

报道称,虽然这种并列毗邻在其他城市可能看上去不协调,但在南京行得通。2018年来到这里的苏格兰教师埃德·库勒姆说:“这座城市的道路,往往绿树成荫,起起伏伏;老旧居住区紧挨着非常现代化的建筑。南京无疑是一座现代化城市,但它有一种古老的蕴味,这座城市的历史遗韵使建筑与自然环境很和谐。”

报道还称,作为一个外来人口不断增加的大学城,南京的节奏不同于熙熙攘攘的北京,也不同于极其新潮的上海,而是新来者乐于接受的平和折衷。

库勒姆解释说,尽管拥有830万人口,但南京是中国为数不多的很容易让人获得安宁和平静的大城市之一。他说:“在浦口(南京西北部的一个地区),坐30分钟的公共汽车就能把你送到老山风景区的边缘。这片大面积的森林覆盖的丘陵有许多小路和小径,很容易把喧闹的人群抛在身后。”

报道称,就在南京市中心,玄武湖提供了一个躲避喧嚣的安静之处,玄武湖公园内有寺庙、茶馆和餐厅。为了更好地了解南京的历史,库勒姆建议到老门东走一走,就在秦淮河以北,是一条经过整修的步行街。老门东是该市历史最悠久的商业街之一,其特色是拥有古典的木结构建筑(修旧如旧),内有纪念品商店,还有供应当地特色美食的小餐馆,比如盐水鸭、肉丸和美味糕点等等。

报道还称,与北京或西安的城墙不同,南京的老城墙不是几何形状的,而是绕着湖和山而建。因此,自然景观往往出现在意想不到的城区。像长江、钟山、玄武湖这些处于城市中心的自然景观给人带来的惊喜,正是新居民们喜欢生活在这里的原因所在。

库勒姆说:“对我来说,生活在南京意味着避开熙熙攘攘的大街,转入老街小巷,可能遇到几处院落、几泓碧水或几片幽林。正是这种巨大的多元性让南京具有了自己的魅力。”

库勒姆说,“对于喜欢避开线性基线重击声的人们”,这座城市还有许多低调的夜总会和现场音乐演出场所。对于想念老家食物的人来说,这里并不缺少迎合外国人和留学生的外国餐厅和咖啡馆。在城市里转一圈很容易。南京拥有一个覆盖该市大部分地区的高效、宽敞的地铁系统,不过自行车也是一个选项,这里有适合骑车的宽阔、笔直的道路。

原标题:外国人眼中的古都南京:历史文化和现代生活融为一体

frame优缺点

优点:

  1. 网页嵌套:通过 iframe,可以将另一个网页嵌入到当前页面中。这对于集成第三方内容(如地图、视频、社交媒体插件等)非常方便,可以在不离开当前页面的情况下展示外部内容。
  2. 安全隔离:每个 iframe 都有独立的文档对象模型(DOM),这意味着它们之间的操作相互隔离。这可以防止外部网页影响当前页面的样式和脚本。
  3. 并行、异步加载:iframe 可以并行且异步加载其嵌套的网页,不会阻塞当前页面的渲染和加载。这可以提高页面的整体性能和加载速度。

缺点:

  1. 性能问题:每个iframe都需要加载渲染,会增加页面加载时间和资源消耗
  2. SEO 问题:搜索引擎可能无法正确地解析 iframe 内的内容,这可能会影响页面的搜索引擎优化(SEO)。
  3. 跨域限制:由于浏览器的同源策略限制,嵌套在 iframe 中的网页只能与同域的父页面进行受限的通信。跨域通信需要通过特殊的技术手段(如跨文档消息传递)来实现。
  4. 响应式问题:在移动设备等小屏幕上,iframe 可能需要滚动或者缩放才能适应屏幕,这可能会导致用户体验下降。

⭐H5新特性

  • 新增选择器 document.querySelector、document.querySelectorAll
  • 拖拽释放(Drag and drop) API
  • 媒体播放的 video 和 audio
  • 本地存储 localStorage 和 sessionStorage
  • 离线应用 manifest
  • 桌面通知 Notififications
  • 语意化标签 article、footer、header、nav、section
  • 增强表单控件 calendar、date、time、email、url、search
  • 地理位置 Geolocation
  • 多任务 webworker
  • 全双工通信协议 websocket
  • 历史管理 history
  • 跨域资源共享(CORS) Access-Control-Allow-Origin
  • 页面可见性改变事件 visibilitychange
  • 跨窗口通信 PostMessage
  • Form Data 对象
  • 绘画 canvas

⭐自定义元素

HTML 提供了一系列内置的元素(如 <div>、<p> 等),而自定义元素则是由开发者自定义的,可以用来扩展 HTML 语义和功能。

在传统的 HTML 中,我们只能使用已定义的标签来创建元素,如 <div>、<p>、<span> 等。但随着 Web 技术的不断发展,HTML5 引入了自定义元素的功能,允许开发者创建自己的标签,并赋予其特定的行为和样式。

CSS

⭐BFC

带你用最简单的方式理解最全面的BFC哔哩哔哩bilibili

BFC,即块级格式化上下文(Block Formatting Context),是CSS中的一个概念。它是指一个独立的渲染区域,其中的元素按照一定的规则进行布局和渲染。

BFC的主要作用是控制元素在布局上的行为,包括外边距的塌陷、浮动元素对周围元素的影响以及清除浮动等。以下是BFC的一些特性和应用:

  1. 外边距折叠:在BFC中,垂直方向上的相邻元素的外边距会发生折叠(合并)现象,从而避免了不必要的间距。但在同一个BFC的元素中,父子元素之间的外边距不会发生折叠。
  2. 清除浮动:BFC可以包裹浮动元素,使其不对其他元素造成影响。通过创建一个新的BFC,可以清除浮动带来的高度塌陷问题。
  3. 阻止浮动元素重叠:在BFC中,浮动元素会受到BFC边界的限制,从而阻止其与其他元素的重叠。这有助于解决一些浮动布局导致的错位或溢出问题。
  4. 自适应两栏布局:BFC可以使用浮动或者overflow: hidden;等方式创建,结合盒模型和清除浮动,可以实现一些常见的布局需求,如自适应两栏布局。

创建BFC的方式有多种,包括:

  • 给元素添加 float 属性。
  • 给元素添加 display: inline-block;、display: table-cell;、display: table-caption; 等属性。
  • 给元素添加 overflow 属性为除 visible、clip 之外的值。

总而言之,BFC是一种控制元素布局行为的机制,它可以解决一些常见的布局问题,如外边距塌陷、浮动元素重叠等。了解BFC的使用和原理对于前端开发中复杂布局的实现非常有帮助。

⭐实现水平居中

  1. 行内元素:text-align:center
  2. 块级元素:
    1. margin: 0 auto(确定宽度的情况下)
    2. transform + 绝对定位
    3. display:flex + justify-content:center
    4. 子display:inline-block + 父text-align:center
    5. display:table + margin:auto

⭐实现垂直居中

  1. 对于文字:设置line-height
  2. flex + align-items
  3. transform + 定位
  4. display:table + verticle-align:middle

⭐水平垂直居中

① 使用Flexbox:通过将父容器设置为display: flex;,然后使用justify-content: center;和align-items: center;属性来水平和垂直居中子元素。

.parent {
  display: flex;
  justify-content: center;
  align-items: center;
}

② 使用Grid布局:通过将父容器设置为display: grid;,然后使用place-items: center;属性来水平和垂直居中子元素。

.parent {
  display: grid;
  place-items: center;
}

③ 使用绝对定位和transform属性:将子元素的位置设置为绝对定位,并且使用top: 50%;和left: 50%;将元素的左上角移动到父容器的中心,然后使用transform: translate(-50%, -50%);将元素的中心与父容器的中心对齐。

.parent {
  position: relative;
}

.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

④ 使用表格布局:将父容器设置为display: table;,然后将子元素设置为display: table-cell;vertical-align: middle;以实现水平和垂直居中。(文本水平垂直居中)

.parent {
  display: table;
}

.child {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
}

⑤父flex + 子margin:auto

⑥绝对定位均设0 + margin:auto

⭐圣杯布局&双飞翼布局

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        /* 
            思路:
                1、容器宽度设为100%来填充整个页面宽度
                2、为左右中三者设置float:left,以此可以显示在一行
                3、为left和right部分设置负的margin值,让它们移到center行中,但注意,现在的left和right将center左右部分覆盖了
                4、解决覆盖问题,有两种方式:
                    (1) 为center左右设置内边距,但这时会将页面撑大,所以我们要将内边距合并到100%的宽度里,这里我们想到了用怪异盒模型
                    (2) 用定位的方式解决,为容器wrapper设置内边距,然后为left和right设置相对定位,并为其移动到左右两边
​
            扩展:
                与双飞翼布局的区别?
                    圣杯布局通过设置负边距与容器内边距来使三栏显示于一列,而双飞翼布局则为中间列额外包裹添加外边距来防止左右两侧遮挡,两者实现效果相似
        
        */
        .item {
            height: 100px;
            /* 这里设置浮动是为了让三者可以并排显示 */
            float: left;
        }
​
        .center {
            /* 为了防止左右两块与center重叠,我们要为其设置内边距 */
            /* padding: 0 300px; */
            /* 方式一:将盒子模型设为怪异盒模型,防止padding将左右顶开 */
            /* box-sizing: border-box; */
        }
​
        .center {
            width: 100%;
            background-color: green;
        }
​
        .wrap {
            padding:0 300px;
        }
​
        .left {
            width: 300px;
            background-color: yellow;
            /* 为了让left块和center在同一行,需要用负的margin值让它向回移动 */
            margin-left: -100%;
            /* 方式二:设relative */
            position: relative;
            left: -300px;
        }
​
        .right {
            width: 300px;
            background-color: red;
            /* 为了让right块和center在同一行,需要用负的margin值让它向回移动 */
            margin-left: -300px;
            /* 方式二:设relative */
            position: relative;
            right: -300px;
        }
    </style>
</head>
<body>
    <!-- 圣杯布局分左右中三部分 -->
    <div class="wrap">
        <!-- 为了让中间内容先渲染,写在上面 -->
        <div class="item center"></div>
        <div class="item left"></div>
        <div class="item right"></div>
    </div>
</body>
</html>

clearfix

.clearfix::after {
    content: "";
    clear: both;
    display: block;
}

clearfix通过为父元素添加伪元素,并为其添加清除浮动效果来解决浮动元素引起的高度塌陷问题,这里设置display:table主要有两方面作用:

  1. 生成独立的BFC,从而避免浮动元素对其周围其他元素的影响
  2. 表格布局有自动调整单元格高度的特性,即表格单元格会根据内容自动撑开高度。通过将伪元素设置为 display: table,可以使其撑开父元素的高度,从而让父元素正确地包含浮动元素。

⭐flex

对于轴线:

  • 设定主轴方向
    • flex-direction:
      • row(default)
      • row-reverse
      • column
      • column-reverse
  • 是否换行
    • flex-wrap:
      • nowrap(default)
      • wrap
      • wrap-reverse
  • 前两者可以合并
    • flex-flow:
      • row nowrap(default)
  • 主轴对齐方式
    • justify-content:
      • flex-start(default) 左对齐
      • flex-end 右对齐
      • center
      • space-between 两端对齐,中间间隔相同
      • space-around 每个成员两侧的间隔相等
      • space-evenly 均匀分布,两侧靠边间隔与元素之间间隔也相同
  • 成员在交叉轴(主轴外的另一个轴)的对齐方式,默认可以理解为y轴
    • align-items:
      • flex-start 交叉轴起点对齐
      • flex-end 交叉轴终点对齐
      • center
      • baseline 文字基线对齐
      • stretch(default) 若未设置高度,则默认占满整个交叉轴
  • 多根轴线(多行)的对齐方式(多根主轴在交叉轴上的对齐方式)
    • align-content:
      • flex-start 与交叉轴起点对齐
      • flex-end 与交叉轴终点对齐
      • center
      • space-between 交叉轴两端对齐,中间平均分布
      • space-around 每根轴线两侧间隔都相同
      • space-evenly 均匀分布,两侧靠边间隔与元素之间间隔也相同
      • stretch(default) 占满整个交叉轴

对于其中的每一项:

  • order 值为数字,为排序的权重
  • flex-grow 值为数字,意为成员的放大比例,默认为0,若都设为1,则会放大等分剩余空间(忽略其原本宽度,全部等分)
  • flex-shrink 值为数字,意为成员的缩小比例,默认为1,若空间不足,则会缩小相同比例,若设为0,则不缩小,若都不缩小,则会超出
  • flex-basis 值为长度,意为在未分配剩余空间时,成员占据的主轴空间大小,默认为auto,即为成员的本来大小
  • flex 为flex-grow flex-shrink flex-basis的简写,默认为0 1 auto ,后两者可选,我们常用这个属性,其实本质大多数用的都是flex-grow
  • align-self 单个成员的交叉轴对齐方式
    • auto(default) 继承自父元素 如果没有父元素,则默认为stretch
    • flex-start
    • flex-end
    • center
    • baseline
    • stretch

⭐清除浮动

浮动的原理是让图片脱离文档流,直接浮在桌面上。我们一般布局的时候都是只设置宽度不设置高度,让内容来自动填充高度。但使用浮动后会让原本填充的高度消失,父元素高度为0,后续添加内容布局会产生混乱,造成高度塌陷,这时候就可以利用清除浮动来解决父元素高度塌陷的问题。

浮动导致的问题及其解决方案:

  • 父元素高度塌陷
    • 父元素固定宽高(适用于宽高确定的板块)
    • 在浮动元素后面新加一个空标签,并设置clear: both;
      • 优点:简单
      • 缺点:添加了许多空的div,语义化差
    • overflow: hidden
      • 优点:简单易用,浏览器支持好
      • 缺点:要设置width和zoom,且有时会裁剪掉部分元素
    • clearfix::after(主流做法)
.clearfix:after{/*伪元素是行内元素 正常浏览器清除浮动方法*/
    content: "";
    display: block;
    height: 0;
    clear:both;
    visibility: hidden;
}
.clearfix{
    *zoom: 1;/*ie6清除浮动的方式 *号只有IE6-IE7执行,其他浏览器不执行*/
}
  • 同级非浮动元素被覆盖
    • 给被遮盖的元素也设置浮动
    • 为被遮盖的元素触发BFC(宽度足够会同行显示)
    • 为被遮盖的元素设置clear: both;(会换行显示)

⭐Grid布局

①定义grid布局:

  • display: grid/inline-grid

②设置行与列的布局

  • grid-template-rows / grid-template-columns
    • 基本使用:grid-template-rows(grid-template-columns): 100px 100px 200px,设置三行(列),高度(宽度)分别为100 100 200px
    • repeat():grid-template-rows(grid-template-columns): repeat(3, 100px),设置三行(列),高度(宽度)均为100px
      • auto-fill:grid-template-rows(grid-template-columns): repeat(auto-fill, 100px),不定有几行/几列,能装多少装多少,当可用空间不足以容纳更多的列时,会创建空的隐式网格项来填充空白区域
      • auto-fit:尽量将每一列放入网格容器中,使得不留下空白的空间,当可用空间不足以容纳更多的列时,会自动调整已有的网格项的大小,以填充剩余空白区域
    • fr:占比,与flex-grow类似,grid-template-rows(grid-template-columns): 100px 1fr 2fr,除去100px,剩下按1:2划分
    • minmax():grid-template-rows(grid-template-columns): 1fr 1fr minmax(100px, 2fr),表示第三行(列)最少为100px,最大不能超过前两行(列)的两倍
    • auto:自动调整,grid-template-rows(grid-template-columns): 100px auto 100px,实现自由适配的三栏布局
  • row-gap / columns-gap / gap:行间距列间距以及二合一写法

③划分区域自定义放置元素

  • grid-template-areas:划分区域
  grid-template-columns: 120px  120px  120px;
    grid-template-rows: repeat(3, 300px);
    grid-template-areas:
      ". header  header"
      "sidebar content content"
      "sidebar .  .";
  • 定义三行三列,通过grid-template-areas来划分区块,并为其命名, . 表示空
  • grid-area:放置元素
  •   .sidebar {
        grid-area: sidebar;
      }
      ​
      .content {
        grid-area: content;
      }
      ​
      .header {
        grid-area: header;
      }
    • 规定哪个类的内容放在哪个区块中

    ④划分区域自动填充元素

    • grid-auto-flow
      • row 默认值,按行进行依次填充
      • column,按列进行依次填充
      • 附加值dense,是否紧凑填充,可以自动在后方找到合适大小的块填充到前面的单元格中,防止按序填充时出现元素过大填充不满的现象

    ⑤自由安排元素位置

    • grid-column-start、grid-column-end、grid-row-start、grid-row-end:分别对应网格的上边框位置、下边框位置、左边框位置、右边框位置,通过这四个元素将内容定位到网格中(左上方顶点为1,向右向下递增)
      • span:声明项目跨度(占几个格子),在start中设置,end就可以不用设置
    • 简写形式:grid-area: 2 / 1 / 4 / 3(其中,2表示起始行,1表示起始列,4表示结束行,3表示结束列)

    ⑥所有元素在单元格内的对齐方式

    • justify-items / align-items:水平/垂直对齐方式
      • start
      • end
      • center
      • stretch(默认)
    • place-items:水平和垂直的合并形式,写两个就是左水平右垂直,写一个就是两者共用

    ⑦单个元素在单元格内的对齐方式

    • justify-self、align-self、place-self:与⑥中用法完全一致,只是针对单个元素使用

    ⑧单元格在容器内的对齐方式

    • justify-content / align-content:水平/垂直对齐方式
      • start(默认)
      • end
      • center
      • stretch
      • space-between
      • space-around
      • space-evenly
    • place-content为上两者的合并形式

    ⑨多出来的东西怎么放?隐式网格

    • grid-auto-columns / grid-auto-rows:定义隐式网格的单元格长宽

    一些面试题

    1. 请解释什么是CSS Grid布局?
    2. Grid布局中有哪些主要的概念和术语?
    3. 请解释Grid容器和Grid项之间的区别是什么?
    4. 如何在父元素上应用Grid布局?
    5. 请解释Grid布局中的行和列是如何定义的?
    6. 如何指定Grid项在网格中的位置?
    7. Grid布局中的重叠和层叠是如何处理的?
    8. 如何控制Grid项的大小和对齐方式?
    9. 请解释Grid布局的自动布局机制。
    10. 如何媒体查询和响应式设计与Grid布局结合使用?

    ⭐选择器

    基本选择器:id class 标签 层次选择器:后代、子代、兄弟、通用 结构选择器:第一个、最后一个、奇数偶数个、伪类、伪元素 属性选择器:属性

    ⭐animation有哪些属性

    CSS 的 animation 属性用于为元素添加动画效果。以下是 animation 属性的一些常用子属性:

    1、animation-name: 定义动画的名称。

    .animation {
      animation-name: myAnimation;
    }
    ​
    @keyframes myAnimation {
      0% { opacity: 0; }
      100% { opacity: 1; }
    }

    2、animation-duration: 定义动画的持续时间。

    .animation {
      animation-name: myAnimation;
      animation-duration: 2s;
    }

    3、animation-timing-function: 定义动画的时间函数(即动画进度的加速度)。

    .animation {
      animation-name: myAnimation;
      animation-timing-function: ease-in-out;
    }

    4、animation-delay: 定义动画开始之前的延迟时间。

    .animation {
      animation-name: myAnimation;
      animation-delay: 1s;
    }

    5、animation-iteration-count: 定义动画的播放次数,infinite为永不停止。

    .animation {
      animation-name: myAnimation;
      animation-iteration-count: 3;
    }

    6、animation-direction`: 定义动画的播放方向。

    .animation {
      animation-name: myAnimation;
      animation-direction: reverse;
    }

    7、animation-fill-mode: 定义动画在播放之前和之后如何应用样式。

    1. none:默认值,动画不会对元素应用任何样式。在非活动时间段,元素将恢复到初始样式。
    2. forwards:在动画结束后,元素将保持动画结束状态。也就是说,元素将保持在最后一帧的状态。
    3. backwards:在动画开始前,元素将立即应用动画的第一帧样式。这意味着动画开始前的状态会提前被应用。
    4. both:结合了 forwards 和 backwards,在动画开始前和结束后都会应用样式。
    .animation {
      animation-name: myAnimation;
      animation-fill-mode: forwards;
    }

    8、animation-play-state: 定义动画的播放状态。

    .animation {
      animation-name: myAnimation;
      animation-play-state: paused;
    }

    这些是 animation 属性的一些常用子属性,它们可以用来控制动画的各个方面,从而创建出丰富多样的动画效果。使用这些属性可以自定义动画的外观、持续时间、延迟等。要实现动画效果,还需要定义动画的关键帧(@keyframes)规则,包含动画在不同百分比时的样式。

    在 CSS 中,可以使用 @keyframes 规则来定义动画的关键帧(即动画的不同阶段)。@keyframes 规则定义了动画的每个关键帧以及相应的样式。

    下面是一个使用 @keyframes 定义动画关键帧的示例:

    @keyframes slide {
      0% {
        transform: translateX(0);
      }
      50% {
        transform: translateX(100px);
      }
      100% {
        transform: translateX(200px);
      }
    }

    在这个例子中,我们创建了一个名为 slide 的动画。通过 @keyframes 规则,我们定义了三个关键帧:0%、50% 和 100%。

    • 在 0% 关键帧,元素的 transform 属性设置为 translateX(0),即初始状态。
    • 在 50% 关键帧,元素的 transform 属性设置为 translateX(100px),表示动画进行到一半时的状态。
    • 在 100% 关键帧,元素的 transform 属性设置为 translateX(200px),表示动画结束时的状态。

    你可以在关键帧中定义任意数量的状态,并根据需要设置不同的样式属性。使用百分比来表示关键帧的时间点,动画会根据关键帧之间的插值进行平滑过渡。

    定义完关键帧后,你可以使用 animation-name 属性将动画应用到具体的元素上,如下所示:

    .element {
      animation-name: slide;
      animation-duration: 2s;
    }

    通过将 animation-name 设置为关键帧名称,你可以将定义好的动画应用于元素,并设置动画的持续时间(在此示例中为 2 秒)。

    请注意,在实际使用中,除了设置关键帧的样式,你还可以使用其他属性调整动画的速度、延迟、重复次数等。根据具体需求,你可以进一步完善动画效果。

    ⭐说说transition

    CSS 的 transition 属性用于在元素发生状态变化时,平滑地过渡(或动画)到新的样式。它允许你控制一个或多个 CSS 属性的变化过程,使得元素的变化更加柔和和可控。

    transition 属性由以下几个子属性组成:

    1、transition-property:指定要过渡的 CSS 属性名称,可以是单个属性,也可以是多个属性。 当 transition 属性只设置了 transition-duration 值时,没有指定 transition-property 值,默认情况下所有可过渡的 CSS 属性都会应用过渡效果。

    .element {
      transition-property: width;
    }

    2、transition-duration:指定过渡的持续时间,以秒(s)或毫秒(ms)为单位。

    .element {
      transition-duration: 0.5s;
    }

    3、transition-timing-function:指定过渡的时间函数,用于控制过渡的速度曲线。常见的值包括 ease(默认值)、linear、ease-in、ease-out 和 ease-in-out,也可以使用贝塞尔曲线来定义自定义的速度曲线。

    .element {
      transition-timing-function: ease-in-out;
    }

    4、transition-delay:指定过渡开始之前的延迟时间,以秒(s)或毫秒(ms)为单位。

    .element {
      transition-delay: 0.2s;
    }

    通过使用这些子属性,你可以控制元素的过渡效果,从而实现例如悬停时颜色渐变、尺寸变化、透明度渐变等效果。

    例如,下面的代码演示了一个当鼠标悬停在元素上时,背景颜色发生渐变过渡的效果:

    .element {
      background-color: blue;
      transition-property: background-color;
      transition-duration: 0.5s;
      transition-timing-function: ease-in-out;
    }
    ​
    .element:hover for(let [key, value] of map) {
            if(largeStr.indexOf(key)!==-1) {
                
            }
        }
      background-color: red;
    }

    以上代码将使元素的背景颜色在悬停时从蓝色平滑地过渡到红色,过渡时间为 0.5 秒,速度曲线为先加速后减速。这只是 transition 属性的一个简单示例,你可以根据需要调整和组合这些子属性来实现更复杂的过渡效果。

    ⭐外边距塌陷解决方案

    外边距塌陷是指在垂直方向上,两个相邻元素的外边距(margin)合并成一个外边距的现象。以下是几种常见的外边距塌陷情况及其解决方案:

    1. 父子元素外边距塌陷:
    2. 情况:父元素的上边距与第一个子元素的上边距合并,导致外边距塌陷。
    3. 解决方案:给父元素添加 overflow: hidden; 或 float: left/right; 属性,为父元素创建新的块级格式化上下文(BFC),从而阻止外边距的合并。
    4. 相邻兄弟元素外边距塌陷:
    5. 情况:两个相邻的兄弟元素,上一个元素的下边距与下一个元素的上边距合并,导致外边距塌陷。
    6. 解决方案:给其中一个元素添加 padding-top 或 border-top 属性,或者在两个元素之间插入空元素(例如 <div></div>)。
    7. 空元素与外边距塌陷:
    8. 情况:一个没有内容的空元素或没有上边框/上内边距的元素,上边距与其下面的元素的上边距合并,导致外边距塌陷。
    9. 解决方案:给空元素添加 padding-top 或 border-top 属性,或者为其添加 display: inline-block; 属性。
    10. 内部包含块的外边距塌陷:
    11. 情况:一个元素的内部包含块(例如 <div>)中的第一个子元素的上边距与外部元素的上边距合并,导致外边距塌陷。
    12. 解决方案:为外部元素添加 overflow: hidden; 或 float: left/right; 属性,将其变为 BFC,阻止外边距合并。

    这些解决方案的原理都是通过改变元素的布局特性来创建新的块级格式化上下文(BFC),从而阻止外边距的合并。BFC 可以独立地控制元素的布局行为,使得外边距不再发生塌陷。

    ⭐说一说overflow的各个值

    • visible:正常显示,多余部分超出盒子显示
    • scroll:默认显示滚动条
    • hidden:不提供滚动条,也不支持用户滚动,多于内容会被裁剪,但可以通过脚本控制滚动
    • clip:和hidden类似,但不允许通过脚本滚动,也不会生成BFC
    • auto:溢出显示滚动条,不溢出则不显示,生成BFC
    • overlay:行为与auto相同,但滚动条绘制在内容之上,不占据空间

    ⭐说说伪类和伪元素

    伪类: 用于已有元素处于某种状态时为其添加对应的样式,这个状态是根据用户行为而动态变化的

    例如:当用户悬停在指定元素时,可以通过:hover来描述这个元素的状态,虽然它和一般css相似,可以为 已有元素添加样式,但是它只有处于DOM树无法描述的状态下才能为元素添加样式,所以称为伪类

    伪元素: 用于创建一些不在DOM树中的元素,并为其添加样式

    例如,我们可以通过:before来在一个元素之前添加一些文本,并为这些文本添加样式,虽然用户可以看见 这些文本,但是它实际上并不在DOM文档中

    ⭐引入样式时,link和@import的区别?

    1. 加载顺序: <link> 在页面加载时同时被加载,而 @import 在页面加载后才被加载。因此,<link> 可以更快地加载外部资源,并且不会阻塞页面的加载,而 @import 会延迟页面的显示,直到所有的 CSS 文件加载完毕。
    2. 兼容性: <link> 是 HTML 标签,可以被所有浏览器和搜索引擎正确解析。而 @import 是 CSS 的语法规则,只能被符合 CSS3 规范的浏览器正确解析,低版本的浏览器可能会忽略 @import 声明。
    3. 使用方式: <link> 可以用于加载任何类型的文件,如 CSS、JavaScript、图像、音频等。而 @import 只能用于加载 CSS 文件。
    4. 作用域: <link> 中的样式表对整个页面都起作用,而 @import 只对当前样式表中的规则起作用。

    综上所述,<link> 更适合引入外部资源,而 @import 更适合在 CSS 文件中嵌入其他 CSS 文件。如果需要同时加载多个 CSS 文件,最好使用 <link>,以提高页面的性能和可访问性。

    ⭐display、visibility、opacity的区别

    • display:none; DOM结构:浏览器不会渲染display属性为none的元素,不占据空间,意思就是页面上没有它的一席之地,你在开发者模式中选不中那个元素。 事件监听:无法进行DOM事件监听。 性能:动态改变此属性时会引起回流,性能较差。 继承:不会被子元素继承,因为子元素也不被渲染。 transtion过渡不支持display。
    • visibility:hidden; DOM结构:元素被隐藏了,浏览器会渲染visibility属性为hidden的元素,占据空间,意思就是页面上有它的空间,在开发者模式中能选中那个元素。 事件监听:无法进行DOM事件监听。 性能:动态改变此属性时会引起重绘,性能较高。 继承:会被子元素继承,子元素通过设置visibility:visible;来显示自身,使子元素取消自身隐藏。 transtion:visibility会立即显示,隐藏时会延时。
    • opacity:0; DOM结构:opacity属性值为0时透明度为100%,元素隐藏,占据空间,opacity值为0到1,为1时显示元素。 事件监听:可以进行DOM事件监听。 性能:提升为合成层,不会引发其他元素的重绘,性能较高。 继承:会被子元素继承,子元素不能通过设置opacity:1;来取消隐藏。 transtion:opacity可以延时显示与隐藏。

    JS

    ⭐简述JavaScript对象、函数、数组的定义。

    对象(Object):JavaScript 的对象是一种复合数据类型,用于存储键值对。对象由一组属性(properties)组成,每个属性都有一个键(key)和对应的值(value)。对象可以通过字面量表示法或构造函数来创建。

    函数(Function):JavaScript 是一门函数式编程语言,函数在 JavaScript 中是一等公民。函数是可执行的代码块,可以接收参数并返回一个值。可以通过函数声明或函数表达式的方式定义函数。

    数组(Array):JavaScript 数组是一种有序、可变的数据集合,可以存储多个值。数组可以包含不同类型的数据,并且长度是动态的。可以使用字面量表示法或构造函数来创建数组。

    ⭐说说JS中的隐式转换

    隐式类型转换是指 JavaScript 在比较或计算操作中自动将一个数据类型转换为另一个数据类型。这种类型转换是根据 JavaScript 的类型转换规则进行的,以下是一些常见的隐式类型转换规则:

    ==

    1. 字符串和数字之间的比较:如果一个操作数是字符串,另一个操作数是数字,JavaScript 会将字符串转换为数字,然后进行比较。
    2. 布尔值和其他类型之间的比较:布尔值在进行比较时,会被转换为数字,true 被转换为 1,false 被转换为 0。
    3. 对象和原始值之间的比较:对象在进行比较时,JavaScript会先使用 valueOf() 方法获取对象的原始值,然后再根据前面提到的方法将两个值进行比较。如果 valueOf() 方法无法返回原始值,则会尝试调用 toString() 方法来获取值。
    4. null 和 undefined 的比较:它们在进行相等比较时被认为是相等的。

    运算

    1. string+其他基本数据类型,转为string
    2. 其他基本数据类型与的number类型操作,均转为number

    补充问题:

    当a为多少时,if判断成立

    let a
    if(a == 1&&a == 2&&a == 3) {
        console.log('success!') 
    }

    答案:

    a = {
        a:1,
        valueOf() {
            return a++
        }
    }

    前端性能优化

    首屏优化

    1. 压缩、分包(利用浏览器并行的能力加载)、删除无用代码
    2. 静态资源分离,如放在CDN上面
    3. JS脚本非阻塞加载(或将其放在最底部,最后加载,以防阻塞页面渲染)
    4. 合理利用缓存
    5. 服务器端渲染(SSR)
    6. 预置loading、骨架屏

    渲染优化

    1. GPU加速,利用GPU来处理复合图层(像素密集型)进行“加速”
    2. 减少回流、重绘,例如:
      1. 避免使用CSS表达式,因为当页面变化时,都会进行重新计算
      2. 不适用table布局,因为该布局中的一个小改动都会引起整个table重新布局,所以现在table布局已经几乎淘汰
      3. 能使用css就不使用js
    3. 离屏渲染,正常情况下数据经过计算和渲染后,就会直接显示在屏幕上,而使用离屏渲染,就会在内存将画面全部渲染好,再放在页面上,以防画面过于复杂而使用户感到掉帧
    4. 懒加载,将需要的资源提前加载到本地,需要时直接从缓存中取出,节约时间。

    JS优化

    1. 防止内存泄露,比如:
      1. 使用全局变量不当产生的内存泄露
      2. DOM引用没有及时清除,导致DOM删除后但JS引用依旧存在,占用资源
      3. 定时器没有及时关闭(所以建议自己封装可以自动关闭的定时器组件)
    2. 循环语句尽早break
    3. 合理使用闭包
    4. 减少DOM访问,因为JS引擎和渲染引擎交互较为费时,如果需要常用,要使用一个变量将其缓存起来,不要每次都去查询获取
    5. 防抖——多次点击,只执行最后一次
    6. 节流——一定时间内,多次调用只执行一次
    7. Web Worker(工作线程),可以将一些耗时的数据处理操作从主线程中剥离出来,使主线程更加专注于页面渲染和交互。

    ⭐跨浏览器兼容问题

    1. CSS盒模型差异,可以使用CSS重置或使用标准化库来进行统一各浏览器的默认样式
    2. JavaScript API兼容性问题,可以通过特性检测来判断当前浏览器是否支持某个API,或使用polyfill库来提供缺失的功能
    3. flex布局兼容性问题,可以使用grid等布局来作为替代方案

    ⭐如何保证代码的质量和可维护性

    1. 模块化,特定的模块负责特定的功能,提高代码的可复用性,降低耦合
    2. 通过一些设计模式来管理实例,例如单例模式、观察者模式等
    3. 进行一些单元测试
    4. 代码复用,提出可复用的函数及组件
    5. 错误处理,合理处理异常和错误情况
    6. 使用代码质量检查工具来检查修复代码规范问题,例如ESLint

    ⭐关于变量提升和函数提升的问题

    var c = 1;
    function c(c) {
        console.log(c)
    }
    c(2)
    //函数作⽤域:局部作⽤域
    var a = 1;
    function b() {
     a = 10;
     return;
     //a函数声明,提前变量a,将a认为是函数b作⽤域的变量,具有局部效果
     function a(){}
    }b();
    console.log(a); // 1
    var m= 1, j = k = 0; 
    function add(n) { 
        return n = n+1; 
    } 
    y = add(m); 
    function add(n) { 
        return n = n + 3; 
    } 
    z = add(m);  

    说一下Vue2响应式的实现

    1. 创建 Vue 实例时,会调用 new Vue(),其中会通过 observe 函数对 data 数据进行观测。
    2. 在 observe 函数中,会使用 Object.defineProperty 递归地遍历所有属性,并为每个属性创建对应的 getter 和 setter。
    3. 在属性的 getter 中,会进行依赖收集。首先,通过闭包引用一个全局变量 Dep.target,该变量保存当前正在计算的 Watcher 实例。然后,在 getter 中调用 dep.depend() 方法,将当前的 Watcher 添加到依赖集合中。
    4. 在属性的 setter 中,当属性的值发生改变时,会触发 setter。在 setter 中,会对新值进行响应式处理(递归调用 observe),并通知相关的依赖进行更新。这一过程通过调用 dep.notify() 实现,dep.notify() 会遍历依赖集合,调用每个依赖的 update 方法,触发相应的更新操作。
    5. 在模板编译过程中,解析模板中的指令表达式,对每个指令表达式生成对应的 Watcher 实例。Watcher 实例内部会调用属性的 getter 方法,在 getter 中触发依赖收集的过程,将当前 Watcher 添加到依赖集合中。
    6. 当属性的值发生变化时,会触发相应的更新操作。依赖收集过程中收集到的 Watcher 实例会在更新阶段被遍历,并调用其 update 方法来更新视图。

    ⭐关于跨域

    跨域请求是指在浏览器中,当请求的源地址与请求地址的协议、域名、端口号不一致时,会被浏览器的同源策略所限制,这是为了保护用户的信息安全。

    1. JSONP(JSON with Padding):JSONP通过动态创建
    2. CORS(Cross-Origin Resource Sharing):CORS是一种现代的跨域解决方案,通过在服务器端设置响应头部,允许客户端跨域访问资源。在前端开发中,可以通过设置服务器的响应头部字段Access-Control-Allow-Origin来允许特定的源进行跨域请求。
    3. 代理服务器(Proxy Server):通过在自己的服务器上设置一个代理服务器,将跨域请求转发到目标服务器,并将目标服务器的响应返回给前端。这种方法需要对服务器进行配置,适用于无法直接修改目标服务器响应头部的情况。
    4. WebSocket:WebSocket是一种全双工通信协议,可以在同一域名下使用不同的端口进行跨域通信。通过建立WebSocket连接,可以实现实时通信和跨域数据传输。

    ⭐请解释一下什么是响应式设计(Responsive Design),以及在开发响应式网站时需要考虑哪些方面,并列举常用方法

    响应式设计(Responsive Design)是一种网页设计和开发的方法,旨在使网站能够适应不同设备、屏幕尺寸和浏览器窗口大小,以提供更好的用户体验。响应式设计通过使用灵活的布局、弹性的图像和媒体查询等技术,让网页能够根据用户设备的特性进行自适应和优化。

    在开发响应式网站时,需要考虑以下几个方面:

    1. 弹性布局:使用相对单位(如百分比、em、rem)而不是固定像素来定义元素的尺寸和布局。这样可以让网页的元素根据屏幕尺寸的变化而自动调整大小和位置。
    2. 媒体查询:使用CSS的媒体查询功能来检测设备的特性(如屏幕宽度、触摸支持等),并根据不同的条件应用不同的样式规则。这样可以根据不同设备的屏幕大小和特性来调整网页的布局和样式。
    3. 图片优化:针对不同设备加载适当尺寸和分辨率的图片,以减少加载时间和带宽占用。可以使用响应式图片技术,如<img srcset>和<picture>元素来提供多个不同尺寸的图片,并根据设备的屏幕密度和大小选择合适的图片加载。
    4. 触摸友好性:优化网页在触摸设备上的交互和操作体验,比如增大可点击区域、使用合适的手势和触摸事件等。
    5. 导航菜单:设计合适的导航菜单,以便在小屏幕设备上能够轻松导航和访问各个页面。
    6. 测试和调试:在不同设备、不同浏览器和不同分辨率下进行测试和调试,以确保网页在各种情况下都能正常显示和运行。
    7. 性能优化:考虑网页加载速度和性能,减少不必要的资源请求和加载,使用压缩和缓存等技术来提高网页的响应速度。

    以下是一些常用的技术和方法来实现响应式设计:

    1. 媒体查询(Media Queries):使用CSS的媒体查询功能,根据设备的特性(如屏幕宽度、设备类型等)应用不同的样式。通过设置不同的CSS规则,可以根据设备的宽度、高度、方向等特性来改变布局和样式。
    2. 相对单位(例如em和rem):相对单位可以根据父元素或根元素的大小进行调整。em单位相对于父元素的字体大小,rem单位相对于根元素(通常是html元素)的字体大小。使用这些相对单位可以根据设备的屏幕大小自适应调整元素的大小。
    3. 百分比布局:使用百分比作为元素的宽度、高度等属性值,以便根据容器的大小来调整元素的尺寸。
    4. 视口单位(例如vw、vh):视口单位是相对于视口宽度和高度的单位。vw表示视口宽度的百分比,vh表示视口高度的百分比。使用视口单位可以根据屏幕的实际尺寸来调整元素的大小。
    5. 弹性盒布局(Flexbox):弹性盒布局是一种灵活的布局方式,可以使容器中的元素在不同尺寸的屏幕上自动调整位置和大小。
    6. 栅格布局(Grid):网格布局是一种二维布局系统,可以将页面划分为行和列,并指定元素在网格中的位置。通过设置不同的网格模板和位置属性,可以实现灵活的响应式布局。
    7. 响应式图片:使用srcset和sizes属性来提供不同尺寸的图片,以适应不同设备的显示需求。
    8. 断点(Breakpoints):根据不同设备的屏幕宽度和布局需求,设置断点来改变页面的布局和样式。

    ⭐什么是单页面应用(SPA)?它与传统多页面应用相比有什么优势和劣势?

    单页面应用(Single Page Application,SPA)是一种Web应用程序的架构模式,它在加载初始HTML页面后,通过JavaScript动态地更新页面的内容,而不需要每次页面切换时重新加载整个页面。

    与传统的多页面应用相比,SPA有以下优势:

    1. 更好的用户体验:由于SPA使用了异步加载和局部更新的方式,用户在浏览网站时可以享受到更流畅、快速的交互体验,减少了页面刷新的延迟。
    2. 较少的网络请求:SPA通常在初始加载时会下载所有所需的JavaScript、CSS和其他静态资源,之后只需要通过API请求数据。相比多页面应用,SPA减少了对服务器的频繁请求,提高了性能。
    3. 良好的代码组织:SPA使用组件化的方式组织代码,将页面拆分为多个可重用的组件。这样可以提高代码的复用性、可维护性和可测试性,使开发工作更加高效。

    然而,SPA也存在一些劣势:

    1. 初始加载较慢:由于SPA需要在初始加载时下载所有所需资源,首次加载时间可能会较长。这对于一些网络条件较差的用户来说可能是一个问题。
    2. 对SEO不友好:传统的搜索引擎爬虫通常会根据HTML页面的内容进行索引,而SPA的内容是通过JavaScript动态生成的,对搜索引擎的爬取和索引不太友好。虽然有一些技术可以解决这个问题(如服务器端渲染),但相对复杂。
    3. 依赖于JavaScript:由于SPA大量依赖于JavaScript来处理页面逻辑和数据交互,因此如果用户禁用了JavaScript,SPA可能无法正常运行。

    ⭐JS垃圾回收机制

    1. 项目中,如果存在大量不被释放的内存(堆/栈/上下文),页面性能会变得很慢。当某些代码操作不能被合理释放,就会造成内存泄漏。我们尽可能减少使用闭包,因为它会消耗内存。
    2. 浏览器垃圾回收机制/内存回收机制:
    3. 浏览器的Javascript具有自动垃圾回收机制(GC:Garbage Collecation),垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。
    4. 标记清除:在js中,最常用的垃圾回收机制是标记清除:浏览器会为内存中所有的变量添加标记,然后再遍历上下文,为其中所有变量及被变量引用的变量清除标记,这样剩下被标记的就是待回收对象。 谷歌浏览器:“查找引用”,浏览器不定时去查找当前内存的引用,如果没有被占用了,浏览器会回收它;如果被占用,就不能回收。 IE浏览器:“引用计数法”,当前内存被占用一次,计数累加1次,移除占用就减1,减到0时,浏览器就回收它。
    5. 优化手段:内存优化 ; 手动释放:取消内存的占用即可。
    6. (1)堆内存:fn = null 【null:空指针对象】
    7. (2)栈内存:把上下文中,被外部占用的堆的占用取消即可。
    8. (3)防止出现隐藏类,在一开始调用构造函数生成实例时就传入需要的变量,防止动态添加和删除属性
    9. (4)静态分配和对象池
    10. 内存泄漏
    11. 在 JS 中,常见的内存泄露主要有 4 种,全局变量、闭包、DOM 元素的引用、定时器

    ⭐JS 中 this 的五种情况

    1. 作为普通函数执行时,this指向window。
    2. 当函数作为对象的方法被调用时,this就会指向该对象。
    3. 构造器调用,this指向返回的这个对象。
    4. 箭头函数捕获的是最近一层非箭头函数作用域的this值,不会绑定到字面量复制的对象上。
    5. 基于Function.prototype上的 apply 、 call 和 bind调用模式,这三个方法都可以显示的指定调用函数的 this 指向。apply接收参数的是数组,call接受参数列表,bind方法通过传入一个对象,返回一个this绑定了传入对象的新函数。这个函数的 this指向除了使用new时会被改变,其他情况下都不会改变。若为空默认是指向全局对象window。

    ⭐原型 && 原型链

    原型关系:

    • 每个 class都有显示原型 prototype
    • 每个实例都有隐式原型 __ proto__
    • 实例的_ proto_指向对应 class 的 prototype

    原型: 在 JS 中,每当定义一个对象(函数也是对象)时,对象中都会包含一些预定义的属性。其中每个函数对象都有一个prototype 属性,这个属性指向函数的原型对象。

    原型链:函数的原型对象上的constructor默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针_proto_ ,该指针是指向上一层的原型对象,而上一层的原型对象的结构依然类似。因此可以利用_proto_ 一直指向Object的原型对象上,而Object原型对象用Object.prototype.__ proto__ = null表示原型链顶端。如此形成了js的原型链继承。同时所有的js对象都有Object的基本方法

    特点: JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。

    ⭐new运算符的实现机制

    1. 首先创建了一个新的空对象
    2. 设置原型,将对象的原型设置为函数的prototype对象。
    3. 让函数的this指向这个对象,执行构造函数的代码(为这个新对象添加属性)
    4. 判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。

    ⭐请解释一下什么是事件委托(或称事件代理),以及它在前端开发中的作用是什么?

    事件委托(或称事件代理)是一种在前端开发中常用的技术,它利用了事件冒泡机制,将事件处理程序绑定到一个父元素上,而不是直接绑定到每个子元素上。当事件触发时,事件会经过冒泡阶段依次向上传播至父元素,父元素可以根据事件的目标元素来判断应该执行哪个事件处理函数。

    事件委托的作用主要有以下几点:

    1. 减少事件处理程序的数量:通过将事件处理程序绑定到父元素上,可以避免为每个子元素都绑定事件处理程序,减少内存消耗。
    2. 动态绑定事件:对于通过 JavaScript 动态添加的子元素,使用事件委托可以自动为它们绑定事件处理程序,无需额外的操作。
    3. 简化代码结构:使用事件委托可以将事件处理程序集中管理,使代码更加简洁、可读性更高。

    举个例子,假设有一个列表的父元素,里面包含了多个子元素(项),我们需要为每个子元素绑定点击事件,实现点击子元素时改变其样式。使用事件委托可以这样处理:

    // 获取父元素
    const parentElement = document.getElementById('parent');
    ​
    // 绑定点击事件到父元素
    parentElement.addEventListener('click', function(event) {
      // 判断事件目标是否是子元素(项)
      if (event.target && event.target.nodeName === 'LI') {
        // 执行事件处理逻辑,例如改变样式
        event.target.classList.toggle('active');
      }
    });

    通过将点击事件绑定到父元素上,无论新增或删除了子元素,甚至是动态生成的子元素,都会自动触发相应的事件处理逻辑,大大简化了代码的管理和维护。

    ⭐说说你常用的ES6新特性

    • 块级作用域(Block Scope): 使用 let 和 const 关键字声明的变量具有块级作用域,即只在当前代码块中有效。相比于 var 声明的变量具有函数作用域而言,这种方式更加灵活和可控。
    • 箭头函数(Arrow Function): 箭头函数通过 => 符号定义,可以简化函数的书写。它具有以下特点:
      • 自动绑定上下文:箭头函数不会创建自己的 this,而是继承外层作用域的 this。
      • 省略 return 关键字:当函数体只有一条返回语句时,可以省略 return 关键字。
      • 更简洁的语法:当只有一个参数时,可以省略括号;当函数体为空时,可以使用 () => {} 表示。
    • 解构赋值(Destructuring Assignment): 解构赋值允许从数组或对象中提取值并赋给变量。例如,可以通过以下方式提取数组元素:
     Codeconst [a, b] = [1, 2];

    也可以通过以下方式提取对象属性:

     Codeconst { name, age } = { name: 'Alice', age: 18 };
    • 模板字符串(Template Strings): 模板字符串使用反引号 `` 包裹,并支持在字符串中插入变量或表达式。例如:
     Codeconst name = 'Alice';
    console.log(`Hello, ${name}!`);
    • 扩展运算符(Spread Operator): 扩展运算符用于展开可迭代对象(如数组和字符串),将其元素逐个展开,例如:
     Codeconst arr = [1, 2, 3];
    console.log(...arr); // 输出:1 2 3
    • 类(Class): ES6 引入了类语法,可以使用 class 关键字定义一个类。类可以包含构造函数、实例方法、静态方法等。例如:
     Codeclass Person {
      constructor(name) {
        this.name = name;
      }
    ​
      sayHello() {
        console.log(`Hello, my name is ${this.name}!`);
      }
    ​
      static getInfo() {
        console.log('This is a person class.');
      }
    }
    ​
    const person = new Person('Alice');
    person.sayHello();     // 输出:Hello, my name is Alice!
    Person.getInfo();      // 输出:This is a person class.
    • 简化对象字面量(Object Literal Shorthand): 当定义对象字面量时,如果属性名和变量名相同,可以直接省略写属性值。例如:
     Codeconst name = 'Alice';
    const age = 18;
    ​
    const person = { name, age };
    console.log(person);   // 输出:{ name: 'Alice', age: 18 }
    • 模块化(Module): ES6 引入了模块化概念,可以将代码拆分为多个模块,每个模块有自己的作用域,并通过 importexport 关键字进行模块之间的导入和导出。例如:
    // moduleA.js
    export function greet(name) {
      console.log(`Hello, ${name}!`);
    }
    ​
    // moduleB.js
    import { greet } from './moduleA.js';
    greet('Alice');       // 输出:Hello, Alice!
    • Promise: Promise 是用于处理异步操作的对象,避免了传统的回调地狱。它表示一个异步操作的最终完成或失败,并可以链式调用 thencatchfinally 方法处理结果。例如:
    function fetchData() {
      return new Promise((resolve, reject) => {
        // 异步操作...
        if (/* 异步操作成功 */) {
          resolve('Data fetched successfully!');
        } else {
          reject('Failed to fetch data!');
        }
      });
    }
    ​
    fetchData()
      .then(data => console.log(data))        // 成功时执行
      .catch(error => console.error(error))   // 失败时执行
      .finally(() => console.log('Done'));    // 不论成功与否都执行
    • 数组方法(Array Methods): ES6 提供了许多方便的数组方法来处理和遍历数组,如 forEachmapfilterreduce 等。这些方法提供了更简洁、可读性更高的方式来操作数组。例如:
    javascript Codeconst numbers = [1, 2, 3, 4];
    ​
    numbers.forEach(num => console.log(num));                 // 遍历输出每个元素
    const doubledNumbers = numbers.map(num => num * 2);       // 对每个元素进行操作并返回新数组
    const evenNumbers = numbers.filter(num => num % 2 === 0); // 过滤出符合条件的元素
    const sum = numbers.reduce((acc, num) => acc + num, 0);    // 对数组进行累加

    说一说apply、call、bind

    apply、call 和 bind 都是 JavaScript 中用于改变函数执行上下文(this)的方法,它们的区别如下:

    1. apply:
    2. 语法:function.apply(thisArg, [argsArray])
    3. 参数:需要指定函数执行时的上下文对象 thisArg 和可选的参数数组 argsArray。
    4. 功能:立即调用函数,并改变函数内部的 this 指向 thisArg,同时可以传递一个数组或类数组对象作为参数(通过 arguments 对象传递参数也可以)。
    5. 示例:fn.apply(obj, [arg1, arg2])
    6. call:
    7. 语法:function.call(thisArg, arg1, arg2, ...)
    8. 参数:需要指定函数执行时的上下文对象 thisArg 和可选的多个参数 arg1, arg2, ...。
    9. 功能:立即调用函数,并改变函数内部的 this 指向 thisArg,同时可以传递多个参数(通过逗号分隔)。
    10. 示例:fn.call(obj, arg1, arg2)
    11. bind:
    12. 语法:function.bind(thisArg, arg1, arg2, ...)
    13. 参数:需要指定函数执行时的上下文对象 thisArg 和可选的多个参数 arg1, arg2, ...。
    14. 功能:创建一个新的函数,函数内部的 this 指向 thisArg,并且绑定了指定的参数。不会立即执行函数,而是返回一个新函数,之后可以再次调用。
    15. 示例:var boundFn = fn.bind(obj, arg1, arg2)

    总结:

    • apply 和 call 可以立即调用函数并改变函数内部的 this 指向,区别在于参数传递方式不同,apply 接受参数数组,而 call 接受多个参数。
    • bind 不会立即执行函数,而是返回一个新函数,函数内部的 this 指向绑定的对象,并且可以预先绑定一些参数。
    • 这三种方法都可以实现改变函数执行上下文的目的,根据具体需求选择合适的方法。

    说一下装箱和拆箱

    在 JavaScript 中,基本数据类型(Primitive Types)和引用数据类型(Reference Types)在处理和操作时有所不同。当我们对基本数据类型值进行属性访问或方法调用时,JavaScript 会将基本数据类型自动转换为对应的包装对象,这个过程称为装箱(Boxing)。

    下面以数字类型(Number)为例,简要说明基本数据类型装箱的过程:

    1. 创建包装对象:当我们使用属性或方法来访问数字类型的值时,JavaScript 在后台会创建一个临时的包装对象(Wrapper Object)。对于数字类型,创建的包装对象是 Number 对象。
    2. 存储值:创建的包装对象将会存储对应的基本数据类型值。例如,对于数字类型的装箱过程,包装对象中会存储相应的数字值。
    3. 访问属性或方法:一旦装箱完成,我们可以通过包装对象来访问属性和方法。这些属性和方法是与包装对象相关联的。例如,通过.toFixed()方法调用来格式化一个数字。
    4. 自动拆箱:当我们使用包装对象进行操作后,如果需要将结果赋值给一个变量,JavaScript 会自动进行拆箱(Unboxing)操作,将包装对象转换回基本数据类型的值。

    装箱的过程是自动发生的,JavaScript 引擎会在需要时自动执行装箱和拆箱操作,使得开发者能够像操作引用类型一样操作基本类型。而这种装箱和拆箱的过程在后台进行,对于开发者来说是透明的。

    需要注意的是,由于装箱过程涉及到对象的创建和数据拷贝,相比于直接操作基本类型,使用包装对象会带来额外的开销。因此,在不必要的情况下,最好直接操作基本类型,而不是通过装箱和拆箱操作。

    ⭐最大安全整数

    JavaScript中的最大安全整数是 9007199254740991。它可以使用 Number.MAX_SAFE_INTEGER 常量来表示。这个值是由 JavaScript 中的双精度浮点数表示法决定的,在进行数值运算时不会丢失精度。

    超过最大安全整数的数值会导致精度丢失,可能会引发意外的结果。如果需要处理超过最大安全整数范围的大整数,可以使用第三方的大数库或者 BigInt 类型(ES2020 新增)来处理。BigInt 类型可以表示任意精度的整数,但是在进行数值计算时需要特别注意性能和兼容性的问题。

    ⭐commonjs和es模块有什么区别?

    CommonJS(简称CJS)和ES Modules(简称ESM)是两种不同的模块化规范,有以下不同:

    1. 语法差异:
    2. CommonJS:使用 require() 导入模块,使用 module.exports={xxx} 或 exports.xxx=xxx 导出模块。
    3. ESM:使用 import 导入模块,使用 export 导出模块。
    4. 对于基本数据类型,ESM导入的是值的引用,CJS导入的是值的拷贝,故ESM中引入的值是常量,不允许直接修改(对象修改或新增属性除外)
    5. 补充:如果导入的是对象,那么变量中传递来的就是对象的地址值,地址值进行拷贝后通过它访问的还是同一个对象,所以这里对象导入的可以理解为都是引用
    6. 作为整体导入时(即import * as mod from xxx),这时导入的对象第一级是只读的,如果尝试对第一层属性进行修改,就会报错
    7. CJS是运行时同步加载(动态),而ESM是编译时异步加载(静态)
    8. CJS适用于服务端开发,ESM适用于浏览器端

    补充:相同点——CJS和ESM导入时,都会将整个模块的代码执行一遍,然后缓存执行的结果

    ⭐commonJS中module.exports和exports有什么区别

    每个node.js文件在执行时都会隐式的、自动的创造一个module对象,同时,module对象会创建一个名叫exports,初始值为{}的属性:

    var module = {
        exports:{}
    }

    为了可以更好的导出对应功能模块里的内容,它会又隐式的创建一个变量exports:

    //隐式的创建了一个变量exports
    var exports = module.exports
    ​
    //此时exports和module.exports 引用的是同一个对象
    console.log(exports === modules.exports) //true  

    所以我们通过exports.xxx = xxx的方式进行导出,它最终也是被加到了modules.exports对象中

    最终导出的是modules.exports对象,这就意味着如果我们将exports的指向改变,那么通过exports.xxx = xxx添加的导出就不会再添加到modules.exports对象中,xxx也就不会被导出

    ⭐如何理解JS中的异步

    JS是一门单线程语言,因为它运行在浏览器的渲染主线程中(当遇到JS代码时,渲染主线程会将控制权交给js引擎来处理),而渲染主线程只有一个。

    而渲染主线程承担着诸多工作,渲染页面,执行js都在其中执行。

    如果用同步的方式,极有可能导致主线程产生阻塞,从而导致消息队列中很多任务无法及时执行。

    所以浏览器就采取了异步措施,当某些异步任务触发时,如定时器、网络请求、事件监听器等,主线程就会将任务交给其他线程去处理,自身立即结束任务执行,转而执行后续任务,等到异步任务执行完毕,将事先传递的回调函数包装成任务,加入到对应队列(延时队列、微任务队列、交互队列)的末尾排队,等待主线程调度执行。

    在这种异步模式下,浏览器就不会发生阻塞,保证了单线程的流畅运行。

    ⭐说一说事件循环

    事件循环又叫消息循环,是浏览器渲染主线程的工作方式。

    在Chrome的底层实现中,它开启了一个for的死循环,每次循环从消息队列中取出第一个任务执行,而其他线程只需要在合适的时机将任务放到消息队列中。

    以前我们会将消息队列简单分为宏任务队列和微任务队列,现在随着浏览器环境愈发复杂,浏览器采用了更加灵活多变的处理方式。

    根据W3C官方解释,每个任务都有不同的类型,同类型的任务须在同一个队列。不同的队列有不同的优先级(例如交互队列优先级大于延时队列),在一次事件循环中,由浏览器自行决定取哪一个队列的任务,但浏览器必须有一个微任务队列,且其优先级是最高的,必须优先调度执行。

    ⭐JS中的计时器能做到精确计时吗?

    不可以

    1. 计算机中采用晶体振荡器来计时,虽然比较准确,但对比原子钟,精确度还是不足,且会受温度电压等因素影响,在计算机中通常会使用网络时间协议来进行校准。而js计时是调用操作系统中的计时函数,也就携带了些许偏差。
    2. 按照W3C标准,当浏览器中使用计时器,其嵌套层级超过五层时,之后的计时器就默认会有一个4ms的延迟,这4ms也会引起时间的偏差
    3. 而最主要的因素还是事件循环中,如果渲染主线程上有任务正在执行,就会推迟计时器的执行

    ⭐如何判断一个对象是否为空

    如果使用常规的Object.getOwnPropertyNames()来判断,虽然可以将一般的不可枚举类型属性也判断出来,但无法判断继承的属性以及Symbol类型值定义的属性。所以我们需要使用Reflect.ownKeys()来进行转换,这样通过它返回的数组长度就能精准判断出对象是否为空。

    ⭐重写一下String.prototype.trim

    1、正则

    String.prototype.trim = function() {
        return this.replace(/(^\s*)|(\s*$)/g, "")
    }

    2、双指针法

    .精灵图(CSS Sprites)的优点和缺点

    精灵图是一种网页图片应用处理方式。就是把网页中很多小背景图片整合到一张图片文件中,再利用CSS的“background-image”,“background-repeat”,“background-position”的组合进行背景图显示及定位,达到显示某一部分背景图的效果。

    精灵图的优点:

    1、减少图片的体积,因为每个图片都有一个头部信息,把多个图片放到一个图片里,就会共用同一个头部信息,从而减少了字节数。

    2、减少了网页的http请求次数,从而加快了网页加载速度,提高用户体验。

    3、解决了网页设计师在图片命名上的困扰,只需对一张集合的图片上命名就可以了,不需要对每一个小元素进行命名,从而提高了网页的制作效率。

    4、更换风格方便,只需要在一张或少张图片上修改图片的颜色或样式,整个网页的风格就可以改变。维护起来更加方便。

    精灵图的缺点:

    1.在图片合并的时候,你要把多张图片有序的合理的合并成一张图片,还要留好足够的空间,防止板块内出现不必要的背景;这些还好,最痛苦的是在宽屏,高分辨率的屏幕下的自适应页面,你的图片如果不够宽,很容易出现背景断裂;

      2.在开发的时候比较麻烦,你要通过photoshop或其他工具测量计算每一个背景单元的精确位置,这是针线活,没什么难度,但是很繁琐;

    3.在维护的时候比较麻烦,如果页面背景有少许改动,一般就要改这张合并的图片,无需改的地方最好不要动,这样避免改动更多的css,如果在原来的地方放不下,又只能(最好)往下加图片,这样图片的字节就增加了,还要改动css。

    4.精灵图不能随意改变大小和颜色。精灵图改变大小会失真模糊,降低用户体验,css3新属性可以改变精灵图颜色,但是比较麻烦,并且新属性有兼容问题。现在一般都是用web字体(图标字体)来代替精灵图。

    2.什么是vue全家桶

    Vue + vue-router + vuex + axios + es6 + sass

    3.doctype是什么,网页常见doctype及特点

     DOCTYPE是document type(文档类型)的简写,在web设计中用来说明你用的XHTML或者HTML是什么版本。
     常见类型:
    1.过渡型(Transitional):要求非常宽松,它允许你继续使用HTML4.01的标识(但是要符合xhtml的写法),完整代码如下:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    2.严格型(Strict):要求非常严格,你不能使用任何表现层的标识和属性,例如<br>,完整代码如下:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
     
    3.框架型(Frameset):专门针对框架页面设计使用,如果你的页面中包含有框架(frameset),完整代码如下:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
     

    3.什么是web语义化,有什么好处

    Web语义化简单来说就是为了让页面对人和机器更友好,让人和机器更容易理解页面内容。

    1.对机器来说,语义化能让机器更精确的知道页面中的重点和关键点。让机器更容易为人筛选出想要的部分。

    2.对开发人员来说,更容开发和易维护页面。根据页面中的标签名和类名就能知道哪个部分放置了哪些内容,从而提高了开发和维护的效率。

    4.你知道的HTTP 请求方式有几种

    HTTPRequestMethod共计17种

    1.GET 请求指定的页面信息,并返回实体主体。

    2.HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头

    3.POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。

    4.PUT 从客户端向服务器传送的数据取代指定的文档的内容。

    5.DELETE 请求服务器删除指定的页面。

    6.CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

    7.OPTIONS 允许客户端查看服务器的性能。

    8.TRACE 回显服务器收到的请求,主要用于测试或诊断。

    9.PATCH 实体中包含一个表,表中说明与该URI所表示的原内容的区别。

    10.MOVE 请求服务器将指定的页面移至另一个网络地址。

    11.COPY 请求服务器将指定的页面拷贝至另一个网络地址。

    12.LINK 请求服务器建立链接关系。

    13.UNLINK 断开链接关系。

    14.WRAPPED 允许客户端发送经过封装的请求。

    15.LOCK 允许用户锁定资源,比如可以再编辑某个资源时将其锁定,以防别人同时对其进行编辑。

    16.MKCOL 允许用户创建资源

    17.Extension-mothed 在不改动协议的前提下,可增加另外的方法。

    5.css选择器有哪些

    1.简单选择器

    通配符选择器 *

    id选择器 #id

    class选择器 .class

    标签选择器 element

    2.复合选择器

    后代选择器 element element

    子代选择器 element>element

    兄弟选择器 element+element

    并列选择器 element,element

    伪类选择器 :link

    属性选择器 [attribute]

    6.css hack原理及常见hack

    原理:CSS hack是一种类似作弊的手段,以欺骗浏览器的方式达到兼容的目的,是用浏览器的兼容性差异来解决浏览器的兼容性问题。

    常见hack:

    1.利用浏览器对相同代码的解析和支持的不同实现的hack

    比如div{ _width:80px },在ie6中能识别并解析带下划线的属性,但是ie7及以上版本中识别不了。

    2.以Firefox或Webkit特有的扩展样式实现的hack

    Firefox支持以-moz-开头的属性

    Webkit内核支持以-webkit-开头的属性

    3.以IE特有的条件注释为基础的hack

    <!--[ifIE8]> <style type="text/css"> #test{ color:red; } </style><![endif]-->

    比如这个样式,可以在ie8中生效,但是其他浏览器则不会生效

    7.css中有哪些常见的继承属性

    • 文本

    1. color(颜色,a元素除外)

    2. direction(方向)

    3. font(字体)

    4. font-family(字体系列)

    5. font-size(字体大小)

    6. font-style(用于设置斜体)

    7. font-variant(用于设置小型大写字母)

    8. font-weight(用于设置粗体)

    9. letter-spacing(字母间距)

    10. line-height(行高)

    11. text-align(用于设置对齐方式)

    12. text-indent(用于设置首航缩进)

    13. text-transform(用于修改大小写)

    14. visibility(可见性)

    15. white-space(用于指定如何处理空格)

    16. word-spacing(字间距)

    • 列表

    1. list-style(列表样式)

    2. list-style-image(用于为列表指定定制的标记)

    3. list-style-position(用于确定列表标记的位置)

    4. list-style-type(用于设置列表的标记)

    • 表格

    1. border-collapse(用于控制表格相邻单元格的边框是否合并为单一边框)

    2. border-spacing(用于指定表格边框之间的空隙大小)

    3. caption-side(用于设置表格标题的位置)

    4. empty-cells(用于设置是否显示表格中的空单元格)

    • 页面设置(对于印刷物)

    1. orphans(用于设置当元素内部发生分页时在页面底部需要保留的最少行数)

    2. page-break-inside(用于设置元素内部的分页方式)

    3. widows(用于设置当元素内部发生分也是在页面顶部需要保留的最少行数)

    • 其他

    1. cursor(鼠标指针)

    2. quotes(用于指定引号样式)

    8.sessionStorage,localStorage,cookie区别

    ·共同点:都是保存在浏览器端,且同源的。

    ·区别:cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递;cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。存储大小限制也不同,cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。

    ·而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。

    ·数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。

    ·作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。WebStorage 支持事件通知机制,可以将数据更新的通知发送给监听者。WebStorage的 api 接口使用更方便。

    9.JavaScript有哪些数据类型

    原始类型有6种 object,number,string,boolean,null,undefined

    10.输出今天是星期几

    var str = "今天是星期" + "日一二三四五六".charAt(new Date().getDay());alert(str);

    11.如何判断一个变量是否为数组

    arr.constructor === Array 为true说明是数组类型

    arr instanceof Array 为true则是数组类型

    Object.prototype.toString.call(arr) === '[object Array]'; 为true为数组类型

    Array.isArray(arr) 为true则为数组类型

    12.实现一个js深度克隆函数

     //深度克隆
    function deepClone(obj){
    var result={},oClass=isClass(obj);
    for(key in obj){
     var copy=obj[key];
     if(isClass(copy)=="Object"){
     result[key]=arguments.callee(copy);
     }else if(isClass(copy)=="Array"){
     result[key]=arguments.callee(copy);
     }else{
     result[key]=obj[key];
     }
     }
     return result;
    }
    function isClass(o){
     if(o===null) return "Null";
     if(o===undefined) return "Undefined";
     return Object.prototype.toString.call(o).slice(8,-1);
    }
    //克隆一个数组
    var arr=["a","b","c"];
    var oNew=deepClone(arr);
    console.log(oNew);//Object {0: "a", 1: "b", 2: "c"}

    13.给定一个日期,页面打印倒计时

    <!DOCTYPE html>

    <html>

    <head>

    <meta charset="utf-8">

    <title>倒计时</title>

    </head>

    <body>

    <input type="text" name="time" id="time" value="2017-09-22" />

    <input type="button" name="okbtn" id="okbtn" value="确认" />

    <br />

    <p id="textp">这里显示倒计时</p>

    </body>

    <script type="text/javascript">

    var okbtn=document.getElementById("okbtn");

    textp=document.getElementById("textp");

    okbtn.onclick=function(){

    var time=document.getElementById("time");

    var timevalue=time.value;

    //通过正则表达式确认输入格式是否正确

    var patt=/^(\d{1,4})(-)(\d{1,2})(\d{1,2})$/;

    if(patt.test(timevalue)==false){

    //如果不正确

    textp.innerHTML="输入格式不满足YYYY-MM-DD";

    return false;

    }else{

    textp.innerHTML="这里显示倒计时";

    }

    //获取输入的年月日

    var timearray=timevalue.split("-");

    //ShowLeftTime(timearray[0],timearray[1],timearray[2]);

    setInterval(function(){ShowLeftTime(timearray[0],timearray[1],timearray[2]);},1000);

    }

    function ShowLeftTime(year,month,date){

    //得出剩余时间

    var now=new Date();

    var endDate=new Date(year,month-1,date);

    var leftTime=endDate.getTime()-now.getTime();

    var leftsecond=parseInt(leftTime/1000);

    var day=Math.floor(leftsecond/(60*60*24));

    var hour=Math.floor((leftsecond-day*24*60*60)/3600);

    var minute=Math.floor((leftsecond-day*24*60*60-hour*3600)/60);

    var second=Math.floor(leftsecond-day*60*60*24-hour*60*60-minute*60);

    //显示剩余时间

    textp.innerHTML="距离"+year+"年"+month+"月"+date+"日"

    +"还有"+day+"天"+hour+"小时"+minute+"分"+second+"秒";

    }

    </script>

    </html>

    14.数组去重

    //利用indexOf

    var aa=[1,3,5,4,3,3,1,4]

    function arr(arr) {

    var result=[]

    for(var i=0; i<arr.length; i++){

    if(result.indexOf(arr[i])==-1){

    result.push(arr[i])

    }

    }

    console.log(result)

    }

    arr(aa)

    //循环嵌套

    function fn(arr) {

    var result = [];

    var flag;

    for (var i = 0, len = arr.length; i < len; i++) {

    flag = false;

    for (var j = 0, len = result.length; j < len; j++) {

    if (arr[i] == result[j]) {

    flag = true;

    break;

    }

    }

    if (!flag) {

    result.push(arr[i]);

    }

    }

    return result;

    }

    15.求数组中最大值,最小值和重复次数最多的数值

    var arr = [1,2,2,3,5,5,5,6];

    var max = arr[0]; // 数组中的最大值

    var min = arr[0]; // 数组中的最小值

    var mostCount; // 数组中出现次数最多的元素

    var temp = {};

    var num = 0;

    for(var i=arr.length-1; i>=0; i--){

    if(max<arr[i]){ // 得到最大值

    max = arr[i]

    }

    if(min>arr[i]){ // 得到最小值

    min = arr[i]

    }

    if(temp[arr[i]]){ // 得到元素出现的次数,并组成obj

    temp[arr[i]] = tempObj[arr[i]]+1;

    }else{

    temp[arr[i]] = 1;

    }

    }

    for(var key in temp){ // 从对象中得到数组中出现最多的元素

    if(!mostCount){

    mostCount = key;

    }else if(temp[mostCount]<temp[key]){

    mostCount = key;

    }

    }

    console.log("最大值为"+max+"; 最小值为"+minVal+"; 次数最多的为"+mostCount);

    17.请概括什么情况下打印控制台会提示undefined

    1.当打印的变量声明未赋值时

    2.当打印的执行函数没有返回值时

    18.原生实现数组快速排序

    var times=0;

    var quickSort=function(arr){

    //如果数组长度小于等于1无需判断直接返回即可

    if(arr.length<=1){

    return arr;

    }

    var midIndex=Math.floor(arr.length/2);//取基准点

    var midIndexVal=arr.splice(midIndex,1);//取基准点的值,splice(index,1)函数可以返回数组中被删除的那个数arr[index+1]

    var left=[];//存放比基准点小的数组

    var right=[];//存放比基准点大的数组

    //遍历数组,进行判断分配

    for(var i=0;i<arr.length;i++){

    if(arr[i]<midIndexVal){

    left.push(arr[i]);//比基准点小的放在左边数组

    }

    else{

    right.push(arr[i]);//比基准点大的放在右边数组

    }

    console.log("第"+(++times)+"次排序后:"+arr);

    }

    //递归执行以上操作,对左右两个数组进行操作,直到数组长度为<=1;

    return quickSort(left).concat(midIndexVal,quickSort(right));

    };

    console.log(quickSort(arr));

    19.原生实现二分查找法

    var arr = [5,0,-56,90,12];

    var flag = false;//标志位进行优化,数组本来就是有序序列的话,无需再排序

    //先进行大的排序

    for(var i=0;i<arr.length-1;i++){

    //小的排序

    for(var j=0;j<arr.length-1-i;j++){

    //比较

    if(arr[j]>arr[j+1]){

    //交换

    var temp = arr[j];

    arr[j] = arr[j+1];

    arr[j+1] = temp;

    flag = true;

    }

    }

    //此部分为优化,已排序的话,无需再次排序

    if(flag){

    flag=false;

    }else{

    break;//已排序,无需交换

    }

    }

    //输出新数组

    for(var i=0;i<arr.length;i++){

    document.write(arr[i]+' ');

    }

    20.正则表达式,清楚字符串前后空格

    var str=" hello ";

    str=str.replace(/^s*|s*$/g,'');

    alert(str);

    21.简述http协议中get和post方法的区别

    1、 GET主要用于从服务器查询数据,POST用于向服务器提交数据

    2、 GET通过URL传递数据,POST通过http请求体传递数据

    3、 GET传输数据量有限制,不能大于2kb,POST传递的数据量较大,一般大量的数据提交都是通过POST方式

    4、 GET安全性较低,容易在URL中暴漏数据,POST安全性较高

    22.什么是csrf攻击,如何阻止

    CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。

    从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤:

      1.登录受信任网站A,并在本地生成Cookie。

      2.在不登出A的情况下,访问危险网站B。

    防止方式

    (1).Cookie Hashing(所有表单都包含同一个伪随机值)

    (2).验证码

    (3).One-Time Tokens(不同的表单包含一个不同的伪随机值)

    23.服务器推送数据到前端有哪些解决方案

    一、Ajax轮询

    用定时器不断发送请求

    优点:实现简单。

    缺点:这是通过模拟服务器发起的通信,不是实时通信,不顾及应用的状态改变而盲目检查更新,导致服务器资源的浪费,且会加重网络负载,拖累服务器。

    二、comet

    基于 HTTP 长连接的 "服务器推" 技术,能使服务器端主动以异步的方式向客户端程序推送数据,而不需要客户端显式的发出请求,目前有两种实现方式:

    1. 基于 AJAX 的长轮询(long-polling)方式

    优点

    客户端很容易实现良好的错误处理系统和超时管理,实现成本与Ajax轮询的方式类似。

    缺点

    需要服务器端有特殊的功能来临时挂起连接。当客户端发起的连接较多时,服务器端会长期保持多个连接,具有一定的风险。

    2. 基于 Iframe 及 htmlfile 的流(streaming)方式

    Comet的优缺点

    优点: 实时性好(消息延时小);性能好(能支持大量用户)

    缺点: 长期占用连接,丧失了无状态高并发的特点。

    三、websocket

    WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket通讯协议于2011年被IETF定为标准RFC 6455,WebSocketAPI被W3C定为标准。在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

    24.h5c3有哪些新增特性

    h5新增的标签

    新增元素

    说明

    video

    表示一段视频并提供播放的用户界面

    audio

    表示音频

    canvas

    表示位图区域

    source

    为video和audio提供数据源

    track

    为video和audio指定字母

    svg

    定义矢量图

    code

    代码段

    figure

    和文档有关的图例

    figcaption

    图例的说明

    main

    time

    日期和时间值

    mark

    高亮的引用文字

    datalist

    提供给其他控件的预定义选项

    keygen

    秘钥对生成器控件

    output

    计算值

    progress

    进度条

    menu

    菜单

    embed

    嵌入的外部资源

    menuitem

    用户可点击的菜单项

    menu

    菜单

    template

    模板

    section

    区块

    nav

    导航

    aside

    侧边栏

    article

    文章

    footer

    底部

    header

    头部

    - css3

    css3被划分为模块,最重要的几个模块包括:选择器、框模型、背景和边框、文本效果、2D/3D 转换、动画、多列布局、用户界面

    • 选择器

    • 框模型

    • 背景和边框

      border-radius、box-shadow、border-image、

      background-size:规定背景图片的尺寸

      background-origin:规定背景图片的定位区域

      background-clip:规定背景的绘制区域

    • 文本效果(常用)

      text-shadow:设置文字阴影

      word-wrap:强制换行

      word-break

      css3提出@font-face规则,规则中定义了font-family、font-weight、font-style、font-stretch、src、unicode-range

    • 2/3D转换

      transform:向元素应用2/3D转换

      transition:过渡

    • 动画

    • @keyframes规则:

      animation、animation-name、animation-duration等

    • 用户界面(常用)

      box-sizing、resize

      css3新增伪类

      :nth-child()

      :nth-last-child()

      :only-child

      :last-child

      :nth-of-type()

      :only-of-type()

      :empty

      :target 这个伪类允许我们选择基于URL的元素,如果这个元素有一个识别器(比如跟着一个#),那么:target会对使用这个ID识别器的元素增加样式。

      :enabled

      :disabled

      :checked

      :not

    25.正则验证邮箱

    由于邮箱的基本格式为“名称@域名”,需要使用“^”匹配邮箱的开始部分,用“$”匹配邮箱结束部分以保证邮箱前后不能有其他字符,所以最终邮箱的正则表达式为

    ^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$

    26.标准模式与怪异模式下盒子模型的计算方式

    两种模式的区别:

      标准模式会被设置的padding撑开,而怪异模式则相当于将盒子的大小固定好,再将内容装入盒子。盒子的大小并不会被padding所撑开。

    标准模式:盒子总宽度/高度 = 设置宽度/高度+padding+border

    怪异模式:盒子总宽度/高度= 内容宽度/高度 + padding + border + margin;

    27.你用到了es6中哪些新特性

    1. 默认参数

    2. 模版表达式

    3. 箭头函数

    4. Promise

    5. 块级作用域的let和const

    6. 模块化

    28.描述一个闭包

    function A(){

    var x = 1;

    return function(){

    return ++x;

    }

    }

    1.存在一个函数A

    2.在函数A内部返回一个函数

    3.返回的函数引用A函数的私有变量

    4.这个返回的函数是A函数的闭包函数

    29.一个箭头函数,如何获取传入的所有实参

    用无限参数

    var fn = (…args)=>{

    console.log(args);

    }

    这样就可以打印传入的所有参数

    注意:在箭头函数中不能使用arguments

    30.通讯协议知道哪些?讲讲websocket协议。

    http、https、websocket、tcp/ip

    webSocket是H5的新协议,它先通过http请求的tcp层3次握手建立连接,然后通过请求带的update:webSocket信息将http协议转换成webSocket协议,再然后就可以服务端向客户端推送信息了。Websocket建立的是长连接,它是双工通信,允许服务器端主动推送信息到客户端。http建立的是短连接,无状态单工通信。