1.说说浏览器的渐进增强和优雅降级的区别?
渐进增强可以理解为向上兼容,一开始针对较为低版本的浏览器来构建页面,保证页面的所有基本的功能点都能实现;然后根据更高版本的浏览器设计一些在用户体验上更为良好的交互界面、追加更多的功能。
优雅降级可以理解为向下兼容,一开始就对高版本的浏览器构建功能、性能、体验都较为完美页面,然后针对低版本的浏览器进行兼容补充。
两者的区别在于:渐进增强属于从基础的页面中增加更多的功能(加);优雅降级是属于从功能丰富的页面上慢慢地减少页面的功能、用户的体验等等。
2. 网站性能优化的方案都有哪些?
-
尽量减少HTTP请求次数
-
延迟加载内容
-
使用离线缓存
-
CSS、JS放置正确位置
-
静态资源压缩
-
静态资源使用多个域名
-
静态资源使用cdn存储
-
预加载
-
DOM操作优化
-
优化算法
3.Link和@import之间有什么区别?
本质的差别:link 属于 XHTML 标签,而 @import 完全是 CSS 提供的一种方式。
加载顺序的差别: 当一个页面被加载的时候(就是被浏览者浏览的时候) ,link 引用的 CSS 会同时被加载,而 @import 引用的 CSS 会等到页面全部被下载完再被加载。所以有时候浏览 @import 加载 CSS 的页面时开始会没有样式(就是闪烁),网速慢的时候还挺明显。
兼容性的差别: @import 是 CSS2.1 提出的,所以老的浏览器不支持,@import 只有在 IE5 以上的才能识别,而 link 标签无此问
使用 dom控制样式时的差别:当使用 javascript 控制 dom 去改变样式的时候,只能使用 link 标签,因为@import 不是 dom 可以控制的。
4. null,undefined 的区别
他们的数据类型不一样:null的数据类型为object、而undefined为undefined
他们相等于但是不恒等于,null定义的数据表示数据为空
总结来说,undefined 表示的是变量未定义或未初始化,而 null 表示变量的值为空。 需要注意的是,在条件判断时,null==undefined 返回 true,但它们的数据类型不同,所以 null === undefined 返回 false。
5.说说css中元素脱离文档流的方式有哪些?定位的方式有哪些以及区别?
脱离文档流: 1、如果元素不再满足浏览器的默认布局排版,也就是说将元素从默认的布局排版中拿走,此时这个元素不再占有它在标准流中的位置。那么这时这个元素就脱离了文档标准流,此时就是脱离文档流了。 2、元素脱离文档流之后,将不再在文档流中占据空间,而是处于浮动状态(可以理解为漂浮在文档流的上方)。 3、脱离文档流的元素的定位基于正常的文档流,当一个元素脱离文档流后,依然在文档流中的其他元素将忽略该元素并填补其原先的空间。
使用定位:position。
Position可以使我们定义的元素不存在与当前的文档对象中。
其中relative值,表示当前是相对定位的盒子会有绝对定位的盒子来把当前盒子作为定位的参照,不会改变当前盒子的文档流。
Absolute值,表示开启绝对定位,绝对定位就已经脱离了文档流了,可以根据距离自己最近的盒子来进行定位。
Fixed值,表示固定定位,他相对与的父级盒子不是别的就是我们的浏览器窗口,也是脱离了文档流的,我们常常用它做一些悬浮按钮等功能
6.伪类和伪元素的区别有哪些? Css3新增了哪些选择器
-
伪类本质上是为了弥补常规CSS选择器的不足,以便获取到更多信息;
-
伪元素本质上是创建了一个有内容的虚拟容器;
-
CSS3中伪类和伪元素的语法不同;
-
可以同时使用多个伪类,而只能同时使用一个伪元素;
属性选择器(权重10)-结构伪类选择器(权重10)-结构伪类选择器(权重1)
7. 说说Promise和async/await的区别是?
Promise是原生的解决异步代码的对象,promise中有三个状态分别是pedding等待中、rejected失败、resolve成功,根据三个状态可以拿到我们的异步任务执行的结果,其中通过链式的.then回调方法中操作。
Async/await是基于promise封装的解决异步编程带来的回调地狱的终极方案,当我们呢在有很多的异步任务相互嵌套执行时就会出现,无限的层级嵌套,代码相当不清晰,async和await的出翔解决了这个问题。
8.Javascript如何实现继承
1.原型链继承
让一个构造函数的原型是另一个类型的实例,那么这个构造函数new出来的实例就具有该实例的属性。
当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
优点:写法方便简洁,容易理解。
缺点:对象实例共享所有继承的属性和方法。传教子类型实例的时候,不能传递参数,因为这个对象是一次性创建的(没办法定制化)。
2.借用构造函数继承
在子类型构造函数的内部调用父类型构造函数;使用 apply() 或 call() 方法将父对象的构造函数绑定在子对象上。
优点:解决了原型链实现继承的不能传参的问题和父类的原型共享的问题。
缺点:借用构造函数的缺点是方法都在构造函数中定义,因此无法实现函数复用。在父类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。
3.组合继承(经典继承)
将 原型链
和 借用构造函数
的组合到一块。使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有自己的属性
优点: 解决了原型链继承和借用构造函数继承造成的影响。
缺点: 无论在什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部
4.原型式继承
方法一:
借用构造函数在一个函数A内部创建一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的一个新实例。
方法二:
Object.create() Object.create() 是把现有对象的属性,挂到新建对象的原型上,新建对象为空对象
ECMAScript 5通过增加Object.create()方法将原型式继承的概念规范化了。这个方法接收两个参数:作为新对象原型的对象,以及给新对象定义额外属性的对象(第二个可选)。在只有一个参数时,Object.create()与这里的函数A方法效果相同。
优点:不需要单独创建构造函数。
缺点:属性中包含的引用值始终会在相关对象间共享,子类实例不能向父类传参
5.寄生式继承
寄生式继承的思路与(寄生) 原型式继承
和 [工厂模式]
似, 即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象。
优点:写法简单,不需要单独创建构造函数。
缺点:通过寄生式继承给对象添加函数会导致函数难以重用。使用寄生式继承来为对象添加函数, 会由于不能做到函数复用而降低效率;这一点与构造函数模式类似.
6.寄生组合式继承
前面讲过,组合继承是常用的经典继承模式,不过,组合继承最大的问题就是无论什么情况下,都会调用两次父类构造函数;一次是在创建子类型的时候,一次是在子类型的构造函数内部。寄生组合继承就是为了降低父类构造函数的开销而实现的。
优点:高效率只调用一次父构造函数,并且因此避免了在子原型上面创建不必要,多余的属性。与此同时,原型链还能保持不变;
缺点:代码复杂
7.ES6、Class实现继承
原理ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。 ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this
优点:语法简单易懂,操作更方便。
缺点:并不是所有的浏览器都支持class关键字 lass Per
9.说说什么是严格模式,限制都有哪些
严格模式:当我们在开发项目时,难免会有写的不规范的js代码,当我们开启严格模式后就会提示我们当前的代码有需要改进的地方,比如定义了一个未使用的变量。
定义未使用的变量或方法、严格使用双引号、等等
严格模式的限制:
-
变量必须声明后再使用
-
函数的参数不能有同名属性,否则报错
-
不能使用with语句
-
不能对只读属性赋值,否则报错
-
不能使用前缀 0 表示八进制数,否则报错
-
不能删除不可删除的属性,否则报错
-
不能删除变量delete prop,会报错,只能删除属性delete global[prop]
-
eval不会在它的外层作用域引入变量
-
eval和arguments不能被重新赋值
-
arguments不会自动反映函数参数的变化
-
不能使用arguments.callee
-
不能使用arguments.caller
-
禁止this指向全局对象
-
不能使用fn.caller和fn.arguments获取函数调用的堆栈
-
增加了保留字(比如protected、static和interface)
10.从A页面跳转到B页面,缓存A组件,从A组件跳转到C组件,取消缓存,如何实现?
在vue中我们可以使用keep-alive组件来实现组件缓存,当我们在路由表中定义了是否缓存的标识,就可以实现想要缓存的组件了。
为了实现针对性的缓存,我们需要使用到组件自带的includes属性,则个属性标识的是在这个数组中的组件讲会被缓存,有了这个属性我们再配合vuex和路由守卫,vuex来存储需要缓存的组件的名称,而路由守卫用于判断是具体从哪个页面进来的是否进行缓存等。