前端面试题
1、call和applay的区别?
call和apply是函数的两个非继承而来的方法。这两个方法是在特定的作用域中调用函数,实际上是等于设置函数体内的this对象的值。可以传入两个参数。第一个参数是运行函数所在的作用域,另一个是传入的参数。
区别是:apply第二个参数掺入的是数组或者argument对象,call第二个参数传入的是一个一个的参数,也就是说传递给函数的参数必须一个一个列举出来
call和apply真正的作用的扩充函数的作用域。
window.color="red"; var o={color:"blue"}; function sayColor(){ alert(this.color); } sarColor.call(this) //red sayColor.call(window) //red sayColor.call(o) //blue
PS:bind
ES5还定义了一个方法:bind()。这个方法会创建一个函数的实例。其this值会绑定到传给bind()函数的值。
window.color="red"; var o={color:"blue"}; function sayColor(){ alert(this.color) }; var objectSayColor=sayColor.bind(o); objectSayColor() //blue
2、什么是闭包?
闭包是指有权访问另一个函数作用域中的函数。创建闭包的方法很常见,就是在一个函数内部创建另外一个函数。
闭包引起的一个问题就是:内存泄漏。
3、什么是盒子模型?有什么区别?
W3C盒子模型和IE盒子模型。
W3C盒子模型包括padding、margin、border、content。其中content的宽度=width;
IE盒子模型与W3C盒子模型的区别就是width=content+border+margin
无论是IE和还是W3C,margin的效果都是一样的。对于行级元素,margin上下无效,左右有效。对于块级相邻元素的情况如下:
(1)都是正数:取最大值。距离=Math.max(margin-bottom,margin-top);
(2)都是负数:取最小值。距离=Math.min(margin-bottom,margin-top);
(3)一个正数、一个负数。取正负相加的值。距离=marin-top+margin-bottom;
4、如何优化性能?
·什么是前端性能优化?
从用户访问资源到资源完整的展现在用户的面前。通过技术手段和优化策略,缩短每个步骤的处理的时间,从而提升资源的访问和呈现速度。
·原因:
在web站点的构建过程当中,很多因素都会影响访问速度,从而用户体验低下导致用户的流失。
·优化的方法:
减少http请求次数,合并js、css
使用CDN,将用户安排在近的服务器上
使用缓存,缓存ajax,使用外部的css和js以便缓存
压缩资源 使用gzip压缩js和css文件
代码层面 避免使用通配符选择器、样式选择器,样式放在顶部,脚本放在底部
5、浏览器的渲染机制是什么?
第一步:浏览器解析html,构建DOM树
第二步:根据css构建渲染树,包括元素的大小、颜色,隐藏的元素不会被构建在该树中
第三步:根据css样式构建布局树,主要确定元素的位置
第四步:根据前面的信息,绘制渲染树
6、快速排序?顺便说说常见的几种排序
冒泡排序、插入排序、归并排序、快速排序
7、继承的方式有哪些?优缺点是什么?
(1)原型链继承
function A(){ } function B(){ }
//继承A的方法 B.prototype=new A(); //以下可以给B的原型添加方法
B.prototype.getName=function(){
return this.name
} var person=new B();
优点:只需要一行代码
在B的原型上添加属性或者方法时,不会影响到A。
缺点:书写顺序问题。给B添加的方法的代码一定要放在替换原型的语法之后
无法实现多继承
无法传参
包含引用类型的原型,导致会被所有的实例共享。
//关于引用类型共享的问题 function A(){ this.colors=["red","blue"]; } function B(){ } B.prototype=new A(); var person1=new B(); person1.colors.push("yellow"); console.log("person1_color",person1.colors); var person2=new B(); console.log("person2_color",person2.colors);
(2)借用构造函数继承(有时也叫伪造经典或者经典继承)
function A(){ } function B(){ A.call(this); } var person=new B();
优点:可以传递参数
可以实现多继承
解决了共享的问题
缺点:创建的实例只是子类的实例
只能继承构造函数的实例和方法。而一般在构造函数中,会写一些属性,原型中会写一些方法。所以只能继承构造函数中的属性
每创建一个东西,都是重新创建一个新的实例,会占用多余的内存,不存在复用
(3)组合继承(伪经典继承)
function A(){ } function B(){ A.call(this); //执行第一次 } B.prototype=New A(); //执行第二次
B.prototype.constructor=B; var person1 =new B();
优点:可以实现多继承
可以传参
缺点:父类的构造函数被调用了两次。如果父类的构造函数较大,比较耗性能,就会影响性能
同名覆盖,在实例中有一份,在原型中有一份,就会占用多余的内存
(4)原生式继承
利用的原理是B.__proto__=A
function (o){ function F(){}; F.prototype=o; return F(); }
(5)寄生式继承 使用与对象
function createOther(o){ var clone=Object(o); clone.sayHi=function(){ //对象增强 alert("sayHi"); } return clone; } //例: var person={ name:"kangxiaoxiao", freiends:["lala","meimie"] } var createOther=createOther(person); createOther.sayHi();
(6)寄生组合式继承
function inheritPrototype(B,A){ var prototype=Object(A.prototype); //创建对象 prototype.constructor=B //对象增强 B.prototype= prototype; //指定对象 } //例: function A(name){ this.name=name; this.colors=["red","blue"] } A.prototype.sayName=function(){ alert(this.name); } function B(name,age){ A.call(this,name); this.age=age } inheritPrototype(B,A); B.prototype.sayAge=function(){ alert(this.age) } var person1=new B("kangxiaoxiao","27");
8、以下方法有什么问题?如何优化?(涉及到内存泄漏)
function assignHandler(){ var doc=document.createElement("div"); doc.onclick=function(){ alert(doc.id) } }
以上的代码创建了一个作为doc元素时间处理程序的闭包,而这个闭包又创建了一个循环引用。由于匿名函数保存了一个对assignHandler()的活动对象的引用,因此就无法减少element的引用数。只要匿名韩式存在,doc的引用数至少就是1,因此它所占用的内存就永远不会被收回。
改进的办法如下:
function assignHandler(){ var doc=document.createElement("div"); var id=doc.id doc.onclick=function(){ alert(id); } doc=null; }
好处:将id赋值给一个变量,减少对doc的循环引用。将element变量设置为null,能够解除对DOM对象的引用,顺利减少其引用次数,确保正常回收占用的内存。
9、vue的生命周期
创建前/后:beforeCreate/created
挂载前/后:beforeMount/mounted
更新前/后:beforeUpdate/updated
卸载前/后: beforeDestory/destoryed
10、vue常见的指令有哪些?
v-if v-module v-show v-on:click
11、返回false的哪些?
null undefind 0 -0 NAN 空字符串
12、请求数据,渲染页面,可以在vue的哪些生命周期中进行?
mounted
13、vue如何封装自定义组件?什么算是好的自定义组件
·注册全局组件
//创建实例 new Vue({ el: '#some-element', // 选项 }) //注册全局组件 Vue.component('my-component', { // 选项 template: '<div>A custom component!</div>' }) //自定义元素 <div id="example"> <my-component></my-component> </div> //局部注册: var Child = { template: '<div>A custom component!</div>' } new Vue({ // ... components: { // <my-component> 将只在父组件模板中可用 'my-component': Child } })
14、vue双向绑定的原理?
vue会遍历data中的所有属性,并使用object.definProperty把这些属性全部转化成getter/setter。而每个组件的实例都有watcher对象,它会在组件渲染过程中记录为依赖。之后当依赖项setter被调用时,会同志wather重新计算,从而致使它关联的组件得到更新。
15、微信小程序如何实现本地存储?
大小限制为10M
//存入 异步 wx.setStorage({ key:"key", data:"value" }) //存入 同步 try { wx.setStorageSync('key', 'value') } catch (e) { } //获取 wx.getStorage({ key: 'key', success: function(res) { console.log(res.data) } }) //获取storage的信息 异步 wx.getStorageInfo({ success: function(res) { console.log(res.keys) console.log(res.currentSize) console.log(res.limitSize) } }) //删除 wx.removeStorage({ key: 'key', success: function(res) { console.log(res.data) } }) //清除storage wx.clearStorage()
16、小程序常用的组件有哪些?常用的API
wx.request({ url: 'test.php', //仅为示例,并非真实的接口地址 data: { x: '' , y: '' }, header: { 'content-type': 'application/json' // 默认值 }, success: function(res) { console.log(res.data) } })
17、小程序与H5有什么不同?
(1)是运行环境的不同
传统的HTML5的运行环境是浏览器,包括webview,而微信小程序的运行环境并非完整的浏览器,是微信开发团队基于浏览器内核完全重构的一个内置解析器,针对小程序专门做了优化,配合自己定义的开发语言标准,提升了小程序的性能。
(2)是开发成本的不同
只在微信中运行,所以不用再去顾虑浏览器兼容性,不用担心生产环境中出现不可预料的奇妙BUG
(3)是获取系统级权限的不同
系统级权限都可以和微信小程序无缝衔接
(4)便是应用在生产环境的运行流畅度
长久以来,当HTML5应用面对复杂的业务逻辑或者丰富的页面交互时,它的体验总是不尽人意,需要不断的对项目优化来提升用户体验。但是由于微信小程序运行环境独立
18、小程序中能不能嵌入H5页面?
可以,个人和海外类型的不支持
<!-- wxml --> <!-- 指向微信公众平台首页的web-view --> <web-view src="https://mp.weixin.qq.com/"></web-view>
19、你对加班怎么看?
各有看法
20、什么是语义化?
根据内容选择合适的标签,便于开发人员阅读和爬虫的SEO及浏览器的解析。
21、在Js中,转换成false的值有?
null、undefined、NAN、0,-0,空字符串
22、this的指向的分类
(1)纯函数的调用,this指向全局作用域(window)
(2)作为对象的方法和属性,指向的是对象
(3)作为构造函数的调用,指向的是构造函数的实例
(4)强制指向一个对象。call/apply指向的传入的第一个参数
23、图片懒加载等原理
将图片的地址给懂data=XXX,当滚至该区域时,用src代替