当前位置:首页 » 《随便一记》 » 正文

前端200道面试题及答案(更新中)

17 人参与  2022年12月10日 09:05  分类 : 《随便一记》  评论

点击全文阅读


目录

html相关

1)说一下对cookie和Storage(localStorage和sessionStorage) 的认识和区别?

2)link和@import的区别

3)浏览器如何实现不同标签页的通信?

4)iframe的优缺点

5)canvas

6)做项目用到哪些h5新特性和css3新特性?

7)用localstorage和sessionStorage写过什么?

8)如何解决页面内容加载缓慢的问题?

9)cookie的特点*

10)页面渲染过程

11)网页上哪里可以看到请求的所有信息

12)HTML5的新特性                                                                                                                                       

13)localstore和sessionstore的区别

14)页面之间是怎么传参数的?

15)如何在浏览器查看和清除localstrorage保存的数据?

16)对H5新增的语义化标签的理解?

css相关

17)CSS选择器的优先级排序,怎么计算权值?

18)display:none和visibility:hidden的区别

19)CSS的继承选择器,.one. two和.one > .two的区别?两个同级类选择器连着一起写有什么作用?(权值相加)

20)CSS的引用方式有哪些?它们的区别?

21)css有哪些选择符?可继承的属性有哪些?css3新增的伪元素有哪些?css优先级的计算

22)fixed和absolute的区别?

23)如何实现水平、垂直居中?

24)实现左侧边栏固定,其他内容自适应?

25)css3的新特性

26)了解过哪些页面布局?

27 用animation做过什么?做过哪些动画?

28 Sass写一个数组?

29)rem出现很小的小数手机上会发生什么,

30 什么时候用less

31 animation和transition

32 移入图片让那个图片慢慢放大

33 盒子模型概念

34 引用样式的方式有哪几种?他们的优先级排序怎么样?

35 px,em,rem,%,vm,vh

36 display的值和作用

37列举两种清除浮动的方法(代码实现或者描述思路)

38 盒子模型(怪异模型)

39 谈谈fixed ,relative , absolute

40 float和absolute有什么区别?

41 代码实现3栏效果,左右两栏固定宽度,中间栏随着浏览器宽度自适应变化

42 css选择器的权重

43 transition transform translate 之间的区别 transform的属性有哪些?

44 css3中的选择器

46 用CSS实现一个背景色为红色,半径为200px的圆,并设置不停的上下移动动画

javascript以及es6相关

 null和undefined的区别?

 js的数据类型

 js 的继承实现方式有哪些,列举两个例子

eval是什么?

 用什么会导致内存泄漏?

 js深度克隆的代码实现?

 同源策略,跨域,后台如何解决跨域,html有哪些标签可以跨域

es6

js自己封装一个方法

 jq用过哪些方法?

 promise?

 触摸有几个事件?

什么时候会发生跨域问题

 匿名函数

 This指向问题

 JQ,JS,vue 三者的区别

 用jq实现双向绑定!

 ajax的实现

ajax的实现

 在数组上新增一个方法,实现复制。

 期望:[1,2,3].copy() //输出 [1,2,3,1,2,3]

 .使用闭包实现一个方法,第一次调用返回1,第二次返回2,第三次3,以此类推。

 .封装一个函数,参数是定时器的时间,.then执行回调函数。

 说一说前端性能优化有哪些方法?

 一个页面上有大量的图片(大型电商网站),加载很慢,你有哪些方法优化这些图片的加载,给用户更好的体验。

 .export和export default?

怎么去判断出来数组里面值为1的元素

 有一个数组,怎么去修改每一个值?

 数组去重

 统计字符串中出现最多的字符

js垃圾回收机制

原型、原型链

作用域链

闭包

继承方法

辗转相除法

数组转字符串

二级下拉菜单

图片预加载和懒加载?

bind() apply()

const用法

Utf-8编码汉字占多少个字节

ajax

js对数组的操作,包括向数组中插入删除数据

两种定时器,setinterval和settimeout。因为settimeout是只执行一次的,如果要执行多次怎么做。(答案:设置一个回调函数,多次调用,大概是这样,你可以去查查)

JS内存回收机制

promise是什么?能解决什么问题?

编程:连接两个数组并返回?

冒泡排序?

创建新数组,向数组插入数据

es6新特性

js对数组有哪些操作方法

什么是ajax,可以用来做什么

讲下你做轮播图的思路,无缝轮播

js的选择器

js数据类型

减少页面加载时间的方法

怎么理解模块化开发

什么是闭包,有什么作用?

定时器 settimeout和setinterval的区别,如果用settimeout实现每隔一定的时间就执行一次,怎么实现

手机号的正则表达式(以1开头的11位数字)

结构的html代码,写原生js实现点击某个li就弹出对应的索引值

对数组进行随机排序, 要求数组中的每个元素不能停留在原来的位置

代码实现parse方法,将有效的JSON字符串转换成JavaScript对象

原生js的变量类型有哪些?ES6新增哪几个变量类型?

js的数组方法有哪些?

es6的有哪些扩展?新增的数组方法有哪些?用什么方法连接两个数组?函数扩展中的箭头函数中的this所指向的是什么?一般函数的this指向的又是什么?

用什么方法判断是否是数组?又用什么方法判断是否是对象?

http相关

浏览器

bootstrap

vue相关

node相关

4  module.export和export?

微信小程序

react

数据库相关

其他


html相关

1)说一下对cookie和Storage(localStorage和sessionStorage) 的认识和区别?

 session 是一个后端存储空间
2. cookie / localStorage / sessionStorage 的区别
存储大小

cookie 4kb  
localStorage 5M 
通讯相关

cookie 随请求携带
storage 不会自动携带
操作相关

cookie 操作复杂,没有 api,前后端都可以操作
storage 操作简单,有 api,只能前端操作
存储格式

cookie:字符串格式
storageL: 键值对
时效相关

cookie:默认会话级别,可以手动设置
storage:localStorage的存储是永久性的,只有在手动删除或者浏览器被卸载后才会被清除,sessionStorage 是会话,当窗口或者页面关闭后会被清除
3.loaclStorage 和 sessionStorage 的区别
跨页面通讯能力
localStorage 随便跨页面
sessionStorage 只是在本页面跳转可以通讯
时效性
localStorage 是永久
sessionStorage 是会话
共同点
不能存储其他数据类型,只能存储字符串数据类型
如果一定要存储其他数据类型,转成 json 格式存储

2)link和@import的区别

 

都知道 ,外部引入 CSS 有2种方式,link标签和@import。
但是它们有何本质区别?
本人项目中多数情况都使用link方式,但见过某些项目人,自以为@import高大上类似es6,极力吹捧使用@import,就此找了一些资料对此进行比较说明:
先上结论
慎用@import方式。可以避免考虑@import的语法规则和注意事项,以及不合理的引入顺序导致的资源文件下载顺序混乱和http请求过多。

区别1:
link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事物如引入网站标题图标;@import属于CSS范畴,只能加载CSS。

<link rel="icon" type="image/x-icon" href="XXX.ico">

区别2:
link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。所以会出现一开始没有css样式,闪烁一下出现样式后的页面。

区别3:
link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。

区别4:
link支持使用Javascript控制DOM去改变样式;而@import不支持。

顺便总结下在html中css有四种引入方式:

内联样式
内联CSS也可称为行内CSS或者行级CSS,它直接在标签内部引入,显著的优点是十分的便捷、高效
示例:<div style="background:red"></div>
这通常是个很糟糕的书写方式,它只能改变当前标签的样式,如果想要多个

拥有相同的样式,你不得不重复地为每个
添加相同的样式,如果想要修改一种样式,又不得不修改所有的 style 中的代码。很显然,内联方式引入 CSS 代码会导致 HTML 代码变得冗长,且使得网页难以维护。
嵌入样式
嵌入方式也称页级CSS或内部CSS,整体是放在head标签里边的,在style标签里边定义样式,作用范围和字面意思相同,仅限于本页面的元素;如果你写的代码超过了几百行,想想每次把代码页拉到最上边都很烦,所以它在可维护性方面较差。
示例:

嵌入方式的 CSS 只对当前的网页有效。因为 CSS 代码是在 HTML 文件中,所以会使得代码比较集中,当我们写模板网页时这通常比较有利。因为查看模板代码的人可以一目了然地查看 HTML 结构和 CSS 样式。因为嵌入的 CSS 只对当前页面有效,所以当多个页面需要引入相同的 CSS 代码时,这样写会导致代码冗余,也不利于维护。
外部样式
链接方式指的是使用 HTML 头部的 标签引入外部的 CSS 文件。
示例:

这是最常见的也是最推荐的引入 CSS 的方式。使用这种方式,所有的 CSS 代码只存在于单独的 CSS 文件中,所以具有良好的可维护性。并且所有的 CSS 代码只存在于 CSS 文件中,CSS 文件会在第一次加载时引入,以后切换页面时只需加载 HTML 文件即可。
导入样式
导入方式指的是使用 CSS 规则引入外部 CSS 文件。
示例:

或者写在css样式中

@charset “utf-8”;
@import url(style.css);
*{ margin:0; padding:0;}
.notice-link a{ color:#999;}

HTML加载过程:
    1) 加载HTML-DOM结构

2)CSS和JS

3)图片和多媒体

4)加载事件触发

总结: link和@import都没有放置顺序的要求,但是不同的放置位置可能会造成效果显示的差异。对于link,无论放到哪个位置,都是一边加载数据,一边进行优化,视觉感受很好;而对于@import,放置到哪里,才从哪里开始加载CSS样式,即先加载数据,然后加载样式,如果网速不佳,可能会造成只有数据出来,而样式一点点加载的效果。并且在同一个页面中,调用两种方式,link永远比@import优先级高。

在项目中使用的时候,一般在页面中调用方式为link,并且放在head标签中;使用@import除了在CSS文件中,在页面调用时,一般加载第三方的样式会使用到,并且需要放置在页面的底部,不会影响自己的网站。
 

       

3)浏览器如何实现不同标签页的通信?

浏览器内多个标签页之间通信,通俗的讲就是浏览器中开了多个窗口,在其中一个窗口做了一些行为等其他窗口不用刷新也能有相关表现。

一、cookie+setInterval方式
要想在多个窗口中通信,通信的内容一定不能放在window对象中,因为window是当前窗口的作用域,里面的内容只属于当前窗口。而cookie是浏览器的本地存储机制,和窗口无关。

将要发送的信息写入cookie:

 var msg = documet.querySelector('#msg'); if(msg.value.trim() != ""){ docment.cookie = "msg=" + msg.value.trim(); }




在另一个页面读取cookie:

  var recMsg = document.querySelector('#recMsg');
 function getValue(key){
    var cookies = '{"'+document.cookie.replace(/=/g,'":"').replace(/;\s+/g,'", "')+'"}';
    cookies = JSON.parse(cookies);
    return cookies[key];
 }
 setInterval(function(){
    recMsg.innerHTML = getValue("msg1");
 },500);



但是由于仅仅从cookie读取信息不能实时更新,需要手动刷新,因此采用setInterval定时器解决,将读取信息的代码封装成一个函数,在定时器内调用即可

缺点:

1)cookie空间有限,容量4k
2)每次http请求都会把当前域的cookie发送到服务器上,浪费带宽
3)setInterval评率设置过大会影响浏览器性能,过小会影响时效性

优点:每个浏览器都兼容

二、websocket协议
websocket是一种网络通信协议,因为http有缺陷,通信只可以由客户端发起,服务器无法主动向客户端发送消息,但如果这时服务器有连续变化的状态,那么就只能使用轮询(每个一段时间,就发出一个询问)的方式来询问。因为websocket拥有全双工(full-duplex)通信自然可以实现多个标签页之间的通信。
发送方先发送消息到WebSocketServer,然后服务端再实时把消息发给接收方

用法:新建webSocket文件夹,在该目录下打开终端,运行npm init (npm安装及配置步骤)初始化一个简单的node项目(因为需要引入ws包),一直按回车到结束就初始了一个简单的node项目。再安装ws包,依旧在当前目录下的终端运行npm i -save ws,在webSocket目录下新建sever.js、send.html、reveive.html文件

三、localstorage

四、html5浏览器新特性——SharedWorker
WebWorker的升级版,webworker只能在一个窗口内使用,而SharedWorker可以在多个窗口之间通信
SharedWorker也是纯客户端的,没有服务端参与
SharedWorker在客户端有一个自己维护的对象worker.js,消息存储在worker.js的data中
SharedWorker不如localStorage的是接收消息不是自动的,也要用定时器实时从worker.js中获取消息

原文链接:https://blog.csdn.net/jewfer/article/details/122614963

4)iframe的优缺点

  

一、iframe的优点:
1、 iframe能够原封不动地把嵌入的网页展现出来。

2、 如果有多个网页调用iframe,只需要修改iframe的内容,就可以实现对调用iframe的每一个页面内容的更改,方便快捷。

3、 网页如果为了统一风格,头部和版本都是一样的,就可以写成一个页面,用iframe来嵌套,可以增加代码的可重用性。

4、 如果遇到加载缓慢的第三方内容如图标和广告等,可以用iframe来解决。

二、iframe的缺点:
1、 会产生很多页面,不容易管理。

2、 在几个框架中都出现上下、左右滚动条时,这些滚动条除了会挤占已经非常有限的页面空间外,还会分散访问者的注意力。

3、 使用框架结构时,必须保证正确设置所有的导航链接,否则会给访问者带来很大的麻烦。比如被链接的页面出现在导航框架内,这种情况下会导致链接死循环。

4、 很多的移动设备(PDA手机)无法完全显示框架,设备兼容性差。

5、 iframe框架页面会增加服务器的http请求,对于大型网站是不可取的。

现在基本上都是用Ajax来代替iframe,iframe已渐渐退出了前端开发。

5)canvas

Canvas介绍
1.canvas是html5的一个新标签,属于h5的新特性
2.canvas标签是一个图形的容器,简单点说就是一块画布,你可以在上画矩形,圆形,三角形,折线等等,也可以用来画logo
3.它是通过javascript来画的,即脚本绘制图形

canvas可以用来干啥呢?
1.制作web网页游戏(但是如果代码写的不咋的游戏可能会非常卡)
2.数据可视化(这么说你可能不明白,但我告诉你echarts就是基于canvas)
3.广告banner的动态效果非常适合用canvas制作
4.canvas还可以用来内嵌一些网页

原文链接https://blog.csdn.net/u012468376/article/details/73350998

6)做项目用到哪些h5新特性和css3新特性?

1 HTML5 的新特性
增加了新标签、新表单和新特性
IE9以上才兼容,如不考虑兼容问题,则可以大量使用(如移动端);

1 重点是常用新特性;
1.1 HTML5 新增的语义化标签
div 对于搜索引擎来说是没有语义的;

header:头部标签
nav:导航标签
article:内容标签
section:定义文档某个区域
aside:侧边栏标签
footer:尾部标签
主要是针对搜索引擎的
可以多次使用
在IE9中需要转为块级元素才能使用
1.2 HTML5 新增的多媒体标签
1 音频:audio;
有 MP3 Wav Ogg 三种格式;
语法
<audio src="文件地址" controls="controls"></audio>
1
属性
autoplay autoplay 视频就绪自动播放(谷歌浏览器需要添加muted来解决自动播放问题);
controls controls 向用户显示播放器控件;
loop loop 播放完是否继续循环播放
src url
Chrome 把音频和视频自动播放禁止了;
2 视频:video;
尽量使用 MP4;
另外还有 Ogg 格式;
语法:
<video src="文件地址" controls="controls"></video>
1
属性
autoplay autoplay 视频就绪自动播放(谷歌浏览器需要添加muted来解决自动播放问题);
controls controls 向用户显示播放器控件;
width px
height px
loop loop 播放完是否继续循环播放
preload auto(预先加载视频)| none(不应加载视频)
src url
poster Imgurl 加载等待的画面图片
muted muted 静音播放
视频静音后可以自动播放;
从而不再使用flash等插件
1.3 HTML5 新增的 input 类型
验证的时候必须添加 form 表单域;
使用 submit 进行提交;
type="email"    限制用户输入必须为 Email 类型
type="url"    限制用户输入必须为 URL 类型
type="date"    限制用户输入必须为 date 类型
type="time"    限制用户输入必须为 time 类型
type="month"    限制用户输入必须为 month 类型
type="week"    限制用户输入必须为 week 类型
type="number"    限制用户输入必须为 number 类型
type="tel"    限制用户输入必须为 tel 类型
type="search"    限制用户输入必须为 search 类型
type="color"    限制用户输入必须为 color 类型
type="submit"    提交按钮
1.4 HTML5 新增的表单属性
属性    值    说明
required    required    表单拥有该属性表示其内容不能为空,必填
placeholder    提示文本    表单的提示信息,存在默认值将不显示
autofocus    autofocus    自动聚焦属性,页面加载完成后聚焦到指定表单
autocomplete    off/on    浏览器基于之前输入的值,显示出可能的选项,
默认已经打开,关闭autocomplete="off"
需要放在表单内,加上name属性,同时提交成功
multiple    multiple    可以多选文件提交
``` /* 设置占位符颜色 */ input::placeholder { color: springgreen; } ```
2 CSS3
存在兼容性问题

2.1 属性选择器
属性选择器可以根据元素特定属性来选择元素,这样就可以不用借助于类或者 id 选择器;
权重为 0, 0, 1, 0;
类选择器、属性选择器、伪类选择器权重相同;
input[name="username"] {
    outline: none;
    border: 3px solid skyblue;
}

选择符    简介
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 元素
2.2 结构伪类选择器
根据文档结构来选择元素,常用于根据父级选择器里面的子元素;
/* 选择第一个孩子,且必须是 li */
ul li:first-child {
    color: red;
}

ul li:nth-child(2) {
    color: red;
}

// 使用 even 选出奇数行
ul li:nth-child(even) {
    background-color: red;
    color: white;
}

ul li:nth-child(even) // 使用 even 选出奇数行
ul li:nth-child(odd) // 使用 odd 选出偶数行
ul li:nth-child(n) // n 是选择所有
n 可以被公示替代
2n 取出偶数项
2n + 1 取出奇数项
5n 取出 5 的倍数项
n + 5 从第五项开始
-n + 5 前五项
数字可以是任何数字
div:nth-child(n) 会包含所有标签类型,同时需要满足设置的标签类型,都满足方能选中;
div:nth-of-type(n) 只包含指定元素,如此处为div;
选择符    简介
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 个
2.3 伪元素选择器
伪元素选择器可以用于利用 css 创建新标签元素,不需要 HTML 标签,从而简化 HTML 结构;

after 和 before 创建的元素是行内元素;

新创建的元素在文档树中是找不到的;

语法:element::before();

after 和 before 必须有 content 属性;

伪元素选择器和标签选择器一样,权重为0, 0, 0, 1;

选择符    简介
::before    在元素内部的前面插入内容
::after    在元素内部的后面插入内容
div {
    width: 200px;
    height: 200px;
    background-color: pink;
}

div::before {
    /* content是必须要写的,元素内容 */
    content: 'before 伪元素选择器';
}

div::after {
    /* content是必须要写的,元素内容 */
    content: 'after 伪元素选择器';
}

content 必须填写,可以写空字符串;

在伪元素中使用 iconfont:

@font-face {
    font-family: "iconfont";
    src: url('iconfont.eot?t=1587189598280');
    /* IE9 */
    src: url('iconfont.eot?t=1587189598280#iefix') format('embedded-opentype'),
        /* IE6-IE8 */
        url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAJwAAsAAAAABiAAAAIjAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCCcAooRgE2AiQDCAsGAAQgBYRtBzIbbgXILrBt2JMiJESQDXTjExAAiOD5/b7Nue9+1bRqcaNJFE0LNDyRiFs3oa1TOqFoJv/9X7p0TKPyfLfcQ01/I//fmLm0hedxGiERBoSECkU85Jegb+7hAvs8l9ObQAdyV32gXPegNQYNoF4cUKB7YBRZCWXcMHbBC3xMoG5GQ+7k7HiBqsxeFYj3b7QB1UJAllm6KpQbDmbxWUk1PaVv4FP0/finF1WSUsGuuny5smH6i5NVPE4ePQSEIAEdL6HAFpCJ28bEuYJgXEE9UbQAjlUe/DKZBHZxVItgf51d2gRTMBn84q0UIMFjUYYbkzYR5Rf7pEf216s366Re+xcwRT8rDtKBHILvT23nf7WRwc97HpmzYS5Q3cwZfL5s4EA2FLYtZU3WOJ6UD9tWV8cE9vT9TTWOrpUJVaMJrorpDIWqJTKzWyhp2EZZ1T7qNm2ONwywgsg1bPgACF2fSNp+oND1Q2b2FyVj/yjrRoG6+xhc2LASb+rHH8gQstF8R9eKI+U6pB6Xn0jfA4Pzioi/EWduGLutTjm9oYh4iS3ZQ/dEFCqOQ1yD5ygIYkw49siSliOS9Ntt1fSmlhWHUHeMEYMgNmR6h1yWWEQFk0W98vkTot0FDNzRV5e+ISzjzo66WjoDyI02GtT3KK9kHrQeIRSksFgIrcE8EgjEUNI8z0MsosWZEEv0tZ1Raqi2tb0+/LtTUGebUjg1herHN0akfQsAAAAA') format('woff2'),
        url('iconfont.woff?t=1587189598280') format('woff'),
        url('iconfont.ttf?t=1587189598280') format('truetype'),
        /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
        url('iconfont.svg?t=1587189598280#iconfont') format('svg');
    /* iOS 4.1- */
}

.iconfont {
    font-family: "iconfont" !important;
    font-size: 16px;
    font-style: normal;
    -webkit-font-smoothing: antialiased;
    -webkit-text-stroke-width: 0.2px;
    -moz-osx-font-smoothing: grayscale;
}

div::after {
    position: absolute;
    font-family: "iconfont" !important;
    font-size: 16px;
    font-style: normal;
    -webkit-font-smoothing: antialiased;
    -webkit-text-stroke-width: 0.2px;
    -moz-osx-font-smoothing: grayscale;
    /* top: ; */
    content: '\e77b';
}

原本直接放在“ iconfont ”类中的样式放在对应伪类中,然后将“&#x”改为“\”即可(如  ,在content中变为 \e77b);

2.4 CSS3 盒子模型
CSS3 中可以通过 box-sizing 来指定盒模型,分别是 content-box、border-box;
这样就可以该表计算盒子大小的方式;
可以分成两种情况:
1 box-sizing: content-box 盒子大小为 width + padding + border (默认);
2 box-sizing: border-box 盒子大小为 width;
.div2 {
    width: 200px;
    height: 200px;
    background-color: skyblue;
    border: 5px solid greenyellow;
    padding: 15px;
    box-sizing: border-box;
}

使用通配符进行统一默认配置;
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

2.5 CSS3 其他特性(了解)
1 CSS3 滤镜 filter;

用于将模糊或颜色偏移等图形效果应用于元素;
filter: 函数();     
例如:filter: blur(5px); blur模糊处理 数值越大越模糊

2 CSS3 calc 函数:

calc() 使声明css属性值时执行一些计算;
width: calc(100% - 80px);
1
上例中使得子元素永远比父元素窄 80px;
可以使用运算符
2.6 CSS3 过渡
在不使用 Flash 动画或 javascript 的情况下,配置元素样式变化过度效果;

主要是过渡效果;
与 :hover 搭配使用;
transition: 要过渡的属性 花费时间 运动曲线 何时开始;
1
要过渡的属性:如果是所有属性,可以写 all ;
花费时间:单位为秒,必须写单位,如 0.5s;
运动曲线:可以省略;
linear:匀速;
ease:缓慢减速;
ease-in:加速;
ease-out:减速;
ease-in-out:先加速后减速;
何时开始:用于延迟,可以省略;
div {
    width: 200px;
    height: 100px;
    background: no-repeat;
    background-image: url(../1.jpg);
    background-size: 100% 100%;
    transition: background-image 1s, width 1s;
}

div:hover {
    background-image: url(../2.jpg);
    width: 400px;
}

改变多个属性则用逗号分开,或用all;
直接用 all 最常见;

原文链接:https://blog.csdn.net/qq_42680313/article/details/105587567

7)用localstorage和sessionStorage写过什么?

sessionStorage用作临时交流的留言板或是交流记录

用localStorage做过记住用户名和密码的功能,做过小游戏最高分和排行榜

8)如何解决页面内容加载缓慢的问题?

一、优化图片

几乎没有哪个网页上是没有图片的。如果你经历过56K猫的年代,你一定不会很喜欢有大量图片的网站。因为加载那样一个网页会花费大量的时间。

即使在现在,网络带宽有了很多的提高,56K猫逐渐淡出,优化图片以加快网页速度还是很有必要的。

优化图片包括减少图片数、降低图像质量、使用恰当的格式。

1、减少图片数:去除不必要的图片。可以将大量的背景图整合成一张雪碧图

2、降低图像质量:如果不是很必要,尝试降低图像的质量,尤其是jpg格式,降低5%的质量看起来变化不是很大,但文件大小的变化是比较大的。

3、使用恰当的格式:请参阅下一点。

因此,在上传图片之前,你需要对图片进行编辑,如果你觉得photoshop太麻烦,可以试试一些在线图片编辑工具。懒得编辑而又想图片有特殊的效果?可以试试用过调用javascript来实现图片特效。

二、图像格式的选择

一般在网页上使用的图片格式有三种,jpg、png、gif。三种格式的具体技术指标不是这篇文章探讨的内容,我们只需要知道在什么时候应该使用什么格式,以减少网页的加载时间。

1、JPG:一般用于展示风景、人物、艺术照的摄影作品。有时也用在电脑截屏上。

2、GIF:提供的颜色较少,可用在一些对颜色要求不高的地方,比如网站logo、按钮、表情等等。当然,gif的一个重要的应用是动画图片。就像用Lunapic制作的倒映图片。

3、PNG:PNG格式能提供透明背景,是一种专为网页展示而发明的图片格式。一般用于需要背景透明显示或对图像质量要求较高的网页上。

三、优化CSS

CSS叠层样式表让网页加载起来更高效,浏览体验也得到提高。有了CSS,表格布局的方式可以退休了。

但有时我们在写CSS的时候会使用了一些比较罗嗦的语句,比如这句:

以下为引用的内容:
margin-top: 10px;
margin-right: 20px;
margin-bottom: 10px;
margin-left: 20px;

你可以将它简化为:

margin: 10px 20px 10px 20px;

又或者这句:

以下为引用的内容:
<p class="decorated">A paragraph of decorated text</p>
<p class="decorated">Second paragraph</p>
<p class="decorated">Third paragraph</p>
<p class="decorated">Forth paragraph</p>

可以用div来包含:

以下为引用的内容:
<div class="decorated">
<p>A paragraph of decorated text</p>
<p>Second paragraph</p>
<p>Third paragraph</p>
<p>Forth paragraph</p>
</div>

简化CSS能去除冗余的属性,提高运行效率。如果你写好CSS后懒得去做简化,你可以使用一些在线的简化CSS工具,比如CleanCSS。

四、网址后加斜杠

有些网址,比如"www.kenengba.com/220",当服务器收到这样一个地址请求的时候,它需要花费时间去确定这个地址的文件类型。如果220是一个目录,不妨在网址后多加一个斜杠,让其变成www.kenengba.com/220/,这样服务器就能一目了然地知道要访问该目录下的index或default文件,从而节省了加载时间。

五、标明高度和宽度

这点很重要,但很多人由于懒惰或其它原因,总是将其忽视。当你在网页上添加图片或表格时,你应该指定它们的高度和宽度,也就是height和width参数。如果浏览器没有找到这两个参数,它需要一边下载图片一边计算大小,如果图片很多,浏览器需要不断地调整页面。这不但影响速度,也影响浏览体验。

下面是一个比较友好的图片代码:

<img id="moon" height="200" width="450" src="http://www.kenengba.com/moon.png" alt="moon image" />

当浏览器知道了高度和宽度参数后,即使图片暂时无法显示,页面上也会腾出图片的空位,然后继续加载后面的内容。从而加载时间快了,浏览体验也更好了。

六、减少http请求

当浏览者打开某个网页,浏览器会发出很多对象请求(图像、脚本等等),视乎网络延时情况,每个对象加载都会有所延迟。如果网页上对象很多,这可以需要花费大量的时间。

因此,要为http请求减负。如何减负?

1、去除一些不必要的对象。

2、将临近的两张图片合成一张。

3、合并CSS

看看下面这段代码,需要加载三个CSS:

以下为引用的内容:
<link rel="stylesheet" type="text/css" href="/body.css" />
<link rel="stylesheet" type="text/css" href="/side.css" />
<link rel="stylesheet" type="text/css" href="/footer.css" />

我们可以将其合成一个:

<link rel="stylesheet" type="text/css" href="/style.css" />

从而减少http请求。

七、其它小技巧(译者添加)

1、去除不必要加载项。

2、如果在网页上嵌入了其它网站的widget,如果有选择余地,一定要选择速度快的。

3、尽量用图片代替flash,这对SEO也有好处。

4、有些内容可以静态化就将其静态化,以减少服务器的负担。

5、统计代码放在页尾。

6、尽量不要用一个很小的图片当背景,这样做会加大客户端CPU处理时间

7,静态资源使用cdn                                                                                                      8,增加服务器带宽                                                                                                     9,如果用户多的话,使用高并发                           

9)cookie的特点*

一、cookie的特点:
1、cookie不可跨域
2、cookie存储在浏览器里面
3、cookie有数量与大小的限制
1)数量在50个左右
2)大小在4kb左右
4、cookie的存储时间非常灵活
5、cookie不光可以服务器设置(用set-cookie),也可以客户端设置。
document.cookie
key:value

二、cookie的属性
1、name cookie的名字,唯一性
2、value cookie的值
3、domain 设置cookie在哪个域名下是有效的
4、path cookie的路径
5、expires cookie的过期时间
6、max-age cookie的有效期,
值:-1 临时cookie,0有效期够了的 cookie,正数存活周期
7、HttpOnly 有这个标记的cookie,前端是无法获取的
8、Secure 设置cookie只能通过https协议传输
9、SameSite 设置cookie在跨域请求的时候不能被发送。
 

10)页面渲染过程

1、解析HMTML标签,构建DOM树
       HTML 文档中的所有内容皆是节点,各节点之间拥有层级关系,如父子关系、兄弟关系等,彼此相连,构成DOM树。最常见的几种节点有:文档节点、元素节点、文本节点、属性节点、注释节点。

DOM节点树中节点与HTML文档中内容一一对应,DOM树构建过程:读取html文档,将字节转换成字符,确定tokens(标签),再将tokens转换成节点,以节点构建 DOM 树。

2、解析CSS,构建CSSOM树
        CSS文档中,所有元素皆是节点,与HTML文件中的标签节点一一对应。CSS中各节点之间同样拥有层级关系,如父子关系、兄弟关系等,彼此相连,构成CSSOM树。

在构建DOM树的过程中,在 HTML 文档的 head 标签中遇到 link 标签,该标签引用了一个外部CSS样式表。由于预见到需要利用该CSS资源来渲染页面,浏览器会立即发出对该CSS资源的请求,并进行CSSDOM树的构建。

CSSOM树构建过程与DOM树构建流程一致:读取CSS文档,将字节转换成字符,确定tokens(标签),再将tokens转换成节点,以节点构建 CSSOM 树。

3、把DOM和CSSOM组合成渲染树(render tree)
      

        渲染树(Render Tree)由DOM树、CSSOM树合并而成,但并不是必须等DOM树及CSSOM树加载完成后才开始合并构建渲染树。三者的构建并无先后条件,亦非完全独立,而是会有交叉,并行构建。因此会形成一边加载,一边解析,一边渲染的工作现象。

构建渲染树,根据渲染树计算每个可见元素的布局,并输出到绘制流程,将像素渲染到屏幕上。

4.在渲染树的基础上进行布局,计算每个节点的几何结构
 4.1重绘(repaint):屏幕的一部分要重绘。渲染树节点发生改变,但不影响该节点在页面当中的空间位置及大小。譬如某个div标签节点的背景颜色、字体颜色等等发生改变,但是该div标签节点的宽、高、内外边距并不发生变化,此时触发浏览器重绘(repaint)。

 4.2重排(reflow):也有称回流当渲染树节点发生改变,影响了节点的几何属性(如宽、高、内边距、外边距、或是float、position、display:none;等等),导致节点位置发生变化,此时触发浏览器重排(reflow),需要重新生成渲染树。譬如JS为某个p标签节点添加新的样式:"display:none;"。导致该p标签被隐藏起来,该p标签之后的所有节点位置都会发生改变。此时浏览器需要重新生成渲染树,重新布局,即重排(reflow)。

注意:重排必将引起重绘,而重绘不一定会引起重排。

何时回引起重排?

当页面布局和几何属性改变时就需要重排。下述情况会发生浏览器重排:

1、添加或者删除可见的DOM元素;

2、元素位置改变——display、float、position、overflow等等;

3、元素尺寸改变——边距、填充、边框、宽度和高度

4、内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;

5、页面渲染初始化;

6、浏览器窗口尺寸改变——resize事件发生时;

4.3如何减少和避免重排

Reflow 的成本比 Repaint 的成本高得多的多。一个节点的 Reflow 很有可能导致子节点,甚至父节点以及兄弟节点的 Reflow 。在一些高性能的电脑上也许还没什么,但是如果 Reflow 发生在手机上,那么这个过程是延慢加载和耗电的。----浏览器的渲染原理简介

1. 直接改变className,如果动态改变样式,则使用cssText(考虑没有优化的浏览器);

2. 让要操作的元素进行”离线处理”,处理完后一起更新;

a) 使用DocumentFragment进行缓存操作,引发一次回流和重绘;
b) 使用display:none技术,只引发两次回流和重绘;
c) 使用cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘;

3.不要经常访问会引起浏览器flush队列的属性,如果你确实要访问,利用缓存;

4. 让元素脱离动画流,减少回流的Render Tree的规模;

5、把每个节点绘制到屏幕上(painting)

原文链接:https://blog.csdn.net/m0_56551554/article/details/121789562https://blog.csdn.net/m0_56551554/article/details/121789562

11)网页上哪里可以看到请求的所有信息

 

以谷歌浏览器为例:

按下f12打开控制台 找到Network就可以看见网页请求的所有信息了

                

12)HTML5的新特性                                                                                                                                       

HTML新特性
1:语义化标签
通过语义化标签,可以让页面有更加完善的结构,让页面的元素有含义,同时利于被搜索引擎解析,有利于SEO,主要标签包括下面的标签:

标签    描述
header    表示文档的头部区域
footer    表示文档的尾部区域
nav    表示文档导航部分
section    表示文档的某一节
article    表示文章
main    表示文档主要的内容区域
2:增强型表单
例如可以通过input的type属性指定类型是number还是date或者url,同时还添加了placeholder和required等表单属性

3. 媒体元素
新增了audio和video两个媒体相关的标签,可以让开发人员不必以来任何插件就能在网页中嵌入浏览器的音频和视频内容。

4. canvas绘图
canvas绘图指的是在页面中设定一个区域,然后通过JS动态的在这个区域绘制图形。

5. svg绘图
这一部分不详细展开,想要了解的小伙伴可以参考其他文章~

6. 地理定位
使用getCurrentPosition()方法来获取用户的位置,从而实现队地理位置的定位。

7. 拖放API
通过给标签元素设置属性draggable值为true,能够实现对目标元素的拖动。

8. Web Worker
Web Worker通过加载一个脚本文件,进而创建一个独立工作的线程,在主线程之外运行,worker线程运行结束之后会把结果返回给主线程,worker线程可以处理一些计算密集型的任务,这样主线程就会变得相对轻松,这并不是说JS具备了多线程的能力,而实浏览器作为宿主环境提供了一个JS多线程运行的环境。

9. Web Storage
关于Web Storage部分,大家需要重点掌握的是cookie、Localstorage和SessionStorage三者之间的区别:

10. Websocket
关于websocket协议,大家主要需要记住的就是websocket和HTTP的区别。

相同点
HTTP和Websocket都是基于TCP的应用层协议。

不同点
websocket是双向通信协议,模拟socket协议,可以双向发送和接受消息,HTTP是单向的,意思是说通信只能由客户端发起。
websocket是需要浏览器和服务器通过握手建立连接,但是HTTP是浏览器向服务器发送连接,服务器预先不知道这个连接。

联系
websocket建立握手时需要基于HTTP进行传输,建立连接之后呢便不再需要HTTP协议了。

原文链接:https://blog.csdn.net/sinat_41696687/article/details/123159705

13)localstore和sessionstore的区别

                

LocalStorge和sessionStorage之间的区别
localStorage
localStorage的生命周期是永久性的,也就是说使用localStorage存储数据,数据会被永久保存,数据不会因为窗口或浏览器的关闭而消失,除非主动的去删除数据。

localStorage有length属性,可以通过控制台查看其有多少条记录的数据。

var storage = null;storage.setItem("key","value")   //调用setItem方法存储数据storage.getItem("key")            //调用getItem方法获取key的值stroage.removeItem("key")        //删除key对应的值stroage.clear()                   //清空数据



sessionStorage
sessionStorage的生命周期相比localStorage来说很短,其周期在窗口关闭时结束。也就是说,当浏览器窗口关闭,sessionStorage的使命就已经结束,其保留的数据也会被清除。

sessionStorage也拥有length属性,两者的使用方法也是一致的,但和localstorage比较,仍有一些区别。

页面刷新不会消除已获得的数据
这里我写了两个html文件(test1.html / test2.html)来进行说明:

因为篇幅问题,所以只取了部分需要注意的代码段

这是test1.html的部分代码:

<body>    <button>跳转按钮</button>    <div>页面的作用:在 sessionStorage 中存数据</div>    <script>        var Data = window.sessionStorage;        console.log(Data)        var str = 'sessionData'        // sessionStorage 存储数据         Data.setItem('code',str)        document.getElementsByTagName('button')[0].onclick = function(){            window.location.href = './test2.html'        }    </script></body>



test2.html的部分代码:

<body>    <div>我是test2页面</div>    <script>              var sessionData = sessionStorage.getItem('code')      console.log(sessionData)      console.log(sessionStorage.getItem('code'))    </script></body>



打开test1页面,可以看见跳转按钮以及一段文字:页面的作用:在 sessionStorage 中存数据;

打开控制器,可以看见已经传入了 code 以及它的值 sessionData;

这时点击跳转按钮,会看见页面刷新,进入test2页面,显示“我是test2页面”

sessionStorage 在test1窗口关闭前;就保存数据了。换一个新的窗口(test2);也不会有数据改变

sessionStorage.getItem(key) 获取sessionStorage的数据中value值
 

14)页面之间是怎么传参数的?

                

1.cookie 传值。

 缺点: cookie储存是需要服务器支持的,本地直接运行静态文件是实现不了的。cookie能够存储少量数据到客户端的磁盘中,特定的网页之间是可以共享cookie中的数据。

2.LocalStorage和SessionStorage传值。

 优点:本地静态文件可支持。在HTML5中,新加入了一个localStorage特性,这个特性主要是用来作为本地存储来使用的,解决了cookie存储空间不足的问题(cookie中每条cookie的存储空间为4k),localStorage中一般浏览器支持的是5M大小,这个在不同的浏览器中localStorage会有所不同。此方法类似cookie,将数据存在一个公共的地方,实现页面之间传值。

 3.get方式,Url传值.。

优点: 速度快. cookie 和 LocalStorage和SessionStorage 都存在速度慢,反应不过来的问题, 我在a页面写进去,在b页面读出来.有时会读到空值。post提交表单跳转的方式肯定不行了,因服务端并不处理这些请求参数,连到达客户端的机会都没有。

4.window.open和window.opener之间传值

window.open可以打开一个新的页面,在新的页面中可以通过window.opener获取父页面的窗口对象,从而可以获取父窗口中的参数。

如:var content = window.opener.document.getElementById("open").innerHTML; 
 

15)如何在浏览器查看和清除localstrorage保存的数据?

        1.按下F12打开开发人员工具
        2.点击切换到 Application
        3.点击LocalStorage 即可查看到保存过的数据信息

在这里插入图片描述

如何清除数据?
点击上方的Clear storage 点击 Clear site data即可删除数据

在这里插入图片描述

16)对H5新增的语义化标签的理解?

一、 语义化标签是什么?

常用的语义化标签包括

<header></header>头部

<nav></nav>导航栏

<section></section>区块(有语义化的div)

<main></main>主要区域

<artical></artical>主要内容

<aside></aside>侧边栏

<footer></footer>底部

二、 为什么会用语义化标签?

平时,我们都会采用DIV+CSS布局我们的页面。但是这样的布局方式不仅使我们的文档结构不够清晰,而且不利于浏览器对页面的读取。所以HTML5新增了很多新的语义化标签。并且,在我们未给页面添加css样式时,用户体验并不好。语义化标签也能让浏览器更好的读取页面结构。再就是便于团队开发和维护,语义化更具可读性,遵循W3C标准的团队都遵循这个标准,可以减少差异化。

css相关

17)CSS选择器的优先级排序,怎么计算权值?

一、各个类型选择器的权重

* 第零等:!important,大过了其它任何设置。* 第一等:代表内联样式,如:style='',权值为1000。* 第二等:代表ID选择器,如:#content,权值为0100。* 第三等:代表类、伪类和属性选择器,如.content,权值为0010。* 第四等:代表标签选择器和伪元素选择器,如div p,权值为0001。* 第五等:通配符、子选择器、相邻选择器等的。如*、>、+,权值为0000。* 第六等:继承的样式没有权值,通配选择器定义的规则优先级高于元素继承过来的规则的优先级。



二、!important
!important的作用是提升优先级,换句话说,加了这句的样式的优先级是最高的(比内联样式的优先级还高)。
1
三、CSS优先级规则

* css选择器的权值不同时,权值高的选择器优先;* css选择器的权值相同时,后定义的选择器优先;* css属性后面加!important时,无条件绝对优先;* 总结:* !important > 行内样式 > id选择器 > 类选择器 || 伪类选择器 || 属性选择器 > 标签选择器 || 伪元素选择器 > 通配符选择器 || 子选择器 || 相邻选择器 > 继承样式


* 注意:
* !important规则被应用在一个样式声明中时,该样式声明会覆盖CSS中任何其他对该元素的声明,无论它处在声明列表中的哪个位置。
* 但是注意,使用!important样式很难调试,因为它改变了你样式本来的权值规则。

四、权值如何进行比较
 

* 当两个权值进行比较时,从高位到低位逐位进行比较,从高等级开始比较。* 如果相同等级的权值相同,再继续进行下一个等级的比较。* 如果不相同,直接应用相同等级权值比较大的选择器对应的样式。而不是把四个等级的权值加起来进行比较。* 如果某个样式后面加了!important,则绝对优先,比内联样式更优先。同一个选择器,同一个属性设置了两次或多次样式,则后设置的样式会覆盖之前的样式



原文链接:https://blog.csdn.net/qq_39090575/article/details/110703916

18)display:none和visibility:hidden的区别

很多人认为visibility: hidden和display: none的区别仅仅在于display: none隐藏后的元素不占据任何空间,而visibility: hidden隐藏后的元素空间依旧保留 ,实际上没那么简单,visibility是一个非常有故事性的属性

visibility具有继承性,给父元素设置visibility:hidden;子元素也会继承这个属性。但是如果重新给子元素设置visibility: visible,则子元素又会显示出来。这个和display: none有着质的区别 :父元素设置display:none; 子元素设置display:block;后子元素不会显示

visibility: hidden不会影响计数器的计数,visibility: hidden虽然让一个元素不见了,但是其计数器仍在运行。这和display: none完全不一样

19)CSS的继承选择器,.one. two和.one > .two的区别?两个同级类选择器连着一起写有什么作用?(权值相加)

1、CSS的继承选择器,.one .two和.one>.two的区别?
.one .two,匹配.one下所有包含.two的标签,包含所有后代元素

.one>.two,匹配.one下子元素中包含.two的标签,只包含.one的子级元素

2、两个同级类选择器连着一起写有什么作用?(.one.two)
权值相加,匹配既包含.one又包含.two类名的标签


原文链接:https://blog.csdn.net/qq_39090575/article/details/113074619

20)CSS的引用方式有哪些?它们的区别?

方式一:内联样式

内联样式也叫行内样式,指的是直接在HTML标签中的 style 属性中添加 css。

示例:

<div style="width: 100px; height: 100px"></div>


这种方式只能改变当前标签的样式,如果想要多个 div 标签拥有相同的样式,就只能重复的为每个 div 添加和修改相同的样式,还会使HTML代码变得冗长,并且难以维护。所以一般不推荐使用内联样式引入CSS样式。

方式二:嵌入样式

嵌入样式指的是在HTML头部中的 style 标签中写入CSS代码。

示例:

<head>    <style>    .div {        width: 100px;        height: 100px;    }    </style></head>


嵌入方式的 CSS 只对当前的网页有效,所以当多个页面需要引入相同的 CSS 样式时,这样写会导致代码冗余,也不利于维护。但是,因为 CSS 代码在HTML文件中,所以会使得代码比较集中,当我们写模板网页时,这样比较写比较好,因为可以让人一目了然地查看 HTML 结构和 CSS 样式。

方式三:链接样式

链接方式指的是使用HTML头部的标签引入外部的 CSS 文件。

示例:

<head>    <link rel="stylesheet" type="text/css" href="index.css"></head>


链接方式是最常见也是最推荐的引入 CSS 的方式。使用这种方式,所有的 CSS 代码只存在于单独的 CSS 文件中,所以具有良好的可维护性,并且所有的 CSS 代码只存在于 CSS 文件中,CSS文件会在第一次加载时引入,以后切换页面时只需加载 HTML 文件即可,并且其他页面需要相同的 CSS 样式时可以复用。

方式四:导入样式

导入样式指的是使用 CSS 规则引入外部 CSS 文件。

示例;

<style type="text/css">    @import url(style.css);</style>


或者

<style type="text/css">    @import url("index.css");</style>


或者

<style type="text/css">    @import "index.css";</style>


原文链接:https://blog.csdn.net/m0_48298027/article/details/110651878

21)css有哪些选择符?可继承的属性有哪些?css3新增的伪元素有哪些?css优先级的计算

一、CSS 选择符:
1.id选择器(# myid)
2.类选择器(.myclassname)
3.标签选择器(div, h1, p,span)
4.相邻选择器(h1 + p)
5.子选择器(ul > li,ol>li)
6.后代选择器(li a)
7.通配符选择器,也称全局选择器( * )
8.属性选择器(a[rel = “external”])
9.伪类选择器(a: hover, li:nth-child)

二、可继承的样式:
1.font-size
2.font-family
3.color
4.text-indent

三、不可继承的样式:
1.border
2.padding
3.margin
4.width
5.height

四、优先级算法:
1.优先级就近原则,同权重情况下样式定义最近者为准;
2.载入样式以最后载入的定位为准;
3.!important > 内联样式>id选择器>calss选择器>标签选择器和伪元素选择器>通配符、子选择器、相邻选择器等>继承的样式没有权值
4.important 比 内联优先级高,但内联比 id 要高

五、CSS3新增伪类举例:
p:first-of-type:选择属于其父元素的首个p元素的每个p元素。
p:last-of-type:选择属于其父元素的最后p元素的每个p元素。
p:only-of-type:选择属于其父元素唯一的p元素的每个p元素。
p:only-child:选择属于其父元素的唯一子元素的每个p元素。
p:nth-child(2):选择属于其父元素的第二个子元素的每个p元素。
:enabled: disabled 控制表单控件的禁用状态。
:checked: 单选框或复选框被选中。
 

22)fixed和absolute的区别?

fixed:固定定位    absolute:绝对定位  两者都会使元素脱离文档流

区别很简单:

1、没有滚动条的情况下没有差异

2、在有滚动条的情况下,fixed定位不会随滚动条移动而移动,而absolute则会随滚动条移动

常用场合:

1.fixed固定定位,只针对浏览器窗口定位,上下左右,不会随着窗口大小改变,固定不变,例如固定位置的小广告,常用于网站边缘的公司联系方式和快速回到顶部

2.absolute绝对定位,脱离文档流,相对于有最近的具有相对定位的上级父元素或者祖宗元素定位,如果依次向上找没找到具有相对定位的上级元素,则相对于浏览器窗口定位
 

23)如何实现水平、垂直居中?

1、利用定位+margin:auto
父级设置为相对定位,子级绝对定位 ,并且四个定位属性的值都设置了0,那么这时候如果子级没有设置宽高,则会和父元素宽高相同,完全覆盖

这里子元素设置了宽高,所以宽高会按照我们的设置来显示,但是实际上子级的虚拟占位已经撑满了整个父级,这时候再给它一个margin:auto它就可以上下左右都居中了

<style>    .father{        width:500px;        height:300px;        border:1px solid #0a3b98;        position: relative;    }    .son{        width:100px;        height:40px;        background: #f0a238;        position: absolute;        top:0;        left:0;        right:0;        bottom:0;        margin:auto;    }</style><div class="father">    <div class="son"></div></div>


2、利用定位+margin:负值

<style>    .father {        position: relative;        width: 200px;        height: 200px;        background: skyblue;    }    .son {        position: absolute;        top: 50%;        left: 50%;        margin-left:-50px;        margin-top:-50px;        width: 100px;        height: 100px;        background: red;    }</style><div class="father">    <div class="son"></div></div>


初始位置为方块1的位置
当设置left、top为50%的时候,内部子元素为方块2的位置
设置margin为负数时,使内部子元素到方块3的位置,即中间位置
这种方案不要求父元素的高度,也就是即使父元素的高度变化了,仍然可以保持在父元素的垂直居中位置,水平方向上是一样的操作

但是该方案需要知道子元素自身的宽高,但是我们可以通过下面transform属性进行移动

3、利用定位+transform
translate(-50%, -50%)将会将元素位移自己宽度和高度的-50%

这种方法其实和最上面被否定掉的margin负值用法一样,可以说是margin负值的替代方案,并不需要知道自身元素的宽高

<style>    .father {        position: relative;        width: 200px;        height: 200px;        background: skyblue;    }    .son {        position: absolute;        top: 50%;        left: 50%;  transform: translate(-50%,-50%);        width: 100px;        height: 100px;        background: red;    }</style><div class="father">    <div class="son"></div></div>


4、table布局

<style>    .father {        display: table-cell;        width: 200px;        height: 200px;        background: skyblue;        vertical-align: middle;        text-align: center;    }    .son {        display: inline-block;        width: 100px;        height: 100px;        background: red;    }</style><div class="father">    <div class="son"></div></div>


5、flex布局

<style>    .father {        display: flex;        justify-content: center;        align-items: center;        width: 200px;        height: 200px;        background: skyblue;    }    .son {        width: 100px;        height: 100px;        background: red;    }</style><div class="father">    <div class="son"></div></div>


css3中了flex布局,可以非常简单实现垂直水平居中

这里可以简单看看flex布局的关键属性作用:

display: flex时,表示该容器内部的元素将按照flex进行布局

align-items: center表示这些元素将相对于本容器水平居中

justify-content: center也是同样的道理垂直居中

6、gird布局

<style>    .father {            display: grid;            align-items:center;            justify-content: center;            width: 200px;            height: 200px;            background: skyblue;         }        .son {            width: 10px;            height: 10px;            border: 1px solid red        }</style><div class="father">    <div class="son"></div></div>


 

24)实现左侧边栏固定,其他内容自适应?

HTML
 

<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <meta http-equiv="X-UA-Compatible" content="ie=edge" />    <title>Static Template</title>    <link rel="stylesheet" href="./index.css" />  </head>  <body>    <div id="box">      <div id="left"></div>      <div id="right"></div>    </div>    <div id="box2"></div>  </body></html>

方案一:左侧固定宽度,右侧flex自适应 flex:1; 占据剩余空间

#box {  width: 100%;  height: 400px;  display: flex;}#left {  width: 100px;  height: 100%;  background-color: lightgreen;}#right {  flex: 1;  background-color: lightblue;}#box2 {  width: 500px;  height: 500px;  background-color: plum;}


方案二:左侧浮动,右侧设置宽度100%,占据左侧普通流位置

#box {  width: 100%;  height: 400px;  background-color: #aaaaaa;}#left {  width: 100px;  height: 100%;  float: left;  background-color: lightgreen;}#right {  width: 100%;  height: 100%;  background-color: lightblue;}#box2 {  width: 500px;  height: 500px;  background-color: plum;}



方案三:左侧固定宽度左浮动,右侧设margin-left等于左侧宽度

#box {  width: 100%;  height: 400px;  background-color: #aaaaaa;}#left {  width: 100px;  height: 100%;  background-color: lightgreen;  float: left;}#right {  width: calc(100% - 100px);  margin-left: 100px;  height: 100%;  background-color: lightblue;}#box2 {  width: 500px;  height: 500px;  background-color: plum;}



方案四:左侧固定宽度、固定定位,右侧宽度100%

#box {  width: 100%;  height: 400px;  background-color: #aaaaaa;  position: relative;}#left {  width: 100px;  height: 100%;  background-color: lightgreen;  position: absolute;  top: 0;  left: 0;}#right {  width: 100%;  height: 100%;  background-color: lightblue;}#box2 {  width: 500px;  height: 500px;  background-color: plum;}


方案五:左侧宽度固定、固定定位,右侧左边距等于左侧宽度:

#box {  width: 100%;  height: 400px;  background-color: #aaaaaa;  position: relative;}#left {  width: 100px;  height: 100%;  background-color: lightgreen;  position: absolute;  top: 0;  left: 0;}#right {  width: calc(100% - 100px);  margin-left: 100px;  height: 100%;  background-color: lightblue;}#box2 {  width: 500px;  height: 500px;  background-color: plum;}


方案六:双左浮动,右侧计算属性计算宽度

#box {  width: 100%;  height: 400px;  background-color: #aaaaaa;}#left {  width: 100px;  height: 100%;  background-color: lightgreen;  float: left;}#right {  width: calc(100% - 100px);  height: 100%;  float: left;  background-color: lightblue;}#box2 {  width: 500px;  height: 500px;  background-color: plum;}


方案七:左侧左浮,右侧右浮动,右侧计算宽度:

#box {  width: 100%;  height: 400px;  background-color: #aaaaaa;}/* #box::after {  content: " ";  display: block;  clear: both;} */#left {  width: 100px;  height: 100%;  background-color: lightgreen;  float: left;}#right {  width: calc(100% - 100px);  float: right;  height: 100%;  background-color: lightblue;}#box2 {  width: 500px;  height: 500px;  background-color: plum;}


方案八:左侧固定宽度,display:inline-block,右侧右浮动,计算宽度

#box {  width: 100%;  height: 400px;  background-color: #aaaaaa;}/* #box::after {  content: " ";  display: block;  clear: both;} */#left {  width: 100px;  height: 100%;  background-color: lightgreen;  display: inline-block;}#right {  width: calc(100% - 100px);  float: right;  height: 100%;  background-color: lightblue;}#box2 {  width: 500px;  height: 500px;  background-color: plum;}

25)css3的新特性

二、选择器
css3中新增了一些选择器,主要为如下图所示:

三、新样式
边框
css3新增了三个边框属性,分别是:

border-radius:创建圆角边框

box-shadow:为元素添加阴影

border-image:使用图片来绘制边框

box-shadow

设置元素阴影,设置属性如下:

水平阴影

垂直阴影

模糊距离(虚实)

阴影尺寸(影子大小)

阴影颜色

内/外阴影

其中水平阴影和垂直阴影是必须设置的

背景
新增了几个关于背景的属性,分别是background-clip、background-origin、background-size和background-break

background-clip

用于确定背景画区,有以下几种可能的属性:

background-clip: border-box; 背景从border开始显示

background-clip: padding-box; 背景从padding开始显示

background-clip: content-box; 背景显content区域开始显示

background-clip: no-clip; 默认属性,等同于border-box

通常情况,背景都是覆盖整个元素的,利用这个属性可以设定背景颜色或图片的覆盖范围

background-origin

当我们设置背景图片时,图片是会以左上角对齐,但是是以border的左上角对齐还是以padding的左上角或者content的左上角对齐? border-origin正是用来设置这个的

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

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

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

默认情况是padding-box,即以padding的左上角为原点

background-size

background-size属性常用来调整背景图片的大小,主要用于设定图片本身。有以下可能的属性:

background-size: contain; 缩小图片以适合元素(维持像素长宽比)

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

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

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

background-break
元素可以被分成几个独立的盒子(如使内联元素span跨越多行),background-break 属性用来控制背景怎样在这些不同的盒子中显示

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

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

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

文字
word-wrap
语法:word-wrap: normal|break-word

normal:使用浏览器默认的换行

break-all:允许在单词内换行

text-overflow
text-overflow设置或检索当当前行超过指定容器的边界时如何显示,属性有两个值选择:

clip:修剪文本

ellipsis:显示省略符号来代表被修剪的文本

text-shadow
text-shadow可向文本应用阴影。能够规定水平阴影、垂直阴影、模糊距离,以及阴影的颜色

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

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

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

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

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

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

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

四、transition 过渡
transition属性可以被指定为一个或多个CSS属性的过渡效果,多个属性之间用逗号进行分隔,必须规定两项内容:

过度效果

持续时间

语法如下:

transition: CSS属性,花费时间,效果曲线(默认ease),延迟时间(默认0)
上面为简写模式,也可以分开写各个属性

transition-property: width; 
transition-duration: 1s;
transition-timing-function: linear;
transition-delay: 2s;
五、transform 转换
transform属性允许你旋转,缩放,倾斜或平移给定元素

transform-origin:转换元素的位置(围绕那个点进行转换),默认值为(x,y,z):(50%,50%,0)

使用方式:

transform: translate(120px, 50%):位移

transform: scale(2, 0.5):缩放

transform: rotate(0.5turn):旋转

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

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

animation也有很多的属性

animation-name:动画名称

animation-duration:动画持续时间

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

animation-delay:动画延迟时间

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

animation-direction:动画执行方向

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

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

七、渐变
颜色渐变是指在两个颜色之间平稳的过渡,css3渐变包括

linear-gradient:线性渐变


background-image: linear-gradient(direction, color-stop1, color-stop2, ...);


radial-gradient:径向渐变


linear-gradient(0deg, red, green);


八、其他
关于css3其他的新特性还包括flex弹性布局、Grid栅格布局,

除此之外,还包括多列布局、媒体查询、混合模式等等
 

26)了解过哪些页面布局?

几种常见布局
table布局
父级容器—display: table
子级容器—display:table-cell
例子

<!DOCTYPE html><html lang="zh_CN">  <head>    <meta charset="UTF-8" />    <meta http-equiv="X-UA-Compatible" content="IE=edge" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <title>Document</title>    <style>      .box {        width: 600px;        height: 100px;        display: table;      }      .left,      .right {        display: table-cell;      }      .left {        background: yellowgreen;      }      .right {        background: skyblue;      }    </style>  </head>  <body>    <div class="box">      <div class="left"></div>      <div class="right"></div>    </div>  </body></html>

float布局
特点:

元素"浮动"
脱离文档流
但不脱离文本流
对自身的影响: 形成"块"(BFC,具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素)、位置尽量靠上、位置尽量靠左(右),无法满足会靠下
对兄弟的影响: 上面贴非float元素、旁边贴float元素、不影响其它块级元素位置、影响其它块级元素内部文本

flexbox布局
布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现;2009年,W3C 提出了一种新的方案----Flex 布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。
Flex是Flexible Box的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性;任何一个容器都可以指定为Flex布局,行内元素也可以使用Flex布局; webkit内核的浏览器,必须加上-webkit-前缀。

弹性盒子
盒子本来就是并列的
指定宽度即可
水平竖直居中 flex 实现

<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <meta http-equiv="X-UA-Compatible" content="ie=edge" />    <title>水平竖直居中布局解决方案-flex+justify-content</title>    <style>      * {        margin: 0;        padding: 0;      }      #parent {        width: 100%;        height: 400px;        background: #ccc;        display: flex;        align-items: center;        justify-content: center;      }      #child {        width: 300px;        height: 200px;        background: #c9394a;      }    </style>  </head>  <body>    <!-- 定义父级元素 -->    <div id="parent">      <!-- 定义子级元素 -->      <div id="child"></div>    </div>  </body></html>

Grid布局
网格布局(Grid)是最强大的 CSS 布局方案。
它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。以前,只能通过复杂的CSS框架达到的效果,现在浏览器内置了;Grid 布局与 Flex 布局有一定的相似性,都可以指定容器内部多个项目的位置。但是,它们也存在重大区别。Flex 布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局。Grid 布局远比Flex布局强大。

<!DOCTYPE html><html lang="zh_CN">  <head>    <meta charset="UTF-8" />    <meta http-equiv="X-UA-Compatible" content="IE=edge" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <title>Document</title>    <style>      .wrapper {        display: grid;        grid-template-columns: repeat(3, 1fr);        grid-gap: 10px;      }    </style>  </head>  <body>    <div class="wrapper">      <div>One</div>      <div>Two</div>      <div>Three</div>      <div>Four</div>      <div>Five</div>    </div>  </body></html>

 

columns布局
CSS属性 columns 用来设置元素的列宽和列数。
例子

<!DOCTYPE html><html lang="zh_CN">  <head>    <meta charset="UTF-8" />    <meta http-equiv="X-UA-Compatible" content="IE=edge" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <title>Document</title>    <style>      .content-box {        columns: 3 auto;      }    </style>  </head>  <body>    <p class="content-box">      JavaScript 框架 WHY VUE.JS?起步 GITHUB 易用 已经会了      HTML、CSS、JavaScript?即刻阅读指南开始构建应用! 灵活      不断繁荣的生态系统,可以在一个库和一套完整框架之间自如伸.JavaScript 框架      WHY VUE.JS?起步 GITHUB 易用 已经会了      HTML、CSS、JavaScript?即刻阅读指南开始构建应用! 灵活      不断繁荣的生态系统,可以在一个库和一套完整框架之间自如伸.JavaScript 框架      WHY VUE.JS?起步 GITHUB 易用 已经会了      HTML、CSS、JavaScript?即刻阅读指南开始构建应用! 灵活      不断繁荣的生态系统,可以在一个库和一套完整框架之间自如伸.JavaScript 框架      WHY VUE.JS?起步 GITHUB 易用 已经会了      HTML、CSS、JavaScript?即刻阅读指南开始构建应用! 灵活      不断繁荣的生态系统,可以在一个库和一套完整框架之间自如伸.JavaScript 框架      WHY VUE.JS?起步 GITHUB 易用 已经会了      HTML、CSS、JavaScript?即刻阅读指南开始构建应用! 灵活      不断繁荣的生态系统,可以在一个库和一套完整框架之间自如伸.    </p>  </body></html>

27 用animation做过什么?做过哪些动画?

做走马灯  原文链接:用animation制作走马灯 - 掘金

做3d魔方      本文链接:使用 C3 Animation 做一个3D魔方_Jaosncode的博客-CSDN博客 

用animation做无缝匀速滚动   本文链接:用animation做无缝匀速滚动_是黄小仙呀的博客-CSDN博客_如何设置animation动画为匀速运动

 做弹力球            本文链接:用动画(animation)做弹力球_lxhby520的博客-CSDN博客 

使用animation制作进度条   本文链接:使用animation制作进度条_乐之者java的博客-CSDN博客

28 Sass写一个数组?

// 定义数组,数组元素用逗号隔开$liColor:#f5ad1b,#5f89ce,#94bf45,#da8ec5,#78bfc2,#bec278; // 开始 @each 循环遍历数组// $c 作为循环变量,代表了数组的元素,不是索引~!!!@each $c in $liColor{     $i:index($liColor,$c);        // 获取 $c 在数组中的索引,并赋值给 $i 赋值用冒号,不是等号~!     li:nth-child( #{$i} ){      // 经典的地方来了,SCSS 循环是从 1 开始,不是 0 哦~       background: $c;           // 背景色       &:hover{         background: lighten($c,10%);    // hover 后的颜色       }     }}

29)rem出现很小的小数手机上会发生什么,

为了保证大部分分辨率下计算出的根字体大小都为整数,所以约定根字体大小的计算公式为:
分辨率宽度 / 10;

在iPhone6下,如果一个元素的宽和高都是1.75rem,其在浏览器内的渲染尺寸
应该是1.75 * 37.5 = 65.625px;

但真实渲染尺寸却是另外一种情况:

    有的宽度是66px,有的却是65px,而且顺序上毫无规律。
    
    如果浏览器统一做四舍五入处理,那么所有的色块尺寸也应该是一样的,不会出现部分向上取整,
部分向下取整。

设想:

    浏览器在渲染时所做的舍入处理只是应用在元素的渲染尺寸上,其真实占据的空间依旧是原始大小。
    
    也就是说如果一个元素尺寸是0.625px,那么其渲染尺寸应该是1px,空出的0.375px空间由
其临近的元素填充;

    
    同样道理,如果一个元素尺寸是0.375px,其渲染尺寸就应该是0,但是其会占据
临近元素0.375px的空间。

30 什么时候用less

函数式编程css自定义变量用于整体主题调整嵌套语法简化开发复杂度

页面层级结构多,重复使用的css代码较多时

31 animation和transition

1.animation概念
可以用 name 设置动画的名称,用 duration 设置动画完成的周期,用 timing-function 设置动
画的速度曲线,delay 设置动画什么时候开始,iteration-count 设置动画播放的次数,direction 规定下一
个周期是否逆向的播放,play-state 动画是否正在进行或者暂停,fill-mode 设置动画停了之后位置什么状态

animation 属性是一个简写属性,用于设置六个动画属性:
animation-name    规定需要绑定到选择器的 keyframe 名称。
animation-duration    规定完成动画所花费的时间,以秒或毫秒计。
animation-timing-function    规定动画的速度曲线。
animation-delay    规定在动画开始之前的延迟。
animation-iteration-count    规定动画应该播放的次数。
animation-direction    规定是否应该轮流反向播放动画。


2.transition概念
用 property 去设置过渡效果的属性名称,duration 设置过渡效果的周期,timing-function 规
定速度效果的速度曲线,delay 设定过渡效果什么时候开始;

transition 属性是一个简写属性,用于设置四个过渡属性:
transition-property    规定设置过渡效果的 CSS 属性的名称。
transition-duration    规定完成过渡效果需要多少秒或毫秒。
transition-timing-function    规定速度效果的速度曲线。
transition-delay    定义过渡效果何时开始。



3.区别


1)transition 是过渡,是样式值的变化的过程,只有开始和结束;animation 其实也叫关键帧,通过和 keyframe 结合可以设置中间帧的一个状态;
2)animation 配合 @keyframe 可以不触发时间就触发这个过程,而 transition 需要通过 hover 或者 js 事件来配合触发;
3)animation 可以设置很多的属性,比如循环次数,动画结束的状态等等,transition 只能触发一次;
4)animation 可以结合 keyframe 设置每一帧,但是 transition 只有两帧;
 

transition可以实现简单的过渡动画效果,而animation可以实现更为复杂的动画效果 

32 移入图片让那个图片慢慢放大

DOM

<body>    <div class="box">        <div class="img">            图片        </div>    </div></body>


CSS
 

<style>    body {        width: 100vw;        height: 100vh;        display: flex;        justify-content: center;        align-items: center;    }    .box {        width: 300px;        height: 300px;        border: 1px solid black;        position: relative;    }    .img {        width: 300px;        height: 300px;        background-color: red;        font-size: 24px;        line-height: 300px;        text-align: center;        position: absolute;        transform-origin: right center;        animation: animate 3s linear;/*使用动画*/    }    /*图片的运动动画*/    @keyframes animate {        from {            transform: scale(0);            left: -110%;        }        to {            transform: scale(1);            left: 0;        }    }</style>


在这里插入图片描述

33 盒子模型概念

盒模型的概念

盒模型是CSS布局的基石,规定了网页元素如何显示以及元素间相互关系。CSS定义所有的元素都可以拥有像盒子一样的外形和平面空间。即都包含内容区、补白(内填充)、边框、边界(外边距)这就是盒模型。

盒模型的组成

盒模型组成 = content(内容) + padding(内填充) + border(边框) + margin(外边距)

内填充:padding,在设定页面中一个元素内容到元素的边缘(边   框) 之间的距离。 也称补白。padding不可以写负值!
 

34 引用样式的方式有哪几种?他们的优先级排序怎么样?

一共有4中方式,分别为内联、内嵌、外联、导入。

1、内联(行内样式) - 在标签内直接写样式,

style=""<div style="width: 300px;height: 300px"></div>



2、内嵌(内部样式) - 在head标签里,加一个style标签,在style里写样式

<head>    <meta charset="UTF-8"/>    <title>document</title>    <style>        div {            background-color: red;        }    </style></head>



3、外联(外部样式) - 新建一个.css文件,通过link来引入样式

<link rel="stylesheet" href="css/index.css">



4、导入(导入样式) - 在head标签里,加一个style标签,再写@import url(),跟用link的方式差不多

<head>    <meta charset="UTF-8"/>    <title>document</title>    <style>        @import url(css/index.css);    </style></head>



5、优先级

1、就近原则

2.理论上:内联>内嵌>外联>导入

3.实际上:内嵌、外联、导入在同一个文件头部,在CSS选择器权值相同的情况下,谁离相应的代码近,谁的优先级高
 

35 px,em,rem,%,vm,vh

1.px

px就是像素,也是我们现在经常使用的基本单位,比如常常听到的电脑像素是1024x768的,表示的是水平方向是1024个像素点,垂直方向是768个像素点。

2.em

em参考物是父元素的font-size,默认字体大小是16px,所以1em不是固定值,因为它会继承父元素的字体大小

3.rem

rem参考物是相对于根元素,我们在使用时可以在根元素设置一个参考值即可,相对于em使用,减少很大运算工作量,例:html大小为10px,12rem就是120px

4.%

% 是相对于父元素的大小设定的比率,position:absolute;的元素是相对于已经定位的父元素,position:fixed;的元素是相对可视窗口

5、vw

css3新单位,viewpoint width的缩写,视窗宽度,1vw等于视窗宽度的1%。

举个例子:浏览器宽度1200px, 1 vw = 1200px/100 = 12 px。

再举个例子:浏览器宽度1200px, 1 vw = 1200px/100 = 12 px

6.vh

vm相对于视口的宽度。视口被均分为100单位

h1 {
    font-size: 8vh;
}

再举个例子:浏览器高度900px, 1 vh = 900px/100 = 9 px

总结:

  1.vw:1vw等于视口宽度的1%。
  2.vh:1vh等于视口高度的1%。

 

36 display的值和作用

1、display的值有:

none,inline,block,list-item,inline-block,table,inline-table,table-caption,table-cell,table-row,table-row-group,table-column,table-column-group,table-footer-group,table-header-group,run-in,box,inline-box,flexbox,inline-flexbox,flex,inline-flex

2、作用:

none: 表示隐藏对象,与visibility属性的hidden值不同,display:none不为被隐藏的对象保留物理空间 ,然visibility:hidden就保留

inline(默认值):表示指定对象为内联元素

block: 指定对象为块元素。

list-item: 指定对象为列表项目

inline-block: 指定对象为内联块元素。(这是CSS2中的属性)

table: 指定对象作为块元素级的表格。类同于html标签table(CSS2)

inline-table: 指定对象作为内联元素级的表格。类同于html标签table(CSS2)

table-caption: 指定对象作为表格标题。类同于html标签caption(CSS2)

table-cell: 指定对象作为表格单元格。类同于html标签td(CSS2)

table-row: 指定对象作为表格行。类同于html标签tr(CSS2)

table-row-group: 指定对象作为表格行组。类同于html标签tbody(CSS2)

table-column: 指定对象作为表格列。类同于html标签col(CSS2)

table-column-group: 指定对象作为表格列组显示。类同于html标签colgroup(CSS2)

table-header-group: 指定对象作为表格标题组。类同于html标签thead(CSS2)

table-footer-group: 指定对象作为表格脚注组。类同于html标签tfoot(CSS2)

run-in: 根据上下文决定对象是内联对象还是块级对象。(CSS3)

box: 将对象作为弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3)

inline-box: 将对象作为内联块级弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3)

flexbox: 将对象作为弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3)

inline-flexbox: 将对象作为内联块级弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3)

flex: 将对象作为弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3)

inline-flex: 将对象作为内联块级弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3)
 

37列举两种清除浮动的方法(代码实现或者描述思路)

实例:

  HTML代码代码

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>清除浮动</title>    <style>        #parent{            border: 1px solid black;        }        #child{            width: 100px;            height: 100px;            background: red;            float: left;        }    </style></head><body>    <div id="parent">        <div id="child"></div>    </div>   </body></html>

效果图-----未清除浮动
效果图
  效果图-----已清除浮动
在这里插入图片描述

 当为子元素设置了浮动,如果不清除浮动,那么父元素将会出现高度塌陷的现象。所以当我们设置了浮动后,就要解决浮动带来的影响。下面就要我们介绍几种清除浮动的方法!

方法一:额外标签法

  给谁清除浮动,就在其后额外添加一个空白标签 ,给其设置clear:both。

  优点:通俗易懂,书写方便。

  缺点:添加许多无意义的标签,结构化比较差。

  clear:both:本质就是闭合浮动, 就是让父盒子闭合出口和入口,不让子盒子出来 。

  css样式

#clear{    clear: both;}



  html代码

<div id="parent">    <div id="child"></div>    <!-- 方法一  额外标签法 -->    <div id="clear"></div></div>

方法二:父元素添加overflow:hidden

  通过触发BFC方式,实现清除浮动

  优点:代码简洁

  缺点:内容增多的时候容易造成不会自动换行导致内容被隐藏掉,无法显示要溢出的元素。

  css样式

#parent{    overflow: hidden;}



方法三:使用after伪元素清除浮动

  优点:符合闭合浮动思想,结构语义化正确。

  缺点:ie6-7不支持伪元素:after,使用zoom:1触发hasLayout。

  css样式


方法四:使用before和after双伪元素清除浮动

  优点:代码更简洁

  缺点:用zoom:1触发hasLayout.

  css样式

#parent:after,#parent:before{content: "";display: table;}#parent:after{    clear: both;}#parent{    *zoom: 1;}



方法五:为父元素设置高度

  缺点: 需要手动添加高度,如何后面的高度发生变化,还要再次修改高度,给后期的维护带来麻烦。

  优点: 简单粗暴直接有效,清除了浮动带来的影响。
 

38 盒子模型(怪异模型)

标准盒子模型和怪异盒子模型(IE盒子模型) 

在标准模式下,一个块的总宽度 = 内容的width + padding(左右) + border(左右) + margin(左右)

设置padding和border会将盒子撑大,在设置的宽高外产生

 

在怪异模式下,一个块的总宽度 = 内容的width + margin(左右)(这里的width包含了padding(左右)和border(左右)的值),设置的padding和border会在原有的宽高里面产生,不会撑开盒子

例如一个div:

 div{        width:100px;        height:100px;        padding:20px;        border:2px solid #000;    }



在标准模式下:总宽度为100px;


在怪异模式下:总宽度为144px;


4.两种模式的转换(通过box-sizing)
box-sizing中比较常用的两个属性值为 content-box 和 border-box ,它可以改变盒子模型的解析计算模式,可以参考上面的代码案例。

当设置box-sizing:content-box时,采用标准模式进行计算,默认就是这种模式;
当设置box-sizing:border-box时,采用怪异模式进行计算
 

39 谈谈fixed ,relative , absolute

.relative相对定位

相对定位:设置相对定位的盒子会相对它原来的位置,通过指定偏移,到达新的位置,但是原来的位置会被保留下来,且仍在标准文档流中,它对父级盒子和相邻的盒子都没有任何影响。

absolute 绝对定位

绝对定位:设置绝对定位的盒子会相对于距离最近的设置了相对定位的祖先元素进行定位,如果一直找不到具有相对定位的祖先元素,就相对于浏览器窗口定位,且会使元素脱离文档流。

fixed 固定定位

固定定位:设置了固定定位的盒子只会相对于浏览器窗口进行定位,也就是窗口中左上角的原点

40 float和absolute有什么区别?

1》文字内容是否会被覆盖

float浮动,当元素通过float来脱离文档流时,虽然其他的元素会当其不存在,但其他元素的内容还是会把这个元素占的位置让出来。也就是该元素浮动在另外一个有文字内容的元素上时,文字内容并不会被浮动的元素覆盖,而是环绕在周围。如:

在这里插入图片描述

absolute脱离文档流的时候,其他元素和元素中的文本都会无视掉他,因此不会像float那样将其他元素的内容挤到旁边去。如:

在这里插入图片描述

2》相对何处进行定位

当一个元素浮动之后,它会被移出正常的文档流,然后向左或者向右平移,一直平移直到碰到了所处的容器的边框,或者碰到另外一个浮动的元素。

设置绝对定位的盒子会相对于距离最近的设置了相对定位的祖先元素进行定位,且会使元素脱离文档流,如果一直找不到具有相对定位的祖先元素,就相对于浏览器窗口定位。

41 代码实现3栏效果,左右两栏固定宽度,中间栏随着浏览器宽度自适应变化

1 flex布局

<section class="layout flexbox">    <style>        .layout.flexbox{          margin-top: 110px;        }        .layout.flexbox .left-center-right{          display: flex;        }        .layout.flexbox .left{          width: 300px;          background: red;        }        .layout.flexbox .center{          flex:1;          background: yellow;        }        .layout.flexbox .right{          width: 300px;          background: blue;        }    </style>    <h1>三栏布局</h1>    <article class="left-center-right">        <div class="left"></div>        <div class="center">        <h2>flexbox解决方案</h2>        1.这是三栏布局的felx解决方案;        2.这是三栏布局的flex解决方案;        </div>        <div class="right"></div>    </article></section>

felxbox布局是css3里新出的一个,它就是为了解决上述两种方式的不足出现的,是比较完美的一个。目前移动端的布局也都是用flexbox。 
felxbox的缺点就是不能兼容IE8及以下浏览器。

2 表格布局 

<section class="layout table">    <style>        .layout.table .left-center-right{          width:100%;          height: 100px;          display: table;        }        .layout.table .left-center-right>div{          display: table-cell;        }        .layout.table .left{          width: 300px;          background: red;        }        .layout.table .center{          background: yellow;        }        .layout.table .right{          width: 300px;          background: blue;        }    </style>    <h1>三栏布局</h1>    <article class="left-center-right">        <div class="left"></div>        <div class="center">        <h2>表格布局解决方案</h2>        1.这是三栏布局的表格解决方案;        2.这是三栏布局的表格解决方案;        </div>        <div class="right"></div>    </article></section>

 5.网格布局

<section class="layout grid">    <style>        .layout.grid .left-center-right{          width:100%;          display: grid;          grid-template-rows: 100px;          grid-template-columns: 300px auto 300px;        }        .layout.grid .left-center-right>div{         }        .layout.grid .left{          width: 300px;          background: red;        }        .layout.grid .center{          background: yellow;        }        .layout.grid .right{           background: blue;        }    </style>    <h1>三栏布局</h1>    <article class="left-center-right">        <div class="left"></div>        <div class="center">        <h2>网格布局解决方案</h2>        1.这是三栏布局的网格布局解决方案;        2.这是三栏布局的网格布局解决方案;        </div>        <div class="right"></div>    </article></section>

42 css选择器的权重

* 第零等:!important,大过了其它任何设置 权值为 infinity 。
* 第一等:代表内联样式,如:style='',权值为1000。
* 第二等:代表ID选择器,如:#content,权值为0100。
* 第三等:代表类、伪类和属性选择器,如.content,权值为0010。
* 第四等:代表标签选择器和伪元素选择器,如div p,权值为0001。
* 第五等:通配符、子选择器、相邻选择器等的。如*、>、+,权值为0000。
* 第六等:继承的样式没有权值,通配选择器定义的规则优先级高于元素继承过来的规则的优先级。

43 transition transform translate 之间的区别 transform的属性有哪些?

transition的优点在于简单易用,但是它有几个很大的局限。
(1)transition需要事件触发,所以没法在网页加载时自动发生。
(2)transition是一次性的,不能重复发生,除非再次触发。
(3)transition只有两个状态,开始状态和结束状态,不能定义中间状态。
(4)一条transition规则,只能定义一个属性的变化,不能涉及多个属性。

transform是使元素变换,变形

 transform中的四个方法

1.旋转rotate
rotate:通过指定的角度参数对原元素指定一个效果。
如果设置的值为正数表示顺时针旋转,如果设置的值为负数,则表示逆时针旋转。如:transform:rotate(30deg);

image-20200803155143384

2.移动translate
translate() 根据左(X轴)和顶部(Y轴)位置给定的参数,从当前元素位置移动。

如:transform:translate(100px,20px):

image-20200803155216425

translateX
通过给定一个X方向上的数目指定一个translation。只向x轴进行移动元素,同样其基点是元素中心点,也可以根据transform-origin改变基点位置
transform:translateX(100px):

image-20200803155241091

translateY
通过给定Y方向的数目指定一个translation。只向Y轴进行移动,基点在元素心点,可以通过transform-origin改变基点位置。
transform:translateY(20px):

image-20200803155313026

3.缩放scale
缩放scale和移动translate是有点相似的,也是有三种情况:下面我们具体来看看这三种情况具体使用方法:
注意:默认值是1,它的值放大是比1大,缩小比1小。
1、scale(x,y) 定义 2D 缩放转换,改变元素的宽度和高度。

如:transform:scale(2,1.5); 

如果只写入一个参数就按照等比例宽高同时缩放 如transform:scale(1.5);  宽高都变为1.5倍

image-20200803155332956

2、scaleX(n) 定义 2D 缩放转换,改变元素的宽度。

如:transform:scaleX(2):

image-20200803155351125

3、scaleY(n) 定义 2D 缩放转换,改变元素的高度。

如:transform:scaleY(2):

image-20200803155408877

4.扭曲skew
1、skew(x-angle,y-angle) 定义 2D 倾斜转换,沿着 X 和 Y 轴。

如:transform:skew(30deg,10deg);

image-20200803155433112

2、skewX(angle) 定义 2D 倾斜转换,沿着 X 轴。

如:transform:skewX(30deg);

image-20200803155514487

3、skewY(angle) 定义 2D 倾斜转换,沿着 Y 轴。

如:transform:skewY(10deg);

image-20200803155539603

 当然还有3d的效果

44 css3中的选择器

 

 

 

46 用CSS实现一个背景色为红色,半径为200px的圆,并设置不停的上下移动动画

一、DOM

<body>    <div class="box"></div></body>


二、CSS

<style>    .box {        width: 200px;        height: 200px;        background-color: red;        border-radius: 50%;        position: relative;        left: 0;        top: 0;        animation: move 2s linear infinite;    }    /*        此方式为动画方式,使用的是定位的top属性        还可以设置            transform: translateY();            margin-top    */    @keyframes move {        form {            top: 0;        }        50% {            top: 100px;        }        to {            top: 0;        }    }</style>


三、结果

在这里插入图片描述

javascript以及es6相关

 null和undefined的区别? js的数据类型?

一、基本数据类型

在介绍undefined与null之前,我们先来了解一下ECMAScript中的数据类型。在ECMAScript中有六种简单数据类型(也称为基本数据类型): Undefined、Null、Boolean、Number 和 String、Symbol (ES6中引入) 。还有一种复杂数据类型——Object。

Undefined和Null都只有一个值,分别对应着undefined和null。这两种不同类型的值,既有着不同的语义和场景,又表现出较为相似的行为。

二、undefined

undefined 的字面意思就是:未定义的值 。这个值的语义是,希望表示一个变量最原始的状态,而非人为操作的结果 。 这种原始状态会在以下 4 种场景中出现:

1、声明一个变量,但是没有赋值

  

var foo;

console.log(foo); // undefined

复制代码

访问 foo,返回了 undefined,表示这个变量自从声明了以后,就从来没有使用过,也没有定义过任何有效的值。

2、访问对象上不存在的属性或者未定义的变量

  

console.log(Object.foo); // undefined

console.log(typeof demo); // undefined

复制代码

访问 Object 对象上的 foo 属性,返回 undefined , 表示Object 上不存在或者没有定义名为 foo 的属性;对未声明的变量执行typeof操作符返回了undefined值。

3、函数定义了形参,但没有传递实参

  

//函数定义了形参 a

function fn(a) {

console.log(a); // undefined

}

fn(); //未传递实参

复制代码

函数 fn 定义了形参 a,但 fn 被调用时没有传递参数,因此,fn 运行时的参数 a 就是一个原始的、未被赋值的变量。

4、使用void对表达式求值

  

void 0 ; // undefined

void false; // undefined

void []; // undefined

void null; // undefined

void function fn(){} ; // undefined

复制代码

ECMAScript 明确规定 void 操作符 对任何表达式求值都返回 undefined ,这和函数执行操作后没有返回值的作用是一样的,JavaScript 中的函数都有返回值,当没有 return 操作时,就默认返回一个原始的状态值,这个值就是 undefined,表明函数的返回值未被定义。

因此,undefined 一般都来自于某个表达式最原始的状态值,不是人为操作的结果。当然,你也可以手动给一个变量赋值 undefined,但这样做没有意义,因为一个变量不赋值就是 undefined 。

三、null

null 的字面意思是:空值 。这个值的语义是,希望表示一个对象被人为的重置为空对象,而非一个变量最原始的状态 。 在内存里的表示就是,栈中的变量没有指向堆中的内存对象。

1、一般在以下两种情况下我们会将变量赋值为null

如果定义的变量在将来用于保存对象,那么最好将该变量初始化为null,而不是其他值。换句话说,只要意在保存对象的变量还没有真正保存对象,就应该明确地让该变量保存null值,这样有助于进一步区分null和undefined。

当一个数据不再需要使用时,我们最好通过将其值设置为null来释放其引用,这个做法叫做解除引用。不过解除一个值的引用并不意味着自动回收改值所占用的内存。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器在下次运行时将其回收。解除引用还有助于消除有可能出现的循环引用的情况。这一做法适用于大多数全局变量和全局对象的属性,局部变量会在它们离开执行环境时(函数执行完时)自动被解除引用。

2、特殊的typeof null

当我们使用typeof操作符检测null值,我们理所应当地认为应该返"Null"类型呀,但是事实返回的类型却是"object"。

  

var data = null;

console.log(typeof data); // "object"

复制代码

是不是很奇怪?其实我们可以从两方面来理解这个结果:

一方面从逻辑角度来看,null值表示一个空对象指针,它代表的其实就是一个空对象,所以使用typeof操作符检测时返回"object"也是可以理解的。

另一方面,其实在JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的(对象的类型标签是 0)。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null的类型标签也成为了 0,typeof null就错误的返回了"object"。在ES6中,当时曾经有提案为历史平凡, 将type null的值纠正为null, 但最后提案被拒了,所以还是保持"object"类型。

四、总结

用一句话总结两者的区别就是:undefined 表示一个变量自然的、最原始的状态值,而 null 则表示一个变量被人为的设置为空对象,而不是原始状态。所以,在实际使用过程中,为了保证变量所代表的语义,不要对一个变量显式的赋值 undefined,当需要释放一个对象时,直接赋值为 null 即可,重点:给一个变量赋值为null,可以手动释放该变量占用的内存,而给变量赋值为undefined依旧会给该变量分配内存空间

 js 的继承实现方式有哪些,列举两个例子

寄生组合继承
这个方法有点意思,融合了原型继承和call继承的优点,真正实现了私对私,公对公~为此,我们需要在call继承的基础上加上原型继承。

原型继承的思想是让子类原型=父类的一个实例,即Child.prototype = new Parent,换句话说,即Child.prototype.__proto__ = Parent.prototype(父类实例原型链指向父类原型,没毛病吧)。
从另一个角度看,我们不创建新的父类实例了!而是让子类原型的__proto__重定向,原本指向Object.prototype,现在让它指向Parent.prototype。实现了原型继承同样的效果。——实际上就是原型继承。

但还有一个问题,IE6~8下是不允许我们操作__proto__的,我们使用Object.create的方法代替。
Object.create(A):创建一个空对象,让这个空对象的__proto__指向A。

// 寄生组合继承function Parent(){    this.x = 100;}Parent.prototype.getX = function getX(){    return this.x;}function Child(){    Parent.call(this);      // call继承当然要保留,实现私对私    this.y = 200;}Child.prototype = Object.create(Parent.prototype);    // 另类原型继承Child.prototype.getY = function getY(){    return this.y;}let c1 = new Child;console.log(c1);


Child.prototype = Object.create(Parent.prototype)这句核心代码实际上和Child.prototype = new Parent别无二致,只是创建的不是父类的实例,而是一个空对象,然后手动更改原型链指向而已。这个操作也可以让父类的公有属性方法成为子类的公有属性方法。

ES6中的类和继承

class Parent{    constructor(){         // constructor函数实际上是Parent函数的私有属性方法        this.x = 100;    }    getX(){             // 在Parent.prototype上的公有属性方法        return this.x;    }}// 原本毫无关联的两个类,因为extends而成为了父子class Child extends Parent{    constructor(){        super();            // 只要用extends实现继承,就要在constructor函数的第一行加一句super(),否则会报错                 this.y = 200;    }    getY(){                  return this.y;    }}



ES6中的继承可以实现与寄生组合继承同样的效果,但写法是不是极其简单呐~
 

eval是什么?

 用什么会导致内存泄漏?

 js深度克隆的代码实现?

 同源策略,跨域,后台如何解决跨域,html有哪些标签可以跨域

es6

js自己封装一个方法

 jq用过哪些方法?

 promise?

 触摸有几个事件?

什么时候会发生跨域问题

 匿名函数

 This指向问题

 JQ,JS,vue 三者的区别

 用jq实现双向绑定!

 ajax的实现

ajax的实现

 在数组上新增一个方法,实现复制。

 期望:[1,2,3].copy() //输出 [1,2,3,1,2,3]

 .使用闭包实现一个方法,第一次调用返回1,第二次返回2,第三次3,以此类推。

       期望

count()//输出1count()//输出2count()//输出3……

      实现

<script>    function outer() {        let number = 0;        return function inner() {            console.log(++number);        }    }    let count = outer();    count();    count();    count();</script>

 .封装一个函数,参数是定时器的时间,.then执行回调函数。

期望

sleep(5000).then(() => console.log('我会在5秒后打印'));



Promise创建

var promise = new Promise(function(resolve, reject) {    //异步处理    //处理结束后、调用resolve或reject,当异步代码执行成功时,我们才会调用resolve(...),当异步代码失败时就会调用reject(...)    //对于已经实例化过的promise对象可以调用promise.then()方法,传递resolve和reject方法作为回调});



程序实现

<script>    function sleep(time) {        return new Promise((resolve) => setTimeout(resolve, time));    }    sleep(5000).then(() => console.log('我会在5秒后打印'));</script>

 说一说前端性能优化有哪些方法?

这里说一下前端性能优化的七大手段,包括减少请求数量、减小资源大小、优化网络连接、优化资源加载、减少重绘回流、使用性能更好的API和构建优化

减少请求数量

【合并】

  如果不进行文件合并,有如下3个隐患

  1、文件与文件之间有插入的上行请求,增加了N-1个网络延迟

  2、受丢包问题影响更严重

  3、经过代理服务器时可能会被断开

  但是,文件合并本身也有自己的问题

  1、首屏渲染问题

  2、缓存失效问题

  所以,对于文件合并,有如下改进建议

  1、公共库合并

  2、不同页面单独合并

【图片处理】

  1、雪碧图

  CSS雪碧图是以前非常流行的技术,把网站上的一些图片整合到一张单独的图片中,可以减少网站的HTTP请求数量,但是当整合图片比较大时,一次加载比较慢。随着字体图片、SVG图片的流行,该技术渐渐退出了历史舞台

  2、Base64

  将图片的内容以Base64格式内嵌到HTML中,可以减少HTTP请求数量。但是,由于Base64编码用8位字符表示信息中的6个位,所以编码后大小大约比原始值扩大了 33%

  3、使用字体图标来代替图片

【减少重定向】

  尽量避免使用重定向,当页面发生了重定向,就会延迟整个HTML文档的传输。在HTML文档到达之前,页面中不会呈现任何东西,也没有任何组件会被下载,降低了用户体验

  如果一定要使用重定向,如http重定向到https,要使用301永久重定向,而不是302临时重定向。因为,如果使用302,则每一次访问http,都会被重定向到https的页面。而永久重定向,在第一次从http重定向到https之后 ,每次访问http,会直接返回https的页面

【使用缓存】

  使用cach-control或expires这类强缓存时,缓存不过期的情况下,不向服务器发送请求。强缓存过期时,会使用last-modified或etag这类协商缓存,向服务器发送请求,如果资源没有变化,则服务器返回304响应,浏览器继续从本地缓存加载资源;如果资源更新了,则服务器将更新后的资源发送到浏览器,并返回200响应

【不使用CSS @import】

  CSS的@import会造成额外的请求

【避免使用空的src和href】

  a标签设置空的href,会重定向到当前的页面地址

  form设置空的method,会提交表单到当前的页面地址

减小资源大小

【压缩】

  1、HTML压缩

  HTML代码压缩就是压缩在文本文件中有意义,但是在HTML中不显示的字符,包括空格,制表符,换行符等

  2、CSS压缩

  CSS压缩包括无效代码删除与CSS语义合并

  3、JS压缩与混乱

  JS压缩与混乱包括无效字符及注释的删除、代码语义的缩减和优化、降低代码可读性,实现代码保护

  4、图片压缩

  针对真实图片情况,舍弃一些相对无关紧要的色彩信息

【webp】

  在安卓下可以使用webp格式的图片,它具有更优的图像数据压缩算法,能带来更小的图片体积,同等画面质量下,体积比jpg、png少了25%以上,而且同时具备了无损和有损的压缩模式、Alpha 透明以及动画的特性

【开启gzip】

  HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术。大流量的WEB站点常常使用GZIP压缩技术来让用户感受更快的速度。这一般是指WWW服务器中安装的一个功能,当有人来访问这个服务器中的网站时,服务器中的这个功能就将网页内容压缩后传输到来访的电脑浏览器中显示出来。一般对纯文本内容可压缩到原大小的40%

优化网络连接

【使用CDN】

  CDN全称是Content Delivery Network,即内容分发网络,它能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度

【使用DNS预解析】

  当浏览器访问一个域名的时候,需要解析一次DNS,获得对应域名的ip地址。在解析过程中,按照浏览器缓存系统缓存路由器缓存ISP(运营商)DNS缓存根域名服务器顶级域名服务器主域名服务器的顺序,逐步读取缓存,直到拿到IP地址

  DNS Prefetch,即DNS预解析就是根据浏览器定义的规则,提前解析之后可能会用到的域名,使解析结果缓存到系统缓存中,缩短DNS解析时间,来提高网站的访问速度

  方法是在 head 标签里面写上几个 link 标签

  

<link rel="dns-prefecth" href="https://www.google.com">

<link rel="dns-prefecth" href="https://www.google-analytics.com">

  对以上几个网站提前解析 DNS,由于它是并行的,不会堵塞页面渲染,这样可以缩短资源加载的时间

【并行连接】

  由于在HTTP1.1协议下,chrome每个域名的最大并发数是6个。使用多个域名,可以增加并发数

【持久连接】

  使用keep-alive或presistent来建立持久连接,持久连接降低了时延和连接建立的开销,将连接保持在已调谐状态,而且减少了打开连接的潜在数量

【管道化连接】

  在HTTP2协议中,可以开启管道化连接,即单条连接的多路复用,每条连接中并发传输多个资源,这里就不需要添加域名来增加并发数了

优化资源加载

【资源加载位置】

  通过优化资源加载位置,更改资源加载时机,使尽可能快地展示出页面内容,尽可能快地使功能可用

  1、CSS文件放在head中,先外链,后本页

  2、JS文件放在body底部,先外链,后本页

  3、处理页面、处理页面布局的JS文件放在head中,如babel-polyfill.js文件、flexible.js文件

  4、body中间尽量不写style标签和script标签

【资源加载时机】

  1、异步script标签

  defer:  异步加载,在HTML解析完成后执行。defer的实际效果与将代码放在body底部类似

  async: 异步加载,加载完成后立即执行

  2、模块按需加载

  在SPA等业务逻辑比较复杂的系统中,需要根据路由来加载当前页面需要的业务模块

  按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载

  webpack 提供了两个类似的技术,优先选择的方式是使用符合 ECMAScript 提案 的 import() 语法。第二种则是使用 webpack 特定的 require.ensure

  3、使用资源预加载preload和资源预读取prefetch

  preload让浏览器提前加载指定资源,需要执行时再执行,可以加速本页面的加载速度

  prefetch告诉浏览器加载下一页面可能会用到的资源,可以加速下一个页面的加载速度

  4、资源懒加载与资源预加载

  资源延迟加载也称为懒加载,延迟加载资源或符合某些条件时才加载某些资源

  资源预加载是提前加载用户所需的资源,保证良好的用户体验

  资源懒加载和资源预加载都是一种错峰操作,在浏览器忙碌的时候不做操作,浏览器空间时,再加载资源,优化了网络性能

  

减少重绘回流

【样式设置】

  1、避免使用层级较深的选择器,或其他一些复杂的选择器,以提高CSS渲染效率

  2、避免使用CSS表达式,CSS表达式是动态设置CSS属性的强大但危险方法,它的问题就在于计算频率很快。不仅仅是在页面显示和缩放时,就是在页面滚动、乃至移动鼠标时都会要重新计算一次

  3、元素适当地定义高度或最小高度,否则元素的动态内容载入时,会出现页面元素的晃动或位置,造成回流

  4、给图片设置尺寸。如果图片不设置尺寸,首次载入时,占据空间会从0到完全出现,上下左右都可能位移,发生回流

  5、不要使用table布局,因为一个小改动可能会造成整个table重新布局。而且table渲染通常要3倍于同等元素时间

  6、能够使用CSS实现的效果,尽量使用CSS而不使用JS实现

【渲染层】

  1、此外,将需要多次重绘的元素独立为render layer渲染层,如设置absolute,可以减少重绘范围

  2、对于一些进行动画的元素,使用硬件渲染,从而避免重绘和回流

【DOM优化】

  1、缓存DOM

const div = document.getElementById('div')

  由于查询DOM比较耗时,在同一个节点无需多次查询的情况下,可以缓存DOM

  2、减少DOM深度及DOM数量

  HTML 中标签元素越多,标签的层级越深,浏览器解析DOM并绘制到浏览器中所花的时间就越长,所以应尽可能保持 DOM 元素简洁和层级较少。

  3、批量操作DOM

  由于DOM操作比较耗时,且可能会造成回流,因此要避免频繁操作DOM,可以批量操作DOM,先用字符串拼接完毕,再用innerHTML更新DOM

  4、批量操作CSS样式

  通过切换class或者使用元素的style.csstext属性去批量操作元素样式

  5、在内存中操作DOM

  使用DocumentFragment对象,让DOM操作发生在内存中,而不是页面上

  6、DOM元素离线更新

  对DOM进行相关操作时,例、appendChild等都可以使用Document Fragment对象进行离线操作,带元素“组装”完成后再一次插入页面,或者使用display:none 对元素隐藏,在元素“消失”后进行相关操作

  7、DOM读写分离

  浏览器具有惰性渲染机制,连接多次修改DOM可能只触发浏览器的一次渲染。而如果修改DOM后,立即读取DOM。为了保证读取到正确的DOM值,会触发浏览器的一次渲染。因此,修改DOM的操作要与访问DOM分开进行

  8、事件代理

  事件代理是指将事件监听器注册在父级元素上,由于子元素的事件会通过事件冒泡的方式向上传播到父节点,因此,可以由父节点的监听函数统一处理多个子元素的事件

  利用事件代理,可以减少内存使用,提高性能及降低代码复杂度

  9、防抖和节流

  使用函数节流(throttle)或函数去抖(debounce),限制某一个方法的频繁触发

  10、及时清理环境

  及时消除对象引用,清除定时器,清除事件监听器,创建最小作用域变量,可以及时回收内存

性能更好的API

  1、用对选择器

  选择器的性能排序如下所示,尽量选择性能更好的选择器

  

id选择器(#myid)

类选择器(.myclassname)

标签选择器(div,h1,p)

相邻选择器(h1+p)

子选择器(ul > li)

后代选择器(li a)

通配符选择器(*)

属性选择器(a[rel="external"])

伪类选择器(a:hover,li:nth-child)

  2、使用requestAnimationFrame来替代setTimeout和setInterval

  希望在每一帧刚开始的时候对页面进行更改,目前只有使用 requestAnimationFrame 能够保证这一点。使用 setTimeout 或者 setInterval 来触发更新页面的函数,该函数可能在一帧的中间或者结束的时间点上调用,进而导致该帧后面需要进行的事情没有完成,引发丢帧

  3、使用IntersectionObserver来实现图片可视区域的懒加载

  传统的做法中,需要使用scroll事件,并调用getBoundingClientRect方法,来实现可视区域的判断,即使使用了函数节流,也会造成页面回流。使用IntersectionObserver,则没有上述问题

  4、使用web worker

  客户端javascript一个基本的特性是单线程:比如,浏览器无法同时运行两个事件处理程序,它也无法在一个事件处理程序运行的时候触发一个计时器。Web Worker是HTML5提供的一个javascript多线程解决方案,可以将一些大计算量的代码交由web Worker运行,从而避免阻塞用户界面,在执行复杂计算和数据处理时,这个API非常有用

  但是,使用一些新的API的同时,也要注意其浏览器兼容性

webpack优化

【打包公共代码】

  使用CommonsChunkPlugin插件,将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,便存到缓存中供后续使用。这会带来速度上的提升,因为浏览器会迅速将公共的代码从缓存中取出来,而不是每次访问一个新页面时,再去加载一个更大的文件

  webpack 4 将移除 CommonsChunkPlugin, 取而代之的是两个新的配置项 optimization.splitChunks 和 optimization.runtimeChunk

  通过设置 optimization.splitChunks.chunks: "all" 来启动默认的代码分割配置项

【动态导入和按需加载】

  webpack提供了两种技术通过模块的内联函数调用来分离代码,优先选择的方式是,使用符合 ECMAScript 提案 的 import() 语法。第二种,则是使用 webpack 特定的 require.ensure

【剔除无用代码】

  tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块系统中的静态结构特性,例如 import 和 export。这个术语和概念实际上是兴起于 ES2015 模块打包工具 rollup

  JS的tree shaking主要通过uglifyjs插件来完成,CSS的tree shaking主要通过purify CSS来实现的

【长缓存优化】

  1、将hash替换为chunkhash,这样当chunk不变时,缓存依然有效

  2、使用Name而不是id

  每个 module.id 会基于默认的解析顺序(resolve order)进行增量。也就是说,当解析顺序发生变化,ID 也会随之改变

  下面来使用两个插件解决这个问题。第一个插件是 NamedModulesPlugin,将使用模块的路径,而不是数字标识符。虽然此插件有助于在开发过程中输出结果的可读性,然而执行时间会长一些。第二个选择是使用 HashedModuleIdsPlugin,推荐用于生产环境构建

【公用代码内联】

  使用html-webpack-inline-chunk-plugin插件将mainfest.js内联到html文件中

 一个页面上有大量的图片(大型电商网站),加载很慢,你有哪些方法优化这些图片的加载,给用户更好的体验。

图片懒加载,在页面上的未可视区域可以添加一个滚动条事件,判断图片位置与浏览器顶端的距离与页面的距离,如果前者小于后者,优先加载。如果为幻灯片、相册等,可以使用图片预加载技术,将当前展示图片的前一张和后一张优先下载。如果图片为css图片,可以使用CSSsprite,SVGsprite,Iconfont、Base64等技术。如果图片过大,可以使用特殊编码的图片,加载时会先加载一张压缩的特别厉害的缩略图,以提高用户体验。如果图片展示区域小于图片的真实大小,则因在服务器端根据业务需要先行进行图片压缩,图片压缩后大小与展示一致。
 

 .export和export default?

使用export和export default进行暴露
每一个js文件相当于在一个函数中运行,而函数的作用域是局部作用域,所以两个js文件之间的作用域不是共享的。
此时ES6规范就为我们提供了export和export default帮助我们将想要暴露的对象暴露出去。

export
export的暴露格式:

暴露一个变量:
export 变量名
或者定义的时候就进行了暴露
export var 变量名 = 变量值
暴露多个变量:
export {量名1,变量2,变量3}
注意: 在js中如果对直接声明的变量进行暴露是没有意义的,因为不使用任任何关键字(如:var)直接生命的变量本事就是全局的如果再使用export进行暴露是没有意义的。

export default
使用格式:
定义一个对象,将对象暴露出去:

const 对象名 = {    属性:值}export default 对象名



import进行引入
针对 export暴露的引入
格式:import {暴露的变量名1,暴露的变量名1,...} from '文件路径名'

针对 export default暴露的引入
格式:import 自定义的名字 from '文件路径名'

export和export default区别
export 和 export default 都可用于导出常量、函数、文件、模块等
在一个文件或模块中,export、import可以有多个,export default仅有一个
通过export方式导出,在导入时要加{ },且不能自定义名字,export default不用加{ },且可以自定义名字

export使用例子
a.js:

var a = 100function fun_a() {   console.log("我是a中的函数")}export {    a,    fun_a}export var b = 200


b.js

import {a,b,fun_a} from './a'console.log(a)fun_a()console.log(b)



运行b.js,报错
(安装node环境所致,安装了node环境默认使用的是commomJS规范而不是ES6规范,所以报错。没有安装node可能不会报该错)

(node:12892) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.(Use `node --trace-warnings ...` to show where the warning was created)C:\Users\86198\VScode\qianDuan\Node.js\b.js:1import {a,b,fun_a} from './a'^^^^^^SyntaxError: Cannot use import statement outside a module



解决:
在b所在的文件夹添加package.json文件,添加"type": "module",指定规范模式为ES6模式
再次运行如果报如下错误

Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'C:\Users\86198\VScode\qianDuan\Node.js\a' imported from C:\Users\86198\VScode\qianDuan\Node.js\b.jsDid you mean to import ../a.js?



是因为import的文件路径没写全,将路径进行补全
再次运行,运行成功:

100我是a中的函数200



export default使用例子
a.js

const module_a = {    getName (){       console.log("我是a中的函数")    },    a:100}export default module_a


b.js

import module_a from './a.js'console.log(module_a.a)module_a.getName()


运行b.js

100我是a中的函数



 

怎么去判断出来数组里面值为1的元素

1.该值在数组中有多个,找出所有位置

   //封装函数 在数组中找到某个值所在的所有索引位置         function indexOfAll(arr, val) {            let idxArr = [],                obj = {}            arr.forEach((item, index) => {                if (item == val) {                    idxArr.push(index)                }            })            return obj = {                [val]: idxArr            };        }        let arr = [1, 2, 3, 'hello', 'world', 23, 23, 3, 67, 3, 100];        console.log(indexOfAll(arr, 3))//{3:[2, 7, 9]}

 2,该值在数组中只有一个

返回true或者false

some()

  console.log(arr.some((item) => {            return item == 1//这里放要判断的条件和值        }))

返回索引

arr.indexOf(val)  arr.lastIndexOf(val) val为要找的值

 有一个数组,怎么去修改每一个值?

    let arr = [1, 2, 3, 4, 5];        //方法1,通过索引下标,找到要修改的元素,重新赋值    arr[0] = 10;    console.log(arr);//[10, 2, 3, 4, 5]        //方法2,使用数组的spliceAPI,参数(起始下标, 要删除元素的个数, 要插入的元素)    arr.splice(1, 1, 20);    console.log(arr);//[10, 20, 3, 4, 5]    //方法3,都修改成同一个值    arr.fill(0);    console.log(arr);//[0, 0, 0, 0, 0]//  方法四  使用map()方法 let arr = [1, 2, 3, 'hello', 'world', 23, 23, 3, 67, 3, 100]; let arr2 = arr.map((item, index) => {            return item + "元"        })        console.log(arr2)//['1元', '2元', '3元', 'hello元', 'world元', '23元', '23元', '3元', '67元', '3元', '100元']//方法五  使用循环 foreach  、for 、for of、for in ....  

 数组去重

Methods 1: 思路:定义一个新数组,并存放原数组的第一个元素,然后将元素组一一和新数组的元素对比,若不同则存放在新数组中。

        function unique(arr) {            let newArr = [arr[0]];            for (let i = 1; i < arr.length; i++) {                let repeat = false;                for (let j = 0; j < newArr.length; j++) {                    if (arr[i] === newArr[j]) {                        repeat = true;                        break;                    }else{                                            }                }                if (!repeat) {                    newArr.push(arr[i]);                }            }            return newArr;        }         console.log(unique([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));        // 结果是[1, 2, 3, 5, 6, 7, 4]


Methods 2: 思路:先将原数组排序,在与相邻的进行比较,如果不同则存入新数组。

        function unique2(arr) {            var formArr = arr.sort()            var newArr=[formArr[0]]            for (let i = 1; i < formArr.length; i++) {                if (formArr[i]!==formArr[i-1]) {                    newArr.push(formArr[i])                }            }            return newArr        }        console.log(unique2([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));        // 结果是[1, 2, 3,  4,5, 6, 7]


 Methods 3: 利用对象属性存在的特性,如果没有该属性则存入新数组。

        function unique3(arr) {            var obj={}            var newArr=[]            for (let i = 0; i < arr.length; i++) {                if (!obj[arr[i]]) {                    obj[arr[i]] = 1                    newArr.push(arr[i])                }               }            return newArr        }        console.log(unique2([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));        // 结果是[1, 2, 3, 5, 6, 7, 4]


Methods 4: 利用数组的indexOf下标属性来查询。

        function unique4(arr) {            var newArr = []            for (var i = 0; i < arr.length; i++) {                if (newArr.indexOf(arr[i])===-1) {                    newArr.push(arr[i])                }            }            return newArr        }        console.log(unique4([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));        // 结果是[1, 2, 3, 5, 6, 7, 4]


Methods 5: 利用数组原型对象上的includes方法。

        function unique5(arr) {            var newArr = []            for (var i = 0; i < arr.length; i++) {                if (!newArr.includes(arr[i])) {                    newArr.push(arr[i])                }            }            return newArr        }        console.log(unique5([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));        // 结果是[1, 2, 3, 5, 6, 7, 4]


Methods 6: 利用数组原型对象上的 filter 和 includes方法。

        function unique6(arr) {            var newArr = []            newArr = arr.filter(function (item) {                return newArr.includes(item) ? '' : newArr.push(item)            })            return newArr        }        console.log(unique6([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));        // 结果是[1, 2, 3, 5, 6, 7, 4]


Methods 7: 利用数组原型对象上的 forEach 和 includes方法。

       

   function unique7(arr) {            let newArr = [];            arr.forEach(item => {                return newArr.includes(item) ? '' : newArr.push(item);            });            return newArr;        }        console.log(unique7([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));        // 结果是[1, 2, 3, 4, 5, 6, 7]


Methods 8: 利用数组原型对象上的 splice 方法

        function unique8(arr) {            var i,j,len = arr.length;            for (i = 0; i < len; i++) {                for (j = i + 1; j < len; j++) {                    if (arr[i] == arr[j]) {                        arr.splice(j, 1);                        len--;                        j--;                    }                }            }            return arr;        }        console.log(unique8([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));


Methods 9: 利用数组原型对象上的 lastIndexOf 方法。

        function unique9(arr) {            var res = [];            for (var i = 0; i < arr.length; i++) {                res.lastIndexOf(arr[i]) !== -1 ? '' : res.push(arr[i]);            }            return res;        }        console.log(unique9([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));        // 结果是[1, 2, 3, 5, 6, 7, 4]


Methods 10: 利用 ES6的set 方法。

        function unique10(arr) {            //Set数据结构,它类似于数组,其成员的值都是唯一的            return Array.from(new Set(arr)); // 利用Array.from将Set结构转换成数组        }        console.log(unique10([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));        // 结果是[1, 2, 3, 5, 6, 7, 4]


 
 

 统计字符串中出现最多的字符

<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title></title><link rel="stylesheet" href=""></head><script>// 判断一个字符串中出现次数最多的字符,统计这个次数//第一种方法var str='asdoosdpedncxsdopdaqdg';function sum(str){var json={};for(var i=0;i<str.length;i++){var key=str.charAt(i);if(json[key]===undefined){json[key]=1;}else{json[key]+=1;}}console.log(json);var maxkey="";var maxvalue=0;for(var k in json){if(maxkey==""){maxkey=k;maxvalue=json[k];}else{if(json[k]>maxvalue){maxkey=k;maxvalue=json[k];}}}console.log(maxkey);//出现次数最多的字符console.log(maxvalue);//出现次数}// 执行函数sum(str);//第二种精简方法function count(str) { var obj = {}; str.replace(/\S/g,function(s){ !obj[s]?obj[s]=1:obj[s]++;}) return obj; }count(str);</script><body></body></html>

js垃圾回收机制

什么是垃圾?
(1)没有被引用的对象或变量

(2)无法访问到的对象(几个对象引用形成一个环,互相引用)

可达性
可达性是指那些以某种方式可以访问到或可以用到的值,它们被保证存储在内存中

有一组基本的固有可达值,由于显而易见而无法删除:
(1)本地函数的局部变量和参数
(2)嵌套调用链上的其他函数的变量与参数
(3)全局变量
(4)还有一些其他的,内部的
这些值成为根。

如果引用或引用链可以从根访问任何其他值,则认为该值是可访问的。
垃圾回收机制
垃圾回收机制(GC:Garbage Collection):执行环境负责管理代码执行过程中使用的内存。JS的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,没有被释放,导致该内存无法被使用,垃圾回收机制就是间歇的不定期的寻找到不再使用的变量,并释放掉它们所指向的内存。

垃圾回收的必要性
字符串、对象和数组没有固定的大小,所以只有当它们大小已知时才能对它们进行动态的存储分配。JavaScript程序每次创建字符串、数组或对象时,解释器都要分配内存才存储这个实体。只要像这样动态地分配了内存,最终都要释放这些内存以便它们能够被再次利用;否则,JavaScript的解释器将会消耗完系统中所有可用的内存,造成系统崩溃。
JavaScript有自己的垃圾回收机制(Garbage Collection),JavaScript的解释器可用检测到何时程序不再使用一个对象,当确定了一个对象无用的时候,就说明不再需要这个对象了,就可用把这个对象所占用的内存释放掉。

例如:

var a='use'var b='over a'var a=b   //将a重写



代码执行以后,‘use’这个字符串就失去了引用(刚开始是被a引用的),系统检测到之后,就会启动垃圾回收机制,释放use字符串的存储空间,以便这些空间可用再被利用。

垃圾回收方式
JavaScript执行环境中的垃圾回收器怎样才能检测到哪块内存可以被回收呢?

通常有两种方式标记清除(mark and sweep)、引用计数(reference counting)

标记清除
这是JavaScript中最常用的垃圾回收方式。

(1)当变量进入执行环境时(函数中声明变量),就标记这个变量为“进入环境”,当变量离开环境时(函数执行结束),则将其标记为“离开环境”,离开环境之后还有的变量则是需要被删除的变量。

(2)垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记。

(3)去掉环境中的变量以及被环境中变量引用的变量的标记。

(4)之后再被加上标记的变量即是需要回收的变量(因为环境中的变量已经无法访问到这些变量)

(5)最后,垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收他们所占用的内存空间。

引用计数
这种方式常常会引起内存泄漏,低版本的IE使用这种方式。机制就是跟踪一个值的引用次数,当声明一个变量并将一个引用类型赋值给该变量时该值引用次数加1,当这个变量指向其他一个时该值的引用次数便减一。当该值引用次数为0时,则说明没有办法再访问这个值了,被视为准备回收的对象,每当过一段时间开始垃圾回收的时候,就把被引用数为0的变量回收。引用计数方法可能导致循环引用,类似死锁,导致内存泄露。

例如:

function problem() {    var objA = new Object();    var objB = new Object();    objA.someOtherObject = objB;    objB.anotherObject = objA;}



objA和objB相互引用,两个对象的引用次数都是2。函数执行完成之后,objA和objB还将会继续存在,因为他们的引用次数永远不会是0。这样的相互引用如果说很大量的存在就会导致大量的内存泄露。

补充:

常见内存泄漏的原因:

(1)全局变量引起的内存泄露
(2)闭包引起的内存泄露:慎用闭包
(3)dom清空或删除时,事件未清除导致的内存泄漏
(4)循环引用带来的内存泄露
 

原型、原型链

一、原型
①所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象
②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象
③所有引用类型的__proto__属性指向它构造函数的prototype

var a = [1,2,3];a.__proto__ === Array.prototype; // true



二、原型链
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。

对象的__proto__和构造函数的原型prototype组成了原型链

举例,有以下代码

function Parent(month){    this.month = month;}var child = new Parent('Ann');console.log(child.month); // Annconsole.log(child.father); // undefined



在child中查找某个属性时,会执行下面步骤:

访问链路为:

访问路链为 :

①一直往上层查找,直到到null还没有找到,则返回undefined
②Object.prototype.__proto__ === null  注意这里的Null是一个对象
③所有从原型或更高级原型中的得到、执行的方法,其中的this在执行时,指向当前这个触发事件执行的对象
原文链接:【原型和原型链】什么是原型和原型链_TowYingWang的博客-CSDN博客_原型和原型链

作用域链

一般情况使用的变量取值是在当前执行环境的作用域中查找,如果当前作用域没有查到这个值,就会向上级作用域查找,直到查找到全局作用域,这么一个查找的过程我们叫做作用域链,下级作用域可以向上级作用域不断查找,但是上级作用域不能向下级作用域查找,类似原型链

举个栗子:

<script>    let a = 10;    function tttt() {        let b = 20;        return function ttt() {            return function tt() {                return function t() {                    let c = '张三'                    var d = "小李"                    a = 'hello';                    b = "world"                    console.log(b) //在全局访问不了b 所以在这打印     world                }            }        }    }    // 调用最内层函数 t 看看a  、b的值会不会改变    tttt()()()()    console.log(a)//hello        // console.log(d)//d is not defined    console.log(c)//c is not defined</script>

可以看到 a 、b的值改变了 

闭包

1.什么是闭包?
如果一个函数用到了它作用域外面的变量,那么这个变量和这个函数之间的环境就叫闭包。

闭包有以下个特性:

函数嵌套函数;内部函数用到了外部函数的参数和变量;参数和变量不会被垃圾回收机制回收。参数和变量不会被垃圾回收机制回收

2.用码举例

function a() {  var i = 0;  return function inner() {    i++;    return i;  };} // 或者function a() {  var i = 0;  function inner() {    return i;  }}


闭包使函数的私有变量不受外部干扰

是变量存于内存中不被销毁

 function a() {    var i = 0;    return function () {        i++;        return i;    };}var fn = a();console.log(fn()); //输出结果: 1console.log(fn()); //输出结果: 2console.log(fn()); //输出结果: 3


变量 i 保存在父作用域中,每次访问函数 y 时, 在函数 y 中找不到变量 i, 会顺着作用域链一直向上找,直到全局作用域中也没找到为止。

闭包常用于实现单例模式、柯里化、防抖、节流、模块化。

滥用闭包可能会造成内存泄漏(无用变量存于内存中无法回收,一直占用内存)。解决此问题的方法是,清除变量(设为 null)。
本文链接:【闭包】什么是闭包?闭包用途_nilmao的博客-CSDN博客_闭包

继承方法

 //动物园        //继承性: 先一个父类,然后子类继承父类的方法和属性        //动物类:动物所有的共有内容放到动物类        //对应的动物类型时继承 动物类的方法或者属性        //动物类(构造函数)        function Animal(name, age, color) {            this.name = name            this.age = age            this.color = color        }        Animal.prototype.move = function() {            console.log(this.name + "正在移动")        }        Animal.prototype.eat = function() {            console.log(this.name + "正在吃")        }        //狗:构造函数 继承 Animal中所有的属性和方法        //方法一:原型链继承:将原型改成对应的对象        //问题:无法初始化对应的属性         function Dog(name, age, color) {        }        Dog.prototype = new Animal("小黑", 2, "白色")            //{name:'小黑',age:2,color:"白色"}        Dog.prototype.watch = function() {                console.log('汪汪汪')            }            // var d1=new Dog("旺财",5,"黑色")            // var d2=new Dog("小白",4,"褐色")            // d1.move()            //老虎:            //方法二:冒充继承法:通过call或者apply改变原有函数的this指向,实现的            //问题:无法将原型中所带有的方法和属性继承过来        function Tiger(name, age, color) {            this.height = 180                //改变Animal中this的指向性                //call和apply 面试题!!!!            Animal.call(this, name, age, color)        }        Tiger.prototype.chiren = function() {                console.log(this.name + "吃人")            }            //产生一个新的对象  构造函数内部this->{}            // var t1=new Tiger("心吧",21,"八色")            // t1.eat()            // console.log(t1)方法一和方法二都不是正确的继承方式,将他两结合得到正确的组合继承            //猫            //方法三:组合继承:冒充继承+原型继承        function Cat(name, age, color) {            Animal.call(this, name, age, color)                //    Animal.apply(this,[name,age,color])        }        Cat.prototype = new Animal()        Cat.prototype.maimeng = function() {            console.log(this.name + "正在卖萌")        }        var c1 = new Cat("小白", 2, "白色")        console.log(c1)        c1.move()

 方法四 es6中的继承 使用 extends和super进行继承

1、使用class构造一个父类

  class Parent {      constructor(name,age){        this.name = name        this.age = age      }      sayName(){        console.log(this.name);      }    }



2、使用class构造一个子类,并使用extends实现继承,super指向父类的原型对象

  class Child extends Parent{      constructor(name,age,gender){        super(name,age) //这里的super()必须写在constructor内部的最上面        this.gender = gender  //super 下方可以添加其他属性和方法      }      sayGender(){        console.log(this.gender);      }    }



3、实例化对象

      const ming = new Child('ming',18,'男')    ming.sayGender()    ming.sayName()    console.log(ming.name);    console.log(ming.age);

方法五:原型式继承

这里不得不提到的就是 ES5 里面的 Object.create 方法,这个方法接收两个参数:一是用作新对象原型的对象、二是为新对象定义额外属性的对象(可选参数)

let parent4 = {  name: 'parent4',  friends: ['p1', 'p2', 'p3'],  getName: function () {    return this.name  },}//下面这句代码将parent4作为了person的原型let person = Object.create(parent4) person.name = 'Tom'person.friends.push('jerry')let person2 = Object.create(parent4)person2.friends.push('lucy')console.log(person.name)console.log(person.name === person.getName())console.log(person2.name)console.log(person.friends)console.log(person2.friends)

通过 Object.create 这个方法可以实现普通对象的继承,不仅仅能继承属性,同样也可以继承 getName 的方法,请看这段代码的执行结果。
在这里插入图片描述
最后两个输出结果是一样的,讲到这里你应该可以联想到浅拷贝的知识点,关于引用数据类型“共享”的问题,其实 Object.create 方法是可以为一些对象实现浅拷贝的。

辗转相除法

辗转相除法又名欧几里得算法(Euclidean algorithm)
目的是求出两个正整数的最大公约数

代码实现

function gcd(a ,b) {    let max = a > b ? a : b;    //获取两数之间最大的数    let min = a > b ? b : a;    //获取两数之间最小的数    let r = max % min;          //获取两数的余数    if(r === 0) {        return min;    }else {        return gcd(min ,r);    }}function gcd(a ,b) {    return b === 0 ? a : gcb(b ,a % b);}



 

数组转字符串

JavaScript 允许数组与字符串之间相互转换。其中 Array 方法对象定义了 3 个方法,可以把数组转换为字符串,如表所示。

数组方法    说明

toString()    将数组转换成一个字符串toLocalString()    把数组转换成本地约定的字符串join()    将数组元素连接起来以构建一个字符串

示例1
下面使用 toString() 方法读取数组的值。

数组中 toString() 方法能够把每个元素转换为字符串,然后以逗号连接输出显示。

var a = [1,2,3,4,5,6,7,8,9,0];  //定义数组var s = a.toString();  //把数组转换为字符串console.log(s);  //返回字符串“1,2,3,4,5,6,7,8,9,0”console.log(typeof s);  //返回字符串string,说明是字符串类型



当数组用于字符串环境中时,JavaScript 会自动调用 toString() 方法将数组转换成字符串。在某些情况下,需要明确调用这个方法。

var a = [1,2,3,4,5,6,7,8,9,0];  //定义数组var b = [1,2,3,4,5,6,7,8,9,0];  //定义数组var s = a + b;  //数组连接操作console.log(s);  //返回“1,2,3,4,5,6,7,8,9,01,2,3,4,5,6,7,8,9,0”console.log(typeof s);  //返回字符串string,说明是字符串类型



toString() 在把数组转换成字符串时,首先要将数组的每个元素都转换为字符串。当每个元素都被转换为字符串时,才使用逗号进行分隔,以列表的形式输出这些字符串。

var a = [1,[2,3],[4,5]],[6,[7,[8,9],0]]];  //定义多维数组var s = a.toString();  //把数组转换为字符串console.log(S);  //返回字符串“1,2,3,4,5,6,7,8,9,0”



其中数组 a 是一个多维数组,JavaScript 会以迭代的方式调用 toString() 方法把所有数组都转换为字符串。

示例2
下面使用 toLocalString() 方法读取数组的值。

toLocalString() 方法与 toString() 方法用法基本相同,主要区别在于 toLocalString() 方法能够使用用户所在地区特定的分隔符把生成的字符串连接起来,形成一个字符串。

var a = [1,2,3,4,5];  //定义数组var s = a.toLocalString();  //把数组转换为本地字符串console.log(s);  //返回字符串“1,2,3,4,5,6,7,8,9,0”



在上面示例中,toLocalString() 方法根据中国的使用习惯,先把数字转换为浮点数之后再执行字符串转换操作。

示例3
下面使用 join() 方法可以把数组转换为字符串

join() 方法可以把数组转换为字符串,不过它可以指定分隔符。在调用 join() 方法时,可以传递一个参数作为分隔符来连接每个元素。如果省略参数,默认使用逗号作为分隔符,这时与 toString() 方法转换操作效果相同。

var a = [1,2,3,4,5];  //定义数组var s = a.join("==");  //指定分隔符console.log(s);  //返回字符串“1==2==3==4==5”



示例4
下面使用 split() 方法把字符串转换为数组。

split() 方法是 String 对象方法,与 join() 方法操作正好相反。该方法可以指定两个参数,第 1 个参数为分隔符,指定从哪儿进行分隔的标记;第 2 个参数指定要返回数组的长度

var s = "1==2== 3==4 ==5";var a = s.split("==");console.log(a);console.log(a.constructor == Array);


 

二级下拉菜单

这里用原生js实现

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Document</title></head><body>    <select id="bt1">    </select>    <select id="bt2">    </select></body><script>    var cityArr = ['北京', '上海', '广州'];    var areaArr = [        ["东城区", "西城区", "崇文区", "宣武区", "朝阳区", "丰台区", "石景山区", "海淀区", "门头沟区", "房山区", "通州区", "顺义区", "昌平区", "大兴区", "平谷区", "怀柔区", "密云县", "延庆县"],        ["黄浦区", "徐汇区", "长宁区", "静安区", "普陀区", "闸北区", "虹口区", "杨浦区", "宝山区", "闵行区", "嘉定区", "松江区", "金山区", "青浦区", "南汇区", "奉贤区", "浦东新区", "崇明县"],        ["越秀区", "荔湾区", "海珠区", "天河区", "白云区", "黄埔区", "番禺区", "花都区", "南沙区", "萝岗区", "增城市", "从化市"]    ]    // 把以上两个数据做到两个下拉列表中,并关联起来    //给bt1添加内容    var str = "";    for (var j = 0; j < cityArr.length; j++) {        str = str + "<option>" + cityArr[j] + "</option>";    };    console.log(str)    var bt1 = document.getElementById("bt1"); //设置变量bt1=页面中id为bt1的元素    bt1.innerHTML = str; //设置bt1的内容为str    //给bt2添加内容    var str1 = "";    for (var k = 0; k < areaArr[0].length; k++) {        str1 = str1 + "<option>" + areaArr[0][k] + "</option>";    }    console.log(str1);    var bt2 = document.getElementById("bt2"); //设置变量bt2=页面中id为bt2的元素    bt2.innerHTML = str1; //设置bt2的内容为str    // 联动 城市变化时对应的地区也发生变化    bt1.onchange = function() {        var index = bt1.selectedIndex;        var str1 = "";        for (var n = 0; n < areaArr[index].length; n++) {            str1 = str1 + "<option>" + areaArr[index][n] + '</option>'        }        bt2.innerHTML = str1;    }</script></html>

图片预加载和懒加载?

原生js实现图片懒加载

<!DOCTYPE html><html><head>    <meta charset="utf-8">    <title></title>    <style type="text/css">        * {            padding: 0;            margin: 0;            list-style: none;        }                ul {            width: 910px;            margin: 0 auto;        }                ul li {            width: 300px;            height: 300px;            border: 1px solid red;            float: left;        }                ul li img {            width: 100%;            height: 100%;        }    </style></head><body>    <ul id="list">    </ul></body><script type="text/javascript">    var list = document.getElementById("list");    for (var i = 1; i <= 32; i++) {//下面这行代码写图片的路径        var imgPath = './image/' + (i <= 9 ? ('0' + i) : i) + ".jfif";        var li = document.createElement("li");        var img = document.createElement("img");        img._src = imgPath;        li.appendChild(img);        list.appendChild(li);    }    var imgArr = document.querySelectorAll("img");    console.log(imgArr[0]._src);    //只显示可视区中的图片    for (var i = 0; i < imgArr.length; i++) {        var imgOffsetTop = imgArr[i].offsetTop;        var bodyHeigh = document.documentElement.clientHeight;        var bodySt = document.documentElement.scrollTop || document.body.scrollTop;        //图片的上边框显示到可视区域中        if (imgOffsetTop <= bodyHeigh + bodySt) {            imgArr[i].src = imgArr[i]._src;        }    }    window.onscroll = function() {        var imgArr = document.querySelectorAll("img");        //只显示可视区中的图片        for (var i = 0; i < imgArr.length; i++) {            var imgOffsetTop = imgArr[i].offsetTop;            var bodyHeigh = document.documentElement.clientHeight;            var bodySt = document.documentElement.scrollTop || document.body.scrollTop;            //图片的上边框显示到可视区域中            if (imgOffsetTop <= bodyHeigh + bodySt) {                imgArr[i].src = imgArr[i]._src            }        }    }</script></html>

图片预加载和懒加载
图片懒加载
在渲染页面的时候,先将图片用一张默认图片代替,当图片到达浏览器可视区域时,才显示真实的图片。

这样的好处是,可以减缓服务器负担,加快初始界面的渲染速度。

实现方式:

使用setTimeOut或setInterval定时器进行延迟加载
条件加载,符合条件或触发事件后再进行异步下载
通过滚动条监听用户距图片距离,快要到达之前进行加载

// 通过滚动条监听用户距图片距离,到达进行加载    let img = document.querySelector('img')    function lazyLoad(){      let viewHeight = document.documentElement.clientHeight      let scrollTop = document.documentElement.scrollTop      // 判断图片是否进入可视区      if(img.offsetTop < viewHeight+scrollTop){        var url ="https://himg.bdimg.com/sys/portraitn/item/46ecf7f5"        img.src = url      }    }    window.addEventListener('scroll',lazyLoad)//如果放多张图片 使用循环



图片预加载
与懒加载相反,先将图片提前加载到缓存,用户一打开页面就能快速呈现图片。

好处是,遇到一些较大的图片时,可以避免页面慢慢渲染。但是服务器负担会增大。

实现方式:css的background元素会自动预加载

// 预加载的图片不能使用dispaly:none隐藏,只能将其宽高设为0或者移到看不见的地方  <style>    li{      list-style: none;    }    #img {    background-image: url('https://himg.bdimg.com/sys/portraitn/item/46ecf7f5');    width: 0;    height: 0;      }  </style><body>  <li id="img"></li>  <button>点击展示</button>  <script>    let btn =  document.querySelector('button')    let li = document.querySelector('li')    btn.addEventListener('click',function(){      let myImg = document.createElement('img')      myImg.src = 'https://himg.bdimg.com/sys/portraitn/item/46ecf7f5'      li.appendChild(myImg)    })  </script>  </body>



JavaScript则常用new Image()实现
 

   // 预加载图片路径    const urlList = [    'https://himg.bdimg.com/sys/portraitn/item/46ecf7f5'    ]    function preLoad(){      let img = new Image()      img.src = urlList[0]      // onload是图片加载完成事件      img.onload = function(){        //放入图片加载完之后的操作        console.log('图片预加载成功');      }    }


    preLoad()

 


原文链接:https://blog.csdn.net/qq_47234456/article/details/124568755

bind() apply()

const用法

Utf-8编码汉字占多少个字节

ajax

js对数组的操作,包括向数组中插入删除数据

两种定时器,setinterval和settimeout。因为settimeout是只执行一次的,如果要执行多次怎么做。(答案:设置一个回调函数,多次调用,大概是这样,你可以去查查)

JS内存回收机制

promise是什么?能解决什么问题?

编程:连接两个数组并返回?

冒泡排序?

创建新数组,向数组插入数据

es6新特性

js对数组有哪些操作方法

什么是ajax,可以用来做什么

讲下你做轮播图的思路,无缝轮播

js的选择器

js数据类型

减少页面加载时间的方法

怎么理解模块化开发

什么是闭包,有什么作用?

定时器 settimeout和setinterval的区别,如果用settimeout实现每隔一定的时间就执行一次,怎么实现

手机号的正则表达式(以1开头的11位数字)

<ol><li></li></ol>结构的html代码,写原生js实现点击某个li就弹出对应的索引值

对数组进行随机排序, 要求数组中的每个元素不能停留在原来的位置

代码实现parse方法,将有效的JSON字符串转换成JavaScript对象

原生js的变量类型有哪些?ES6新增哪几个变量类型?

js的数组方法有哪些?

es6的有哪些扩展?新增的数组方法有哪些?用什么方法连接两个数组?函数扩展中的箭头函数中的this所指向的是什么?一般函数的this指向的又是什么?

用什么方法判断是否是数组?又用什么方法判断是否是对象?

http相关

GET和POST的区别?何时使用POST**http状态码HTTP状态码200/302/401/404/500分别代表什么意思http协议http中的方法,除了get方法、post方法http和https的区别http协议

浏览器

浏览器存储浏览器图片加载

bootstrap

bootstrap的原理46.用过bootstrap的哪些组件,导航条怎么实现的(问原理),怎么适应窗口大小?d-flex和d-block有什么冲突?bootstrap的grid-system?bookstrap的响应式所示怎么实现的。bookstrap栅格系统,你怎么理解栅格系统

vue相关

vue生命周期的理解v-if和v-show的作用相似,它们的区别?vue项目v-model双向绑定原理用过vue的哪些组件?vue项目用什么搭建的,搭建的时候有遇到过什么问题吗?axios的withCredential? intercepter,vue-router 的模式有?head标签里面有个什么vue(发音一样我不知道是什么)方法还是啥东西?watch的作用?为什么要用它?vue的生命周期,哪个钩子函数可以数据请求,为什么?vue第三方组件的引入vue第三方组件的引入Vue中有哪些生命周期函数路由跳转的方式vue生命周期的理解vue数据双向绑定的原理,用了什么设计模式(web高级)Vue的钩子函数Vue基于什么语言Vue的第三方组件库ivew组件之间的传参(例如子组件和父组件之间的传参)vue如何实现双向据绑定?vue父组件子组件通信?vue删除数据监测不到?父组件子组件传参路由跳转的方式vue路由传参怎么实现?vue生命周期的钩子函数有哪些?MVVM和MVC区别?

node相关

1 做node用了什么框架

2 用mongodb做过什么

3 node.js

4  module.export和export?

每一个node.js执行文件,都自动创建一个module对象,同时,module对象会创建一个叫exports的属性,初始化的值是 {}

 module.exports = {};

在 node 的 js 模块里可以直接调用 exports 和 module 两个“全局”变量,但是 exports 是 module.exports 的一个引用。

exports 是 module.exports 的一个引用module.exports 初始值为一个空对象 {},所以 exports 初始值也是 {}require 引用模块后,返回的是 module.exports 而不是 exports!!!!!exports.xxx 相当于在导出对象上挂属性,该属性对调用模块直接可见exports = 相当于给 exports 对象重新赋值,调用模块不能访问 exports 对象及其属性如果此模块是一个类,就应该直接赋值 module.exports,这样调用者就是一个类构造器,可以直接 new 实例。
//plus.jsfunction plus(a,b){return a+b;}// 这样导出的 plus 是作为 exports 的一个方法被导出的exports.plus = plus;// main.jsvar Plus = require('plus');console.log(Plus.plus(1,2)); // 左边的 Plus 是 require 过来的模块名,右边的是它的 plus 方法。

在 node 编译的过程中,会把 js 模块封装成如下形式:

 
// require 是对 Node.js 实现查找模块的 Module._load 实例的引用// __finename 和 __dirname 是 Node.js 在查找该模块后找到的模块名称和模块绝对路径(function(exports,require,module,__filename,__dirname){function plus(a,b){return a+b;}exports.plus = plus;})

为了将函数直接导出成模块,而不是模块的一个方法,需要

module.exports = plus;

// plus.jsfunction plus(a,b){return a+b ;}module.exports = plus;// main.jsvar plus = require('plus');console.log(plus(1,2));

exports = module.exports = {};

例子一:

var name = 'rainbow';exports.name = name;exports.sayName = function(){console.log(name);}// 给 exports 赋值相当于给 module.exports 这个空对象添加了两个属性,相当于:var name = 'rainbow';module.exports.name = name;module.exports.sayName = function(){console.log(name);}

例子二:

exports = module.exports = somethings// 等价于module.exports = somethingsexports = module.exports// module.exports = somethings 是对 mudole.exports 进行了覆盖,// 此时 module.exports 和 exports 的关系断裂,// mudole.exports 指向了新的内存块,// 而exports 还是指向原来的内存块,// 为了让 module.exports 和 exports 还是指向同一个内存或者说指向同一个"对象",// 所以我们就 exports = module.exports.

例子三:

 

exports = function(){};

// 这样就是重新给 exports 赋值,它将不再是 module.exports 的引用,二者将无任何联系。

例子四:

 
module.exports.something = function(){};exports.something = function(){};

// 上面两个方程是等价的

例子五:

 
// index.jsvar something = require('./requireMe');something();// requireMe.jsexports.something = function(){console.log('am a function');}// 以上代码会报错,因为 require 出来的 module.exports 是一个object,不能直接执行
//修改方式一// requireMe.jsmodule.exports = function(){console.log('am a function');}// 当把代码改成上面这样,就不会报错,因为此时的 module.exports 是一个 function,可以直接执行。// 修改方式二// index.jsvar something = require('./requireMe');something.something();// 因为这时候 require 出来的是一个 object,有一个 something 的属性,所以可以这样调用执行。

总结要导出的东西放在model.exports里面   model.exports={} 刚开始他是一个空对象

       model.exports={ //这里面以键值对的形式放要导出的东西 }

可以使用对象的简写方式,

微信小程序

微信小程序获取用户信息

react

react的生命周期?

数据库相关

数据库Mongodb的update有几个参数?vue和react的区别,用法区别

其他(此题目处供参考,根据个人情况回答)

对哪个编程语言比较熟?webpack中在production下怎么禁止console.log和alert?传统网站、响应式、vue、小程序的区别?除了学校和培训,你还自学有什么技术?项目中哪个是你做得比较好的,实现了什么功能项目中哪个是你做得比较好的,实现了什么功能项目中遇到兼容性问题最近两年面试题总结,答案有时间慢慢完善:购物车的实现过程(包括怎么布局,可以用vue、react、jq等)购物车详情页优化(用户商品加入太多导致页面卡顿)(懒加载、分页)数据结构(排序算法,冒泡以外的)团队合作的经验通宵经历(不是玩的)课外项目(自己瞎做的那种)为什么学前端?有没有参赛或者除了学校课程内容外的经验?应该是想知道有没有合作经验是否熟悉使用开发者工具?有没有使用过断点调试?最近有没有在看某一本书?或者是有没有学习某一个课程?有没有什么学习的计划?

************持续更新中.......

实在抱歉 由于篇幅太长,导编辑起来很卡所以没有继续编辑,  进行了分类其他内容放在以下链接(题目不一定相同)

前端十五道html面试题_一只路过的菜鸟的博客-CSDN博客_前端html面试题

js十五道面试题(含答案)_一只路过的菜鸟的博客-CSDN博客_js面试题

【30 道 Vue 面试题,内含详细讲解】_一只路过的菜鸟的博客-CSDN博客_vue的一些面试题

http相关十道面试题(含答案)_一只路过的菜鸟的博客-CSDN博客_http面试题


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/49548.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1