前端常见面试题

一、HTML相关:

1. Html5 新增了哪些标签?

布局标签:   header,  section,  footer,  article,  aside

表单标签:   datalist, input:type=’week|date|time|datetime|number|search|url|tel|color|email|range’

多媒体标签:  audio,  video
其他标签:   progress(进度条), meter

 

2. 行内元素和块级元素的具体区别是什么?

一、行内元素和块级元素的区别

  行内元素不会占据整行,在一条直线上排列,都是同一行,水平方向排列;块级元素会占据一行,垂直方向排列。

  块级元素可以包含行内元素和块级元素;行内元素不能包含块级元素。

  行内元素与块级元素属性的不同,主要是盒模型属性上,行内元素设置width无效,height无效(可以设置line-height),margin上下无效,padding上下无效。


二、行内元素和块级元素的相互转换

  行内元素转化为块元素: display:block;

  块元素转化为行内元素: display:inline;

 

3. 列举几个块级标签和行内标签?

块级标签:div,  p,  h1~h6,  section,  header,f  ooter
行内标签:span,  em(i),  strong(b),  u,  em(i),  a

 

4. 行内元素的padding 和margin 可设置吗?

1 行内元素设置水平方向的padding 和margin 是可以生效,但是设置垂直方向的padding 和margin 虽然看起来对标签起作用,但实际并没有对周围元素产生任何影响,
所以行内元素设置垂直方向的padding和margin 是无效的.

 

5. 简述readyonly 与disabled 的区别

readyonly 是设置表单元素为只读状态;
disabled 是设置表单元素为禁用状态.

 

6. 哪些标签都存在伪元素?

大部分容器标签(大部分双标签)都有伪元素, iframe 没有伪元素;
大部分单标签都没有伪元素, 但是img 有伪元素

 

7. 伪元素可以使用js 来操作吗?

js不可以操作伪元素

 

8. Html5 的网页为什么只需要写<!DOCTYOE HTML>?

html5不基于SGML,因此不需要对DTD进行引用,但是需要doctype来规范浏览器的行为(让浏览器按照他们应该的方式来运行)
而HTML4.01基于SGML,所以需要对DTD进行引用,才能告知浏览器文档所使用的文档类型。

SGML(Standard Generalized Markup Language),即标准通用标记语言;DTD (Document Type Definition)规定了标记语言的规则,这样浏览器才能正确地呈现内容。

 

二、CSS相关

9. px em rem 这三种长度单位的区别?

px是一个绝对单位;em和rem是一个相对单位, em参考的是当前元素的字体(font-size)大小, rem参考的是html元素的字体(font-size)大小.

 

10.CSS3 新增伪类有那些?

p:first-of-type 选择属于其父元素的首个<p>元素。
p:last
-of-type 选择属于其父元素的最后一个<p>元素。
p:nth
-child(2)选择属于其父元素的第二个子元素。
p:nth
-type-of(2)选择属于其父元素的第二个子元素p。
:enabled、:disabled 控制表单控件的禁用状态。
:checked,单选框或复选框被选中。

 

11.谈谈css 选择器优先级顺序以及判定标准?

优先级从低到高:
  通配符选择器 < 标签选择器 < 类选择器(属性选择器) < ID选择器;
  行内样式<使用!important 修饰的属性优先级最高;
  如果两个选择器(属性完全相同)同时命中一个元素, 并且权重一样,则书写顺序会影响优先级, 后一个选择器的属性会覆盖前一个选择器中相同的属性.

 

12.position 几个属性的作用?

position 的常见四个属性值: relative,absolute,fixed,static。一般都要配合"left"、"top"、"right"以及"bottom" 属性使用。
  
1:static:默认位置,(static 元素会忽略任何top、bottom、left 或right 声明)一般不常用。

2:relative:位置被设置为relative 的元素,偏移的top,right,bottom,left 的值都以它原来的位置为基准偏移。注意relative 移动后的元素在原来的位置仍占据空间。

3:absolute:位置设置为absolute 的元素,可定位于相对于包含它的元素的指定坐标。意思就是如果它的父容器设置了position 属性,并且position 的属性值为absolute 或者relative,
那么就会依据父容器进行偏移。如果其父容器没有设置position 属性,那么偏移是以body为依据。注意设置absolute 属性的元素在标准流中不占位置。
4:fixed:位置被设置为fixed 的元素,可定位于相对于浏览器窗口的指定坐标。不论窗口滚动与否,元素都会留在那个位置。它始终是以body 为依据的。注意设置fixed 属性的元素在标准流中不占位置。

 

13.position的relative、absolute与fixed区别?

relative 相对定位,以自己当前处于文档流的位置为基准设置偏移量,所以自身在文档流会保持占有固定的物理空间,并且物理空间的位置只受文档流的影响,而不受自身设置偏移量(top/left这些)影响,
注意自身设置了margin这类非定位属性也一样改变其在文档流的物理位置。

 

absolute 绝对定位,是相对于设置了position为relative或者absolute最近的父级元素定位(body、html标签也需要定位属性才能作为定位父级),如果没有就是基于视窗定位,不占文档流的物理空间。

 

fixed 固定定位,是相对于浏览器视窗的,不占文档流的物理空间。

 

 

14.在一个页面中给多个元素设置相同的id, 会导致什么问题?

会导致通过js获取dom元素的时候, 只能获取到第一个元素, 后面的元素都无法正常获取.

 

15.用伪类实现一个上三角?

/*
为除了上边框以外的所有边框设置相同的宽度
设置左右两边border设为透明色
设置下border为想要的颜色
设置该盒子的宽度为0
*/
.triangle_border_up {
    border-left: 20px solid transparent;
    border-right: 20px solid transparent;
    border-bottom: 20px solid red;
    width: 0;
}

 

16.怎么让一个不定宽高的div,垂直水平居中?

方案一:transform
.parent {
    background: #DDD;
    width: 400px;
    height: 400px;
}

.son {
    position: relative;
    background: pink;
    width: 200px;
    height: 200px;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

 

  方案二:flex 弹性布局

.parent {
    display: flex;
    justify-content: center;
    align-items: center;
    background: #DDD;
    width: 400px;
    height: 400px;
}

.son {
    background: pink;
    width: 200px;
    height: 200px;
}

 

  方案三:绝对定位

.parent {
    position: relative;
    background: #DDD;
    width: 400px;
    height: 400px;
}

.son {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background: pink;
    width: 200px;
    height: 200px;
    margin: auto;
}

 

 

17.清除浮动有哪些常用的方式?

额外标签法: 在浮动元素的最后添加一个块级标签, 给其设置一个clear:both 的属性(缺点:会在页面上产生很多空白标签);
给浮动元素的父元素设置高度:(缺点:不太灵活);
给浮动元素的父元素设置overflow:hidden;
使用伪元素法:(推荐使用):
/*给需要清除浮动的元素添加clear类*/
.clear:after{ content:
''; display:block; overflow:hidden; visibility:hidden; clear:both; }

 

18.让两个块级元素在一行显示有哪些做法?

设置显示模式:display:inline|inline-block;

flex布局: 给父元素设置display:flex;

使用浮动

 

19.如何设置一个元素在垂直方向居中?

首先不考虑代码的灵活性, 可以使用margin 外边距或者padding 内边距来实现元素在垂直方向居中显示.具体可以给父元素设置一个垂直方向的padding 内边距; 

也可以给需要垂直居中的子元素设置垂直方向的外边距.其次如果这个需要垂直居中的元素是一个单行文本,则可以使用行高等于标签高度的方式来实现.

也可以使用css3 中的flex 布局, 使用align-items:center 设置元素在侧轴(垂直方向)居中对齐.

也可以使用绝对定位的方式, 设置元素在相对定位的父元素中垂直对齐.

 

20.说说图片懒加载的原理?实际开发中用过哪些图片懒加载的插件?

img 标签在加载图片的时候, 是通过请求src属性所指向的文件来加载图片的, 那如果img 标签本身没有src属性的话, 那么img标签在渲染的时候,就不会加载图片.
所以图片懒加载的原理就是将img 标签的src属性暂时先改成一个自定义的属性, 这样页面在加载时就会不去自动加载图片, 
当img标签所在区域进入屏幕可视区域后, 从存放图片路径的自定义属性中获取图片地址,并动态的设置给对应img标签的src属性, 
这样浏览器就会自动请求对应的图片资源, 也就实现了所谓的图片懒加载.
图片懒加载的插件有很多,大部分是基于jquery的, 比如jquery.lazyload. 当然vue中也有实现了图片懒加载的插件, 比如vue-lazyload, vue的组件库中也有图片懒加载的组件.

 

21.css3 新增了那些新特性?

媒体查询(@media);

transfrom系列:  translate 平移, scale 缩放,rotate 旋转

动画(animate);

过渡效果(transition);

flex弹性(伸缩)布局;

盒模型计算方式:box-sizing:border-box;

线性渐变(linear-gradient),径向渐变;

伪元素, 文字阴影(text-shadow), 边框阴影(box-shadow), 圆角(border-radius)

 

22.display:none 和visibility:hidden 的区别?


display:none会让元素从渲染树中消失,渲染的时候不占据任何空间;
visibility: hidden不会让元素从渲染树中消失,渲染的时候仍然占据空间,只是内容不可见。
display: none会引发重排,而visiibility: hidden只会引发重绘。

 

display: none是非继承属性,子孙节点消失是由于元素从渲染树中消失造成,通过修改子孙节点的属性无法显示;
visibility: hidden是继承属性,子孙节点消失是由于继承了hidden,通过设置visibility: visible,可以让子孙节点显示。

 

3,读屏器不会读取display:none的元素内容,而会读取visibility:hidden的元素内容。

 

 

23.Less 是什么?

Less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量、Mixin、函数等特性,使 CSS 更易维护和扩展。Less 可以运行在 Node 或浏览器端。

在less中可以定义一些变量和表达式以及使用嵌套语法; 
less 中使用@定义变量(@baseColor:pink); 
后期可以通过一些编译工具(less)将less 编译成浏览器能直接识别的 css 样式. 
所以less 只是在开发阶段使用的一种中间语言, 使用 less 的目的是提高开发效率以及提高代码的可维护性.

 

24.Scss 是什么?(sass)

Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能,
这些拓展令 CSS 更加强大与优雅。使用 Sass 以及 Sass 的样式库(如 Compass)有助于更好地组织管理样式文件,以及更高效地开发项目。
CSS, Sass, SCSS 三者之间的关系请参考:https://www.cnblogs.com/wphl-27/p/9765647.html


scss 是一种css 预处理语言, 在less中可以定义一些变量和表达式以及使用嵌套语法; scss 中使用$定义变量($baseColor:pink); 后期可以通过一些编译工具(node
-sass)将less 编译成浏览器能直接识别的css 样式. 所以scss 只是在开发阶段使用的一种中间语言, 使用scss 的目的是提高开发效率以及提高代码的可维护性.

 

25.Stylus 是什么?(.styl)

Stylus 是一个高效、动态以及丰富的 CSS 预处理器。它同时支持缩进的和通俗的两种风格的 CSS 语法风格。

在stylus 中可以定义一些变量和表达式以及使用嵌套语法(stylus 中是使用缩进的语法表示嵌套关系);
后期可以通过一些编译工具(stylus)将stylus 编译成浏览器能直接识别的css 样式.
所以stylus 只是在开发阶段使用的一种中间语言,使用stylus 的目的是提高开发效率以及提高代码的可维护性.

 

三、JavaScript基础相关:

26.js 中有哪些数据类型

7 种原始类型:
  Boolean
  Null
  Undefined
  Number
  BigInt(现提案阶段)
  String
  Symbol(ES6新增)
和 Object

 

27.typeof(typeof()) 和instanceof 的区别?

typeof:     可以判断变量的数据类型,返回值是字符串;
instanceof:   a instanceof b 用于判断b是不是在a的原型链上, 也可以实现判断数据类型, 返回值为布尔值.

 

28.怎么判断两个对象相等?

先判断俩者是不是对象;
再判断俩个对象的所有key 值是否相等相同;
最后判断俩个对象的相应的key 对应的值是否相同

 

29.js 中函数有哪些定义方式

函数声明:function fn(){}
函数表达式:var fn=function(){}
构造函数:var fn=new Function(‘参数1’,’参数2’,’函数体’)

 

30.js 中函数有哪些调用形式?

普通函数,对象的方法,事件处理函数,构造函数,回调函数

 

31."==" 和"===" 的区别?

==只会对值进行比较,===不仅会对值进行比较,还会对数据类型进行比较.

 

32.js 中的常用内置对象有哪些?并列举该对象的常用方法?

1.Math(数学相关)
  Math.abs(x);           返回指定数值的绝对值
  Math.radom();          返回0到1之间的伪随机数
  Math.ceil(x);          向上取整
  Math.sqrt(x);          返回指定数值的平方根
  Math.pow(x,y);          返回x的y次幂
  Math.max(a,b,c,...);      返回给定的一组数字中的最大值。如果给定的参数中至少有一个参数无法被转换成数字,则会返回NaN

 

2.Date(日期相关)
  Date.now();             返回自 1970-1-1 00:00:00  UTC(世界标准时间)至今所经过的毫秒数
  Date.prototype.getTime();    返回从1970-1-1 00:00:00 UTC(协调世界时)到该日期经过的毫秒数,对于1970-1-1 00:00:00 UTC之前的时间返回负值
  Date.prototype.getFullYear()  根据本地时间返回指定日期对象的年份(四位数年份时返回四位数字)
  Date.prototype.getMonth();   根据本地时间返回指定日期对象的月份(0-11)
  Date.prototype.getDate();    根据本地时间返回指定日期对象的月份中的第几天(1-31)
  Date.prototype.getHours();   根据本地时间返回指定日期对象的小时(0-23)
  Date.prototype.getMinutes();  根据本地时间返回指定日期对象的分钟(0-59)
  Date.prototype.getSeconds();  根据本地时间返回指定日期对象的秒数(0-59)

 

3.Array(数组相关)
  Array.from();           从类数组对象或者可迭代对象中创建一个新的数组实例
  Array.isArray();         用来判断某个变量是否是一个数组对象
  Array.of();            根据一组参数来创建新的数组实例,支持任意的参数数量和类型
  Array.prototype.push();     在数组的末尾增加一个或多个元素,并返回数组的新长度
  Array.prototype.reverse();   颠倒数组中元素的排列顺序,即原先的第一个变为最后一个,原先的最后一个变为第一个
  Array.prototype.pop();      删除数组的最后一个元素,并返回这个元素
  Array.prototype.splice();    该方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组

 

4.Object(对象相关)
  Object.prototype.toString()  返回对象的字符串表示
  Object.is();           比较两个值是否相同。所有 NaN 值都相等(这与==和===不同)
  Object.keys();          返回一个包含所有给定对象自身可枚举属性名称的数组
  Object.values();         返回给定对象自身可枚举值的数组
  Object.seal();          防止其他代码删除对象的属性

 

 

33.列举和数组操作相关的方法

push: 将元素添加到数组的末尾, 返回值是数组长度
pop: 将数组最后一个元素弹出, 返回值是被弹出的元素
unshift: 在数组的开头插入一个元素,返回值是数组的长度
shift: 将数组第一个元素弹出,返回值是被弹出的元素
splice(index,len): 删除数组中指定元素
concat: 连接数组
reverse: 翻转数组

 

34.列举和字符串操相关的方法

substr(start,len)/substring(start,end): 截取字符串
slice:从数组字符串中截取一段
indexOf/lastIndexOf:查找某一个字符是否存在于另外一个字符串中, 存在则返回索引, 不存在则返回-1;indexOf 是从前向后顺序查找;lastIndexOf是从后向前查找
replace:替换字符串特定的字符
toUpperCase:将字符串转成大写
toLowerCase:将字符串转成小写
charAt:获取字符串中指定索引的字符

 

35.document.write 和innerHTML 的区别?

document.write 是指定整个页面区域的内容, innerHTML 是指定某一个元素的内容.

 

36.分别阐述split(),slice(),splice(),join()?

split 可以使用一个字符串切割另外一个字符串, 返回值是数组;
slice 可以从数组中截取一部分(字符串对象也有slice 方法);
splice(index,len)可以删除指定的数组元素;
join 可以将数组元素使用特定的连接符拼接成字符串;

 

37.JavaScript的强制类型转换?

转化成字符串:toString() 、String() 、+拼接
转换成数字:Number() 、parseInt()、parseFloat();
转换成布尔类型:Boolean()

 

38.如何判断一个变量foo 是数组?

foo instanceof Array;
foo.constructor == Array;
Array.isArray(foo)
Object.prototype.toString.call(foo)=="[object Array]"

 

三、JavaScript基础相关:

39.什么是原型对象?

每一个构造函数都有一个prototype的属性,这个属性的值是一个对象,这个对象就叫做构造函数的原型对象; 
一般建议将构造函数的成员属性绑定在原型对象prototype上,因为原型对象prototype身上的属性默认可以通过实例对象访问到;
这样做可以保证在每次通过new关键字创建实例对象的时候,这些方法不会被重复在内存中创建.

 

40.什么是原型链?

每个构造函数都有一个prototype 属性, 即原型对象, 通过实例对象的___proto___属性也可访问原型对象;
而原型对象本质也是一个对象, 是对象就有自己的原型对象, 最终形成的链状的结构称为原型链.

 

41.什么是构造函数?

构造函数本质也是一个函数, 只不过这个函数在定义的时候首字母一般需要大写; 构造函数调用的时候,必须通过一个new关键字来调用; 
我们一般不直接使用构造函数, 而是使用构造函数创建出来的实例对象. 构造函数是js 面向对象的一个重要组成部分.

 

42.js 中实现继承的方式?

ES6 之前官方并没有提供一种实现继承的语法, 所以大部分继承方式都是程序员通过代码在模拟,常见的继承方式有以下几种:
  1.原型继承;
  2.借用构造函数继承;
  3.组合继承;
  4.
ES6 之后使用extends 关键字实现继承(class Student extendsPerson{})

 

43.什么是闭包, 有什么作用, 使用的时候需要注意什么?

闭包是一个跟函数相关的概念,表现形式是一个父函数内部,嵌套了一个子函数, 子函数直接或间接的被返回给外部作用域, 并且子函数中会使用到父函数局部作用域中的变量.当我们在外部调用这个子函数的时候, 就会发生闭包现象.
闭包的定义:闭包是指有权访问另一个函数作用域中的变量的函数。
闭包的作用:闭包可以延展一个函数的作用域
注意事项:不能滥用闭包, 会导致内存泄漏

 

44.什么是内存泄漏, 哪些操作会引起内存泄漏?

内存泄漏是指本应该被垃圾回收机制回收的内存空间由于某种特殊原因没有被及时回收,滥用全局变量和滥用闭包都会导致内存泄漏.

 

45.什么是预解析?

JS 代码在执行之前,解析引擎会对代码进行一个预先的检查, 主要会对变量和函数的声明进行提升, 将变量和函数的声明提到代码的最前面,变量只提升声明,不提升赋值.

 

46.说说你对this 关键字的理解

this的定义:this表示当前执行代码的环境对象
this在不同的场景下指向不太一样, 主要分为以下几种情况:   普通函数中指向全局对象window;   对象的成员方法中指向该方法的宿主对象;   构造函数中指向new出来的实例对象;   事件处理函数中指向事件源;   回调函数中指向全局对象window

 

47.call/apply/bind 的区别

这三个方法都是Function这个特殊对象的方法,通过这三个方法都可以改变函数内部this的指向.
不同点:   call 和apply 会调用一次函数, 而bind 不会调用函数, 只会在内存中创建一个函数的副本(修改过this指向的函数).   call 从第二个参数开始需要一个参数列表,   apply 的第二个参数要求是一个数组

 

48.new 操作符具体干了什么呢?

第一步:  创建一个空对象;
第二步:  将this 指向空对象;
第三步:  动态给刚创建的对象添加成员属性;
第四步:  隐式返回this

 

49. 下面代码的执行结果是什么?

var helloWord=(function(){
  console.log('hello one');
  setTimeout(function(){
  console.log('hello two');
},100);
setTimeout(function(){
  console.log('hello three');
},0);
console.log('hello four');
}());

依次输出: hello one,hello four,hello three,hello two

 

 

50. 下面代码执行结果是什么?

var a={
  id:10
}
b=a;
b.id=1;
b.name='test';
console.log(a);
输出{id: 1, name: "test"}
 
分析过程:对象是一种引用数据类型, 简单的b=a 只是把a 在内存中的地址赋值给了b, 所以修改b 会影响a.

 

51. 下面代码执行结果是什么?

var length=10;
function fn(){
  console.log(this.length);
}
var obj={
  length:5,
  method:function(fn){
    fn();
    arguments[0]();
  }
}
obj.method(fn,1);
执行结果:在控制台输出10,2

 

分析过程:
  fn(); 此时this 指向window, 所以this.length=10;
  arguments[0]()中的this 永远指向arguments,而arguments本身有一个length 属性,就是参数的个数.

 

 

52. 下面代码执行完毕, 浏览器依次弹出什么?

(function test(){
  var a=b=5;
  alert(typeof a);
  alert(typeof b);
})()
alert(typeof a);
alert(typeof b);
执行结果:依次弹出: number; number,undefined,number

 

分析过程:自调用函数会开辟一个局部作用域, var a=b=5 这句代码var只会修饰a,所以a是一个局部变量, b是全局变量

 

 

53. 下面代码输出结果是什么?

[1,2,3].map(function(item,index){
  // console.log(item,index);
  //parseInt(数值,进制)
  parseInt(1,0);
  parseInt(2,1);
  parseInt(3,2);
});
[1,2,3].map(parseInt);
输出结果:[1,NaN,NaN];

 

54. 下面代码执行结果是什么?

console.log(square(5));
var square=function(n){
  return n*n;
}
执行结果:报错(Uncaught TypeError: square is not a function)
分析过程:函数表达式方式声明的函数只提升声明, 不提升赋值, 所以不能再声明之前调用.
 

 

55. 下面代码执行结果是什么?

console.log(2.0=='2'==new Boolean(true)=='1');
执行结果: 输出true
分析过程: 2.0==’2’ 返回true;   true==new Boolean(true) 返回true;  true==’1’返回true;   所以最终结果是true.

 

 

56. 下面的代码会输出什么?怎么改动下面代码, 使其依次输出1,2,3,4,5

for(var i=1;i<=5;i++){
    setTimeout(function(){
        console.log(i);
    },1000);
}
执行结果:在控制台输出:6,6,6,6,6,原因在于setTimeout中的代码是异步执行的,
在该例子中,不论延时时间长或短,log语句总是会在循环结束后才打印i的值,而此时i早已完成循环递增,变为了终值6

改造后的代码:

for (var i = 1; i <= 5; i++) {
    (function (i) {
        setTimeout(function () {
            console.log(i);
        }, 1000*i)
    })(i)
}
或者使用es6 let声明变量i
for (let i = 1; i <= 5; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000 * i)
}

 

 

57. 下面代码执行结果是什么?

var a=10;
function Foo(){
    if(true){
        let a=4;
    }
    alert(a);
}
Foo(); 
执行结果: 弹出10
分析过程: let声明的变量有块级作用域, 所以let声明的a只在if条件的花括号中生效, 所以会向上级作用域查找.
 

 

58. 使用js 封装一个冒泡排序

// 方案1
function sortBubble(arr){
  for(var i=0;i<arr.length;i++){
        for(var j=0;j<arr.length-i;j++){
            if(arr[j]>arr[j+1]){
              var temp=arr[j];
          arr[j]=arr[j+1];
         arr[j+1]=temp;
        }
       }
  return arr;
}

 

//方案2
function sortBubble(ary) {
    for (var i = 0; i < ary.length - 2; i++) {
        for (var j = i + 1; j < ary.length; j++) {
            if (ary[i] > ary[j]) {
                temp = ary[i];
                ary[i] = ary[j];
                ary[j] = temp;
            }
        }
    }
    return ary;
}

 

//方案3(单重循环)
function sortBubble(ary) {
    for (var i = 0, j = i + 1; i < ary.length - 2; j++) {
        if (ary[i] > ary[j]) {
            temp = ary[i];
            ary[i] = ary[j];
            ary[j] = temp;
        }
        if (j == ary.length - 1) {
            i++;
            j = i + 1;
        }
    }
    return ary;
}

 

 

59. 封装一个方法实现去除数组中的重复元素

方案1:
function unique(arr){
  var newArr=[];
  for(var i=0;i<arr.length;i++){
    if(newArr.indexOf(arr[i])==-1){
      newArr.push(arr[i]);
    }
  }
  return newArr;
}

 

 方案二:

var arr = [1,2,2,3,3,4];
var newArr = Array.from(new Set(arr));

分析过程:
Set是es6中新增的一种数据类型,和数组很类似,但是元素不能重复;
Array.from也是es6新增的方法,可以将类数组对象(伪数组、set),转换成数组.

 

 

60. 已 知 数 组 var arr=[‘This’, ’is’, ‘Woqu’, ‘Company’], alert 出 ”This is Woqu Company”.

var arr=[‘This’, ’is’, ‘Woqu’, ‘Company’];
alert(arr.join(' '));alert(arr.join(' '));

 

61. 编写一个 js 函数 parseQueryString, 它的用途是把 url 中的参数解析为一个对象, 如”http://www.demo.cn/index.html?key1=val1&key2=val2”

var url = "http://www.demo.cn/index.html?key1=val1&key2=val2";

function parseQueryString(argu) {
    var str = argu.split('?')[1];
    var result = {};
    var temp = str.split('&');
    for (var i = 0; i < temp.length; i++) {
        var temp2 = temp[i].split('=');
        result[temp2[0]] = temp2[1];
    }
    return result;
}

console.log("解析url参数:", parseQueryString(url));

 

62. 统计 'gjhgadfgskgjfajhdegwqeg'字符串中出现最多的字母?

var str = 'gjhgadfgskgjfajhdegwqeg';

function countStr(str) {
var json = {};
var iMax = 0;
var iIndex = '';
// 循环完毕后会得到一个对象,如{a:0,b:1,c:2,d:3,e:4} for (var i = 0; i < str.length; i++) { if (!json[str.charAt(i)]) { json[str.charAt(i)] = 1; } else { json[str.charAt(i)]++; } }; // 查找出现次数做多的字符,和出现次数 for (var i in json) { if (json[i] > iMax) { iMax = json[i]; iIndex = i; } } return { count: iMax, //出现的最多次数 char: iIndex //出现次数最多的字符 } } console.log("字符统计:", countStr(str));

 

63. 编码实现对象深拷贝

function deepClone(obj) {
    let cloneObj = null;
    if (obj instanceof Object) {
        let isArray = Array.isArray(obj);
        cloneObj = isArray ? [] : {};
        for (let key in obj) {
            cloneObj[key] = obj[key] instanceof Object ? deepClone(obj[key]) : obj[key];
        }
    } else {
        throw new Error('obj 不是一个对象!');
    }
    return cloneObj;
}

 

64. 有 Student 和 Person 两个类, Person 类有 name 属性和 sayName 方法, Student 类继承自 Person 类. 分别使用 ES5 和 ES6 的语法实现.

ES6 实现:
//定义父类
class Person {
    //父类构造方法
    constructor(name) {
        this.name = name;
    }

    //父类定义方法
    sayName() {
        console.log("The name is: " + this.name);
    }
}

//定义子类
class Student extends Person {
    //子类构造方法
    constructor(name, age) {
        super(name);
        this.age = age;
    }

    //子类定义方法
    showAge() {
        console.log("The age = " + this.age);
    }
}

//创建父类对象
let person = new Person("zs");
person.sayName();

//创建子类对象
let student = new Student("ls", 20);
student.sayName();
student.showAge();

 

ES5 实现:

//父类构造函数
function Person(name) {
    this.name = name;
}
Person.prototype.sayName = function() {
    console.log(`My name is ${this.name}`);
}

//子类构造函数
function Student(name, age) {
    Person.call(this, name);
    this.age = age;
}
//将子类原型对象指向一个父类对象以继承父类的属性和方法
Student.prototype = new Person();
//将子类自定义方法挂载到原型对象上
Student.prototype.showAge = function() {
    console.log(`My age is ${this.age}`)
};
//将原型对象的constructor指回子类构造函数本身以修正子类原型对象的指向错误
Student.prototype.constructor = Student;

//创建父类对象
let person = new Person("zs");
person.sayName();

//创建子类对象
let student = new Student("ls", 20);
student.sayName();
student.showAge();

 

 

65. 写一个左中右布局占满屏幕, 其中左右两块固定宽度 200,中间自适应,要求先加载中间块, 请写出结构和样式

Css 样式
<style>
    * {
        padding: 0;
        margin: 0;
    }
    
    html,
    body {
        height: 100%;
    }
    
    .center {
        height: 100%;
        background: #1FA363;
        margin: 0 200px;
    }
    
    .left {
        position: absolute;
        width: 200px;
        height: 100%;
        left: 0;
        top: 0;
        background: #DC4C3F;
    }
    
    .right {
        position: absolute;
        width: 200px;
        height: 100%;
        right: 0;
        top: 0;
        background: #FFCE44;
    }
</style>

html 结构:

<body>
    <div class="center">center</div>
    <div class="left">left</div>
    <div class="right">right</div>
</body>
思路分析: html 标签的加载顺序是自上而下, 所以要想让中间部分先加载, 只需要把中间部分的标签写在最前面即可.

 

 

66. 如何扩展 jquery 的静态方法, 如$.getName();

$.extend({
    getName: function () {
        // do something
    }
});

 

67. 使用 js 求 10000 以内的所有质数的和

求 10000 以内的所有质数的和
//求质数和
function getZs(num) {
    var sum = 0;
    for (var i = 2; i <= num; i++) { //4
        //假设所有的数都是质数
        var flag = true;
        //通过嵌套循环找到 i 除了 1 和本身以外所有可能出现的因子
        for (var j = 2; j < i; j++) {
            //判断 i 是否为质数
            if (i % j == 0) { //能进到当前的分支 说明不是质数
                flag = false;
            }
        }
        if (flag == true) {
            sum += i;
        }
    }
    return sum;
}
console.log("10000以内的素数和= ", getZs(10000));
输出指定范围内的素数(优化写法)
//输出指定范围内的素数
function getPrimenumber(n) {
    var flag = 0;
    var result = [2, 3];
    for (i = 3; i <= n; i += 2) {
        for (j = 2; j <= Math.sqrt(i); j++) {
            if (i % j == 0) {
                flag = 0;
                break;
            } else {
                flag = 1;
            }
        }
        if (flag == 1) {
            result.push(i);
            flag = 0;
        }
    }
    return result;
}

 

 

68. 使用js 打印出1-10000 之间的所有对称数(如121, 1331)

function isSymNum(start, end) {
    start = (start <= 11 ? 11 : start);
    for (var i = start; i <= end; i++) {
        var strI = +(i.toString().split('').reverse().join(''));
        if (strI == i) {
            console.log(i);
        }
    }
}
isSymNum(1, 10000);

 

69. 二维数组根据num 的值进行升序排序

var list = [{id: 32,num: 5}, {id: 28,num: 12}, {id: 23,num: 9}];
list.sort(function(a, b) {
return a.num - b.num; }) console.log(list);

 

70. Js 中eval 的功能是什么? 缺点是什么?

eval 函数的作用: 可以将一个字符串当做js 代码执行.
eval 函数的缺点: 执行效率比较低, 不安全.

 

71. 有一个数列(0,1,1,2,3,5,8,13,21...),定义函数求数列第n项 (斐波那锲数列)

function getFibo(n) {
     if (n == 1) return 0;
     if (n == 2) return 1;
     return getFibo(n - 1) + getFibo(n - 2);
}

 

72. 使用什么办法能让如下条件判断成立?

if(a==1&&a==2&&a==3){
    console.log('ok')
}

//方案一:
var a = {
    value: 1,
    toString: function() {
        return this.value++;
    }
}

 

//方案二:
var
a = [1, 2, 3]; a.join = a.shift;
//数组作隐式转换时会自动调用join方法,可以将join方法替换为shift方法以达到目的

 

//方案三:
var init = 1;
Object.defineProperty(window, 'a', {
    get: function() {
        return init++;
    }
});
 

 

73. 下面代码输出结果是什么?

function changeObjectProperty(o) {
    o.siteUrl = "http://www.csser.com/";
    o = new Object();
    o.siteUrl = "http://www.popcg.com/";
}
var CSSer = new Object();
changeObjectProperty(CSSer);
console.log( CSSer.siteUrl );

结果:
http://www.csser.com/

 

四、WebAPI相关:

74.列举DOM 元素增删改查的API

创建DOM: document.createElement();

查找DOM:
    document.getElementById();
    document.getElementsByClassName();
    document.getElementsByName();
    document.querySelectorAll();
    document.querySelector();

 

追加DOM: parentDom.appendChild();

 

移除DOM: parentDom.removeChild();

 

 

75.BOM 中有哪些常用的对象?

location:
    location.href; 页面url 地址
    location.hash; url 中#后的部分
    location.search; url 中?后的部分(查询字符串)
    location.reload(); 刷新页面;

navigator:    navigator.userAgent: 浏览器的userAgent信息

 

history:
    history.go(1);前进1步
    history.go(-1);后退1步;
    history.forward();前进
    history.back(); 后退

 

screen:
    screen.availWidth: 屏幕有效宽度
    screen.availHeight: 屏幕有效高度

 

 

76.列举几个常见的浏览器兼容问题?

主流浏览器发送ajax 使用XMLHttpRequest 创建异步对象,
IE 浏览器时候用XActive 创建异步对象;

 

主流浏览器注册事件
    addEventListener("eventType","handler","true|false");
    removeEventListner("eventType","handler","true|false");
IE 浏览器注册事件:
    注册事件:attachEvent( "eventType""handler")
    移除事件:detachEvent("eventType""handler" )

 

阻止事件冒泡:
    主流浏览器:event.stopPropagation()
    IE 浏览器:event.cancleBubble=true;

 

获取事件源:
    主流浏览器: event.target
    IE 浏览器:event.srcElement

 

77.什么是事件委托以及时间委托的原理?

事件委托:    本应该注册给子元素的事件, 注册给父元素

 

事件委托的原理:事件冒泡, 因为有事件冒泡的存在, 所以子元素的事件会向外冒泡,触发父元素的相同事件, 根据事件对象可以找到真正触发事件的事件源.

 

79.Javscript 中有几种定时器, 有什么区别?

setInterval: 间歇定时器, 间隔一定的时间就执行, 执行多次;
setTimeout: 延时定时器, 只执行一次

 

80.如何实现多个标签页的通信?

localStorage 可以实现同一浏览器多个标签页之间通信

localStorage 是Storage 对象的实例。对Storage 对象进行任何修改,都会在文档上触发storage 事件。
当通过属性或者setItem()方法保存数据,使用delete 操作符或removeItem()删除数据,或者调用clear()方法时,都会触发该事件。
通过监听该事件就可以实现多个标签页之间的通信

 

//监听storage的改变
window.addEventListener("storage",function(event){ //do something },false);

 

 

81. jquery 中的$.each 和$(selector).each()有什么不同?

$.each 可以循环任何数组, 包括普通数组和jquery 对象组成的伪数组;
$(selector).each()只能循环遍历jquery 对象组成的伪数组.

 

82. Jquery 中$.each 和原生js 中的forEach 方法有什么区别?


1.jQuery中的$.each 不仅可以遍历普通数组, 还可以遍历jQuery对象的伪数组, 原生js中的forEach只能遍历普通数组;

2.参数列表不同
  //jquery
  $.each( obj/arr, function( key, value ) {   alert( key
+ ": " + value );   });

  //JavaScript
  arr.forEach(function callback(value, index, array) {
    //your iterator
    //thisArg代表this对象
  }, thisArg);

 

 

83. 原生JS 的window.onload 与Jquery 的$(document).ready(function(){}),$(function () {})有什么不同?

执行时机不一样: 
  window.onload 会等待页面元素渲染完毕并且资源文件加载完毕后才会执行;
  $(document).ready(function() {})是当页面元素渲染完毕后就会执行, 所以执行时机先于window.onload

 

84. Jquery 实现连式编程的原理是什么?

jquery中的方法中最后都会return 一个this, 这个this 就是当前元素的jquery对象

 

85. Jquery 如何多次给同一个标签绑定同一个事件?

使用addEventListener(‘事件名’,function(){})注册的事件, 不会出现事件覆盖, jquery中也是这样做的.

 

86. 如何开发jquery 插件?

Jquery 提供了两种开发插件的方式:
//$.fn: 可以通过任意jquery 对象来调用
$.fn.green=function(){
console.log(this,$(this));
$(this).css({background:'green'});
}
// 调用以后, div 的背景色会被设置成green
$("div").green();

 

$.extend: 开发的插件只能通过$顶级对象来调用
// 定义
$.extend({
    alert: function (msg) {
        alert(msg);
    }
});
// 调用
$.alert('这是提示信息')

 

 

87. Jquery 中那些方法不支持链式操作?

$.trim(); 
$.each();
$(selector).html();
$(selector).text();

 

88. H5 都新增了那些新特性?

语义化的标签:  (header,nav,footer,aside,article,section)
本地存储:    sessionStorage,localStorage;
拖拽释放:    (Drag and drop) API 音频、视频API(audio,video)
画布:      (Canvas) API
地理:      (Geolocation) API
表单控件:    calendar、date、time、email、url、search
新的技术:    websocket

 

89. sessionStorage,localStorage 和cookie 三者有什么区别?

共同点:它们三者都是浏览器端的存储介质, 可以存储一些数据.

 

不同点:
sessionStorage 是将数据存储在页面的内存中, 所以数据会跟随页面的关闭而销毁, 存储数据相对较少(5M 左右), 只能存储键值对;

 

localStorage 是将数据存储在电脑的磁盘上, 存储数据量大(20M 左右),需要手动删除, 只能存储键值对;

 

cookie 是http 协议的重要组成部分, 存储数据量相对比较少(4K 左右),存储cookie 的时候可以设置过期时间, 到达过期时间后, 会自动销毁,如果没有设置, 则跟随浏览器的关闭而销毁. 
cookie 中存储的数据会伴随每一次http 请求被发送到服务端, 所以不建议在cookie 中存储大量数据.

 

 

 

90. 使用jquery 写出一个简单的$.ajax 的请求

$.ajax({
    url:'/api',
    type:'post',
    data:{},
    dataType:'json',
    success:function(res){
        console.log(res);
    }
});

 

91. 常见HTTP 状态码都有哪些?

100 => 正在初始化(一般是看不到的)
101 => 正在切换协议(websocket 浏览器提供的)
200 或者以2 开头的两位数=> 都是代表响应主体的内容已经成功返回了
202 => 表示接受
301 => 永久重定向/永久转移
302 => 临时重定向/临时转移(一般用来做服务器负载均衡)
304 => 本次获取的内容是读取缓存中的数据,会每次去服务器校验
400 => 参数出现错误(客户端传递给服务器端的参数出现错误)
401 => 未认证,没有登录网站
403 => 禁止访问,没有权限
404 => 客户端访问的地址不存在
500 => 未知的服务器错误
503 => 服务器超负荷(假设一台服务器只能承受10000 人,当第10001 人访问的时候,如果服务器没有做负载均衡,那么这个人的网络状态码就是503)

 

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

1. GET 请求指定的页面信息,并返回实体主体。
2. HEAD 类似于get 请求,只不过返回的响应中没有具体的内容,用于获取报头
3. POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。
4. PUT 从客户端向服务器传送的数据取代指定的文档的内容。
5. DELETE 请求服务器删除指定的页面。
6. CONNECT HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
7. OPTIONS 允许客户端查看服务器的性能。
8. TRACE 回显服务器收到的请求,主要用于测试或诊断。
9. PATCH 实体中包含一个表,表中说明与该URI 所表示的原内容的区别。
10. MOVE 请求服务器将指定的页面移至另一个网络地址。
11. COPY 请求服务器将指定的页面拷贝至另一个网络地址。
12. LINK 请求服务器建立链接关系。
13. UNLINK 断开链接关系。
14. WRAPPED 允许客户端发送经过封装的请求。
15. LOCK 允许用户锁定资源,比如可以再编辑某个资源时将其锁定,以防别人同时对其进行编辑。
16. MKCOL 允许用户创建资源
17. Extension-mothed 在不改动协议的前提下,可增加另外的方法。

 

93. 请尽可能详尽的解释ajax 的工作原理

第一步:创建一部对象var xhr=new XMLHttpRequest()
第二步:设置请求行xhr.open(‘请求方式’,请求地址);
第三步:发送请求Get 方式xhr.send(null),
如果是post 请求还要设置请求头

xhr.setRequestHeader('Content-Type','application/x-www-formurlencoded');
xhr.send("name=zs&age=18");
//第四步:监听服务端的响应
xhr.onreadystatechange=function(){
    if(xhr.status==200&&xhr.readyState==4){
    // 获取json
    var json=xhr.responseText&&JSON.parse(xhr.responseText)
    // 获取xml
    var xml=xhr.responseXML;
    console.log(json,xml)
    }
}

 

94. 页面编码和被请求的资源编码如果不一致如何处理?

a.html的编码是gbk或gb2312的。而引入的js编码为utf-8的,那就需要在引入的时候使用:<script src="http://www.xxx.com/test.js" charset="utf-8"></script>
同理,如果你的页面是utf-8 的,引入的js 是gbk 的,那么就需要加上charset="gbk".

 

95. 如何解决跨域问题?jsonp 跨域的原理是什么?

动态在页面中创建一个script 标签, 使其src 属性指向后端数据接口,后端数据接口必须返回一个js 函数的调用字符串( 如cb(‘{“name”:”zs”,”age”:18}’)), 
将要返回给前端的json 数据作为函数的实参, 当script 标签加载完毕后会在浏览器中执行后端返回的函数调用,所以前端必须事先对调用的函数进行声明.
因为函数是在js 中声明的, 所以可以在函数内部拿到服务端调用的时候传入的实参, 所以就间接实现了跨域请求数据.

 

97. 什么是同步和异步, 那种执行方式更好?

同步是指一个程序执行完了接着去执行另外一个程序, 异步是指多个程序同时执行. 所以异步效率更高, 因为异步不会出现阻塞现象,前一个程序的执行不会影响后一个程序的执行.

 

98.GET 和POST 的区别,何时使用POST?

get是将要传递的参数拼接在url中进行传递,传递数据量少,不安全。
post是将传递的参数放在请求体里传递,携带数据量大,相对安全,要提交一些敏感数据(比如登录),上传文件时,必须使用post请求.

 

posted @ 2019-09-24 13:58  feihu1024  阅读(926)  评论(0编辑  收藏  举报