2021前端面试题

img标签的title和alt属性有什么区别

  • alt:图片加载失败时,显示在网页上的替代文字
  • title:鼠标(手机端该属性无意义)放在图片上时显示的文字
  • alt是必需属性(但属性值可为空),title非必需

图片懒加载的原理

图像是img标记,浏览器根据图像的src属性请求图像,因此惰性加载的关键是当图像不在可视区域时,不给`imgs‘赋值。

懒加载的思路及实现代码详见js实现图片懒加载原理

H5新增了哪些标签?

常见的有:article、aside、audio、video、footer、header、nav、section

H5和H4有什么不同?

H5新特性有: 用于媒体回放的video和audio元素 对本地离线存储的更好的支持 新的特殊内容元素,如article、footer、header、nav、section

简单地说,它更标准,提供更多的多功能支持。更标准、更可读性、更好的性能和更方便的执行。

块级元素、行内元素分别有哪些?

块级元素:div , p , form, ul, li , ol, dl, form, address, fieldset, hr, menu, table 行内元素:span, strong, em, br, img , input, label, select, textarea, cite

SVG和CANVAS的区别?

SVG

表示以XML格式定义图像的可伸缩矢量图形。

CANVAS

通过 JavaScript 来绘制 2D 图形。

二者比较

svg如何调整颜色

标签fill属性设置即可

关于CSS

css3新的特性?

RGBA和透明度

是RGB颜色模型的一个扩展。本质上,在设置元素中添加了一个alpha通道,即一个表示除红色、绿色和蓝色三种颜色之外的透明度的通道。

background属性

  • background-image:设置元素的背景图像。
  • background-origin:规定背景图片的定位区域。
  • background-size :规定背景图片的尺寸。
  • background-repeat:设置是否及如何重复背景图像。

word-wrap属性

word-wrap 属性允许长单词或 URL 地址换行到下一行。

注:所有主流浏览器都支持 word-wrap 属性。

基础语法:

word-wrap: normal|break-word;

text-shadow属性

text-shadow 属性:向文本设置阴影。

text-shadow基础语法:

text-shadow: 5px 5px 5px #FF0000;

参数分别表示:水平阴影,垂直阴影,模糊距离,阴影颜色;

font-face属性

font-face属性:定义自己的字体

在新的 @font-face 规则中,您必须首先定义字体的名称(比如 myFirstFont),然后指向该字体文件。

border-radius属性

border-radius 属性:是一个简写属性,用于设置四个 border-*-radius 属性。

基础语法:

border-radius: 1-4 length|% / 1-4 length|%;

注:该属性允许您为元素添加圆角边框!

border-image属性

border-image:将图片规定为包围 div 元素的边框

border-image基础语法:

border-image: url(border.png) 30 30 round

box-shadow属性

box-shadow属性:向框添加一个或多个阴影。(盒阴影)

box-shadow基础语法:

box-shadow: 10px 10px 5px #888888

媒体查询

媒体查询定义两套css,当浏览器的尺寸变化时会采用不同的属性。

元素居中的方式有哪些?

水平居中

1.行内元素水平居中 利用 text-align: center 可以实现在块级元素内部的行内元素水平居中。此方法对inline、inline-block、inline-table和inline-flex元素水平居中都有效。 此外,如果块级元素内部包着也是一个块级元素,我们可以先将其由块级元素改变为行内块元素,再通过设置行内块元素居中以达到水平居中。

2.块级元素的水平居中 ①将该块级元素左右外边距margin-left和margin-right设置为auto。 ②使用table+margin 先将子元素设置为块级表格来显示(类似),再将其设置水平居中。 display:table在表现上类似block元素,但是宽度为内容宽。 ③使用absolute+transform 先将父元素设置为相对定位,再将子元素设置为绝对定位,向右移动子元素,移动距离为父容器的一半,最后通过向左移动子元素的一半宽度以达到水平居中。 不过transform属于css3内容,兼容性存在一定问题,高版本浏览器需要添加一些前缀。 ④使用flex+justify-content 通过CSS3中的布局利器flex中的justify-content属性来达到水平居中。 ⑤使用flex+margin 通过flex将父容器设置为为Flex布局,再设置子元素居中。

3.多块级元素水平居中 ①利用flex布局 利用弹性布局(flex),实现水平居中,其中justify-content 用于设置弹性盒子元素在主轴(默认横轴)方向上的对齐方式,本例中设置子元素水平居中显示。 ②利用inline-block 将要水平排列的块状元素设为display:inline-block,然后在父级元素上设置text-align:center,达到与上面的行内元素的水平居中一样的效果。

4.浮动元素水平居中 对于定宽的浮动元素,通过子元素设置relative + 负margin 对于不定宽的浮动元素,父子容器都用相对定位 通用方法(不管是定宽还是不定宽):flex布局

垂直居中

1.多行内联元素垂直居中 ①利用flex布局(flex) 利用flex布局实现垂直居中,其中flex-direction: column定义主轴方向为纵向。这种方式在较老的浏览器存在兼容性问题。 ②利用表布局(table) 利用表布局的vertical-align: middle可以实现子元素的垂直居中。

2.块级元素垂直居中 ①使用absolute+负margin(已知高度宽度) 通过绝对定位元素距离顶部50%,并设置margin-top向上偏移元素高度的一半,就可以实现了。 ②使用absolute+transform 当垂直居中的元素的高度和宽度未知时,可以借助CSS3中的transform属性向Y轴反向偏移50%的方法实现垂直居中。但是部分浏览器存在兼容性的问题。 ③使用flex+align-items 通过设置flex布局中的属性align-items,使子元素垂直居中。 ④使用table-cell+vertical-align 通过将父元素转化为一个表格单元格显示(类似 和 ),再通过设置 vertical-align属性,使表格单元格内容垂直居中。

水平垂直居中

1、绝对定位+CSS3(未知元素的高宽) 利用Css3的transform,可以轻松的在未知元素的高宽的情况下实现元素的垂直居中。 CSS3的transform固然好用,但在项目的实际运用中必须考虑兼容问题,大量的hack代码可能会导致得不偿失。 2、flex布局 利用flex布局,其中justify-content 用于设置或检索弹性盒子元素在主轴(横轴)方向上的对齐方式;而align-items属性定义flex子项在flex容器的当前行的侧轴(纵轴)方向上的对齐方式。不能兼容低版本的IE浏览器。 3、flex/grid与margin:auto(最简单写法) 容器元素设为 flex 布局或是grid布局,子元素只要写 margin: auto 即可,不能兼容低版本的IE浏览器。

自适应的方案?

viewport方案

配置默认根字号、默认字号、默认设计稿宽度,然后使用postcss插件将代码中的px自动转换成rem,这种方法可以完成使用1080p设计稿再不同手机下的适应方案,所有元素大小均按照1080p下的大小来定义px。配置上述插件后,px单位在编译后会默认转为rem单位,如果不需要被转换,可以将小写的px改成大写的PX或Px。取消使用viewport.js文件,如果遇到不能适配的公共组件,则拷贝一个新的版本,适配新的方案,逐步淘汰老版本。

// 引用该mixin,其中包含了默认的变量等
$default-font-size: 100;    // 默认根字号大小,用于换算vw单位
$baseFontSize: 100px;   // 默认字号大小,用于计算rem值
$pageWidth: 1080;       // 默认的设计稿宽度
@import '@oppobrowser/lib-browser-scss/src/mixins.scss';

//项目的vue.config.js中增加如下postcss配置
// 在css配置项中增加postcss配置,用于px转rem单位,后续合到master后就统一配置了
css: {
    loaderOptions: {
      sass: {
        data: '@import "@/common/scss/variables.scss";',
      },
      postcss: {
        plugins: [
          require('postcss-pxtorem')({
            // 把px单位换算成rem单位
            rootValue: 100, // 换算的基数(设计图1080的根字体为100)
            selectorBlackList: [], // 忽略转换正则匹配项
            propList: ['*'],
          }),
        ],
      }
}

rem方案

针对Android4.4以下版本,全部使用rem单位兼容方案,并在head标签内添加脚本重写html根字号的大小,1080p下为100px。并且针对受影响的公共组件写出兼容性代码。

<script type="text/javascript">
    (function(doc, win) {
        var basicWidth = 1080;
        var minWidth = 360;
        var htmlElement = doc.documentElement;
        var dpr = parseInt(window.devicePixelRatio || 1, 10);
        var recalc = function() {
            var clientWidth = htmlElement.clientWidth || (basicWidth / 2);
            window.rootFontSize = 100 * (clientWidth / basicWidth);
            clientWidth = clientWidth < minWidth? minWidth : clientWidth;
            htmlElement.style.fontSize = 100 * (clientWidth / basicWidth) + 'px';
            htmlElement.setAttribute("data-dpi", dpr);
        };
        recalc();
        if (!win.addEventListener) return;
        win.addEventListener('resize', recalc, false);
    })(document, window);
</script>

父容器高度塌陷的解决方案?

overflow:hidden

利用伪元素

div::after {
    display: block;    
    content: "";
    clear: both;
}

添加一个div

<style>
    .cf {
        clear: both;
    }
</style>
<div>
    .......
    .......
    <div class="cf"></div>
</div>

清除浮动的方法有哪些?

额外标签法

给谁清除浮动,就在其后额外添加一个空白标签 。 优点:通俗易懂,书写方便。(不推荐使用) 缺点:添加许多无意义的标签,结构化比较差。

给元素small清除浮动(在small后添加一个空白标签clear(类名可以随意),设置clear:both;即可)

父级添加overflow方法

可以通过触发BFC的方式,实现清楚浮动效果。 优点:代码简洁(慎重使用,若该父盒子里还有position定位会引起麻烦) 缺点:内容增多时候容易造成不会自动换行导致内容被隐藏掉,无法显示需要溢出的元素。

注意:别加错位置,是给父亲加(并不是所有的浮动都需要清除,谁影响布局,才清除谁。)

使用after伪元素清除浮动

after方式为空元素的升级版,好处是不用单独加标签了。 优点:符合闭合浮动思想,结构语义化正确 缺点:由于IE6-7不支持:after,使用zoom:1,触发hasLayout。

注意:这个也是给父亲添加 clearfix

使用before和after双伪元素清除浮动

注意:是给父亲添加clearfix

less和sass的区别?

不管是Sass,还是Less,都可以视为一种基于CSS之上的高级语言,其目的是使得CSS开发更灵活和更强大,Sass的功能比Less强大,基本可以说是一种真正的编程语言了,Less则相对清晰明了,易于上手,对编译环境要求比较宽松。考虑到编译Sass要安装Ruby,而Ruby官网在国内访问不了,个人在实际开发中更倾向于选择Less。

关于JS、ES6

es6兼容的浏览器版本

支持ie 11+

var,let,const的比较?

  • var声明变量存在变量提升,let和const不存在变量提升
  • let、const都是块级局部变量
  • 同一作用域下let和const不能声明同名变量,而var可以

继承的方式有那几种?

原型链继承

父类的实例作为子类的原型

借用构造函数继承(伪造对象、经典继承)

复制父类的实例属性给子类

实例继承(原型式继承)

组合式继承

调用父类构造函数,继承父类的属性,通过将父类实例作为子类原型,实现函数复用

寄生组合继承

通过寄生的方式来修复组合式继承的不足,完美的实现继承

es6 extends继承

代码量少,易懂

ES5继承和ES6继承的区别

es5继承首先是在子类中创建自己的this指向,最后将方法添加到this中

Child.prototype=new Parent() || Parent.apply(this) || Parent.call(this)

es6继承是使用关键字先创建父类的实例对象this,最后在子类class中修改this

说说对原型链的理解

原型链,简单理解就是原型组成的链,对象的proto它的是原型,而原型也是一个对象,也有proto属性,原型的proto又是原型的原型,就这样可以一直通过proto想上找,这就是原型链,当向上找找到Object的原型的时候,这条原型链就算到头了。

有哪些数据类型

值类型(基本类型):

字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。

引用数据类型:

对象(Object)、数组(Array)、函数(Function)。

判断数据类型的方式有哪些

  1. typeof
  2. instanceof
  3. constructor
  4. Object.prototype.toString.call()

数组去重的方式

1、使用set

2、使用 filter()

3、使用 reduce()

const array = [' ', 1,  2, ' ',' ', 3];
​
// 1: "Set"
[...new Set(array)];
​
// 2: "Filter"
array.filter((item, index) => array.indexOf(item) === index);
​
// 3: "Reduce"
array.reduce((unique, item) => 
  unique.includes(item) ? unique : [...unique, item], []);
​
​
// RESULT:
// [' ', 1, 2, 3];

深拷贝和浅拷贝的方式

深拷贝

1、最简单的方法就是JSON.parse(JSON.stringify())

function deepCopy(o) {
    return JSON.parse(JSON.stringify(o))
}

var c = {
    age: 1,
    name: undefined,
    sex: null,
    tel: /^1[34578]\d{9}$/,
    say: () => {
        console.log('hahha')
    }
}
// { age: 1, sex: null, tel: {} }

需要注意的是:这种拷贝方法不可以拷贝一些特殊的属性(例如正则表达式,undefine,function)

2、用递归去复制所有层级属性

function deepCopyTwo(obj) {
    let objClone = Array.isArray(obj) ? [] : {};
    if (obj && typeof obj == 'object') {
        for (const key in obj) {
            //判断obj子元素是否为对象,如果是,递归复制
            if (obj[key] && typeof obj[key] === "object") {
                objClone[key] = deepCopyTwo(obj[key]);
            } else {
                //如果不是,简单复制
                objClone[key] = obj[key];
            }
        }
    }
    return objClone;
}

浅拷贝

object.assign(target,source)

防抖和节流的区别

debounce和throttling 各有特点,在不同 的场景要根据需求合理的选择策略。如果事件触发是高频但是有停顿时,可以选择debounce; 在事件连续不断高频触发时,只能选择throttling,因为debounce可能会导致动作只被执行一次,界面出现跳跃。

二叉树的遍历有几种方法?

  • 先序
  • 中序
  • 后序
  • 层序遍历

具体实现方法详见:二叉树遍历的几种常见方法

数组扁平化有几种方法?

二维数组时,可以简单使用flat()方法

let arr = [[1,2],[3,4],[5,6]];

let arr = [[1,2],[3,4],[5,6]].flat();
console.log(arr); // [1,2,3,4,5,6]

如果是多维数组,则flat()将达不到效果,

需要给flat()传一个参数,var newArray = arr.flat([depth]),

参数:depth ,可选,指定要提取嵌套数组的结构深度,默认值为 1。

let arr = [[1,2],[3,4],[5,6]].flat(Infinity);
console.log(arr); // [1,2,3,4,5,6]

迭代实现 (ES6扩展运算符…)

const arr = [1,2,[3,4,5,[6,7],8],9,10,[11,[12,13]]];
const flatten = (arr) => {
while(arr.some(item=>Array.isArray(item))){
arr=[].concat(…arr);
}
return arr;
}
console.log(flatten(arr)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

普通递归实现

const arr = [1,2,[3,4,5,[6,7],8],9,10,[11,[12,13]]];
const flatten = (arr) => {
let result = [];
arr.forEach((item, i, arr) => {
if (Array.isArray(item)) {
result = result.concat(flatten(item));
} else {
result.push(arr[i])
}
})
return result;
};
console.log(flatten(arr));

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值