1、数组去重的方式
方式一:使用ES6的Set进行去重
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>数组去重</title> </head> <body> <script type="text/javascript"> function array_dedup(arr){ return Array.from(new Set(arr)); } let arr=array_dedup([1,2,3,3,4,5,5,6]); console.log(arr);//1,2,3,4,5,6 </script> </body> </html>
方式二:使用indexof去重
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>数组去重</title> </head> <body> <script type="text/javascript"> let arrs=[1,2,3,4,5,5,6]; function arraydedep(arr){ let temp=[]; for(let i=0;i<arr.length;i++){ if(temp.indexOf(arrs[i])==-1){ temp.push(arrs[i]) } } return temp; } let arr=arraydedep(arrs); console.log(arr);//1,2,3,4,5,6 </script> </body> </html>
方式三:扩展运算符和Set实现去重
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>数组去重</title> </head> <body> <script type="text/javascript"> let arr=[1,2,2,3,3,4,5]; let unique=[...new Set(arr)]; console.log(unique);//输出1,2,3,4,5 </script> </body> </html>
参考资料:https://www.cnblogs.com/jjgw/p/11574495.html
2、说说深拷贝和浅拷贝
浅拷贝:浅拷贝是对象共用一个内存地址,对象的变化相互影响。比如常见的赋值引用就是浅拷贝
深拷贝:深拷贝是将对象放到一个新的内存中,两个对象的改变不会相互影响或者你可以理解为浅拷贝由于只是复制一层对象的属性,当遇到有子对象的情况时,子对象就会互相影响。所以,深拷贝是对对象以及对象的所有子对象进行拷贝。
浅拷贝实现方式:
1、简单对象的浅拷贝
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>对象的浅拷贝</title> </head> <body> <script type="text/javascript"> var obj1={name:'cat'}; var obj2=obj1; obj2.name='dog'; console.log(obj1);//{name:'dog'} console.log(obj2);//{name:'dog'} </script> </body> </html>
2、使用循环实现浅拷贝
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>使用循环实现浅拷贝</title> </head> <body> <script type="text/javascript"> var person={ name:'tt', age:18, friends:['aa','bb','cc'] } function shallowCopy(source){ if(!source||typeof source!=='object'){ throw new Error('error'); } var targetObj=source.constructor===Array?[]:{}; for(var keys in source){ if(source.hasOwnProperty(keys)){ targetObj[keys]=source[keys] } } return targetObj; } var p1=shallowCopy(person); console.log(p1);//{name:'tt',age:18,friends:['aa','bb','cc']} </script> </body> </html>
深拷贝实现方式:
1、递归调用浅拷贝实现深拷贝
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>递归实现深拷贝</title> </head> <body> <script type="text/javascript"> var obj1={ name:'cat', show:function(){ console.log('名称:'+this.name); } } var obj2=deepClone(obj1); obj2.name='pig'; obj1.show();//cat obj2.show();//pig function deepClone(obj){ var objClone=Array.isArray(obj)?[]:{}; if(obj&&typeof obj==='object'){ for(key in obj){ if(obj.hasOwnProperty(key)){ //判断obj子元素是否为对象,如果是,递归复制 if(obj[key]&&typeof obj[key]==='object'){ objClone[key]=deepClone(obj[key]) }else{ //如果不是,简单复制 objClone[key]=obj[key] } } } } return objClone; } </script> </body> </html>
2、利用 JSON 对象中的 parse 和 stringify实现深拷贝
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>利用 JSON 对象中的 parse 和 stringify</title> </head> <body> <script type="text/javascript"> var obj1={ name:'cat', show:function(){ console.log(this.name); } } var obj2=JSON.parse(JSON.stringify(obj1)); obj2.name='dog'; console.log(obj1.name);//cat console.log(obj2.name);//dog obj1.show();//cat obj2.show();//TypeError: obj2.show is not a function </script> </body> </html>
3、使用Object.assgin()方法实现深拷贝
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>使用Object.assgin()方法</title> </head> <body> <script type="text/javascript"> let srcObj = {'name': 'lilei', 'age': '20'}; let copyObj2 = Object.assign({}, srcObj, {'age': '21'}); copyObj2.age = '23'; console.log(srcObj);//{name:'lilei',age:20} console.log(copyObj2);//{name:'lilei',age:23} srcObj = {'name': '明', grade: {'chi': '50', 'eng': '50'} }; copyObj2 = Object.assign({}, srcObj); copyObj2.name = '红'; copyObj2.grade.chi = '60'; console.log(srcObj);//{name:'红',grade:{chi:60,eng:50}} </script> </body> </html>
参考文章:https://www.cnblogs.com/jjgw/p/11744143.html
3、请说出减低页面加载时间的方法
- 合并css、js文件,减少http请求
- 压缩js、css文件
- 减少dom操作、尽可能用变量代替dom的操作
4、null和undefined的区别?
- null是一个无的对象,转换数值时为0,undefined表示一个无的原始值,转换数值时为NaN
- 当声明的变量还未初始化时,值为undefined,null用来表示尚未存在的变量
- undefined表示缺少值,就是此处应该有一个值,但是这个值未定义
- null表示没有对象,即该处不应该有值
undefined典型用法:
- 变量被声明了,但没有赋值时,就等于undefined。
- 调用函数时,应该提供的参数没有提供,该参数等于undefined。
- 对象没有赋值的属性,该属性的值为undefined。
- 函数没有返回值,默认返回undefined。
null典型用法:
- 作为函数的参数,表示该函数的参数不是对象。
- 作为对象原型链的终点。
5、get和post之间的区别?
- 传输大小,get比post要小
- get请求参数会保留在历史记录中,而post不会
- post时加密传输,get时明文传输
- get只能接受url编码,post没有限制
6、常见的浏览器及内核分别是什么?
- IE:trident内核
- FireFox:gecko内核
- Safari:webkit内核
- Opera:blink内核
- Chrome:以前webkit内核,现在blink内核
7、请你谈谈Cookie的弊端
-
每个特定的域名下最多生成的cookie个数有限制
-
IE和Opera 会清理近期最少使用的cookie,Firefox会随机清理cookie
-
cookie的最大大约为4096字节,为了兼容性,一般不能超过4095字节
-
安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息
8、对BFC规范的理解
- BFC全称是Block Formatting Context,即块格式化上下文。它是CSS2.1规范定义的,关于CSS渲染定位的一个概念。BFC是页面CSS 视觉渲染的一部分,用于决定块盒子的布局及浮动相互影响范围的一个区域。
- BFC的一个最重要的效果是,让处于BFC内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响。利用BFC可以闭合浮动,防止与浮动元素重叠
9、什么叫优雅降级和渐进增强?
- 渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
- 优雅降级:一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。
区别:
- 优雅降级是从复杂的现状开始,并试图减少用户体验的供给
- 渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要
- 降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带
10、前端页面有哪三层构成,分别是什么?作用是什么?
- 结构层:由 HTML 或 XHTML 之类的标记语言负责创建,仅负责语义的表达。解决了页面“内容是什么”的问题。
- 表示层:由CSS负责创建,解决了页面“如何显示内容”的问题。
- 行为层:由脚本负责。解决了页面上“内容应该如何对事件作出反应”的问题。
11、请说说你对标签语义化的理解?
- 去掉或者丢失样式的时候能够让页面呈现出清晰的结构
- 有利于SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息:爬虫依赖于标签来确定上下文和各个关键字的权重;
- 方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义的方式来渲染网页;
- 便于团队开发和维护,语义化更具可读性,遵循W3C标准的团队都遵循这个标准,可以减少差异化
12、Doctype作用? 严格模式与混杂模式如何区分?它们有何意义?
- <!DOCTYPE> 声明位于文档中的最前面,处于 <html> 标签之前。告知浏览器以何种模式来渲染文档。严格模式的排版和 JS 运作模式是,以该浏览器支持的最高标准运行。
- 在混杂模式中,页面以宽松的向后兼容的方式显示。模拟老式浏览器的行为以防止站点无法工作。DOCTYPE不存在或格式不正确会导致文档以混杂模式呈现。
13、HTML与XHTML——二者有什么区别
- XHTML 元素必须被正确地嵌套。
- XHTML 元素必须被关闭。
- 标签名必须用小写字母。
- XHTML 文档必须拥有根元素。
14、请列举几种隐藏元素的方法
- visibility: hidden;这个属性只是简单的隐藏某个元素,但是元素占用的空间任然存在。
- opacity: 0;一个CSS3属性,设置0可以使一个元素完全透明,制作出和visibility一样的效果。
- position: absolute;使元素脱离文档流,处于普通文档之上,给它设置一个很大的left负值定位,使元素定位在可见区域之外。
- display: none;元素会变得不可见,并且不会再占用文档的空间。
- transform: scale(0);将一个元素设置为无限小,这个元素将不可见。这个元素原来所在的位置将被保留。
- HTML5 hidden attribute;hidden属性的效果和display:none;相同,这个属性用于记录一个元素的状态。
- height: 0; overflow: hidden;将元素在垂直方向上收缩为0,使元素消失。只要元素没有可见的边框,该技术就可以正常工作。
- filter: blur(0);将一个元素的模糊度设置为0,从而使这个元素“消失”在页面中。
15、经常遇到的浏览器兼容性有哪些?如何解决?
- 浏览器默认的margin和padding不同
- IE6双边距bug
- 在ie6,ie7中元素高度超出自己设置高度。原因是IE8以前的浏览器中会给元素设置默认的行高的高度导致的
- min-height在IE6下不起作用
- 透明性IE用filter:Alpha(Opacity=60),而其他主流浏览器用 opacity:0.6
- input边框问题,去掉input边框一般用border:none;就可以,但由于IE6在解析input样式时的BUG(优先级问题),在IE6下无效
16、JavaScript是如何实现面向对象和继承机制?
创建对象方法:
- 利用json创建对象
- 使用JavaScript中的Object类型
- 通过创建函数来生成对象
继承机制:
- 构造函数绑定,使用call或apply方法,将父对象的构造函数绑定在子对象上。
- prototype模式,继承new函数的模式。
- 直接继承函数的prototype属性,对b的一种改进。
- 利用空对象作为中介。
- 在ECMAScript5中定义了一个新方法Object.create(),用于创建一个新方法。
- 拷贝继承,把父对象的所有属性和方法,拷贝进子对象,实现继承。
17、jQuery的特点
- 一款轻量级的js库
- 丰富快速的DOM选择器
- 链式表达式
- 事件、样式、动画等特效支持
- Ajax操作封装,支持跨域
- 跨浏览器兼容
- 插件扩展开发
18、Ajax的优点和缺点
优点:
- 无刷新更新数据
- 异步与服务器通信
- 前端和后端负载平衡
- 基于标准被广泛支持
- 界面与应用分离
缺点:
- AJAX干掉了Back和History功能,即对浏览器机制的破坏
- AJAX的安全问题
- 对搜索引擎支持较弱
- 违背URL和资源定位的初衷
19、介绍一下你对浏览器内核的理解 ?
内核主要分成两部分:渲染引擎(layout engineer 或 Rendering Engine) 和 JS 引擎
渲染引擎:
- 负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入 CSS 等),以及计算网页的显示方式,然后会输出至显示器或打印机
- 浏览器内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同
- 所有网页浏览器、电子邮件客户端以及其它需要编辑、显示网络内容的应用程序都需要内核
JS 引擎:
- 解析和执行 javascript 来实现网页的动态效果
- 最开始渲染引擎和 JS 引擎并没有区分的很明确,后来 JS 引擎越来越独立,内核就倾向于只指渲染引擎
19、计算属性(computed)、方法(methods)和侦听属性(watch)的区别与使用场景
methods VS 计算属性
- 计算属性是基于它们的依赖进行缓存的,而methods如果视图发生变化,则会重新渲染视图开销很大。
- 如果开销大的话可以选择计算属性,如果不希望有缓存的话可以选择methods。
watch VS 计算属性
- 计算属性可以用于复杂的表达式,而数据变化时执行异步或开销较大的操作时可以选择watch。
20、 Vue 双向绑定,为什么不能通过修改下标来通知视图发生变化
- 在vue.js中vue提供了一些数组变异和非变异的方法,如果需要通过下标改变可以通过Vue.set来进行改变
21、简述 Vue 中的 MVVM 模型
- vue本身将Dom和数据进行了绑定,其中一个改变另一个也会随之变化,DOM监听和数据绑定是关键
- Dom中的视图发生变化时,model中的数据也会发生改变,当model中数据变化时,DOM中的视图也会发生改变
22、Vue 路由中 hash 模式和 history 模式区别
- hash包含在url中,但不包含在http请求中,对后端没有影响
- history是通过#后面的地址实现跳转比如go,back
23、 Vue 路由中 route 和router 的区别
- route是路由信息对象,包括push,param,name,query等信息
- router是路由实例,包括了路由的跳转方法和钩子函数
24、路由的原理
通过浏览器中的hash值进行改变,一个hash值对应一个组件