前端2020年面试题(6)

五十一.JS内存回收机制

		Javascript语言有自己的一套内存回收机制,一般情况下局部变量和对象使用完就会被系统自动回收,无需我们理会。但是碰到闭包的情况这些变量和对象是不会被回收的,对于普通的web站点,页面刷新或跳转这些内存也会被回收。如果是单页web站点,页面切换及数据请求都是通过ajax无刷新机制实现的,页面资源无法自动回收,时间长了会严重影响性能,造成内存泄漏甚至页面崩溃直接退出,这时候手动释放不用资源就非常必要了,包含删除dom、释放对象等
想手动释放含有闭包的对象时,必须先将引用对象属性的事件删除,然后设置为null方可消耗对象。这种事件一般是可以多次执行的,如原生事件的监听,定时器。一般比较有名较完善的插件都有带销毁资源方法,如iscroll插件,里面就有一个destroy原型方法,它里面也就是移除事件监听和删除定时器。

什么是闭包?

五十二.promise是什么?能解决什么问题?

Promise 对象用于表示一个异步操作的最终完成 (或失败), 及其结果值.

这种链式写法的好处在于,先统一执行AJAX逻辑,不关心如何处理结果,然后,根据结果是成功还是失败,在将来的某个时候调用success函数或fail函数。古人云:“君子一诺千金”,这种“承诺将来会执行”的对象在JavaScript中称为Promise对象。

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('foo');
  }, 300);
});

promise1.then((value) => {
  console.log(value);  // expected output: "foo"
});

console.log(promise1);// expected output: [object Promise]

Promise对象可以串联起来,简化为:

new Promise(test).then(function (result) {
    console.log('成功:' + result);
}).catch(function (reason) {
    console.log('失败:' + reason);
});

Promise的好处:

在异步执行的流程中,把执行代码和处理结果的代码清晰地分离了。
根据结果是成功还是失败,在将来的某个时候调用success函数或fail函数。	
Promise还可以做更多的事情,比如,有若干个异步任务,需要先做任务1,如果成功后再做任务2,任何任务失败则不再继续并执行错误处理函数。要串行执行这样的异步任务,不用Promise需要写一层一层的嵌套代码。

五十三.float和absolute有什么区别?

共同点:对内联元素设置float和absolute属性,可以让元素脱离文档流,并且可以设置其宽高。
不同点:float仍会占据位置,absolute会覆盖文档流中的其他元素。

在这里插入图片描述

54.cookie和session有什么联系?

1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、可以考虑将登陆信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中。

会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。

	Cookie通过在客户端记录信息确定用户身份,
	Session通过在服务器端记录信息确定用户身份。

Cookie:
会话Cookie和持久Cookie

会话cookie:(不设置过期时间形成的),则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不存储在保存在**内存**里,当然这种行为并不是规范规定的。

持久Cookie:(设置了过期时间形成的),浏览器就会把cookie保存到**硬盘**上,关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在浏览器的不同进程间共享。

Cookie具有不可跨域名性(就是说,浏览器访问百度不会带上谷歌的cookie)。
55.vue如何实现双向据绑定?
实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer,用来监听所有属性。

3个步骤实现数据的双向绑定:

1.实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。
2.实现一个订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。
3.实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。

更多

五十六.vue父组件子组件通信?

五十七.图片预加载和懒加载?

懒加载:在需要显示图片的时候才去加载图片。

预加载:在还没显示的时候就加载图片。

懒加载原理:

比如我们首屏有二十张图片,但是打开页面的时候只需要显示轮播图和第一张图片,
那么另外的图片是不是可以在需要显示的轮播图和显示的第一张图片加载完成后慢慢去加载。

懒加载方法

1、使用定时器或者计时器。在打开页面需要显示的图片我们优先加载,然后写一个定时器或者计时器去请求之后需要用到的图片。	
2、条件加载。一些图片是某些条件触发才显示的,也可以在显示页面的时候先不加 载,直到需要显示的时候去加载图片。
3、可视区域加载。说白了就是监听滚动条,滚动条滚动到一定位置的时候就去加载马上要显示的图片,要稍微提前一点去加载。

预加载原理:

虽然页面还不需要显示图片,但是我们已经把这些图片加载下来了,
只是不显示这些图片,我们都知道浏览器是会缓存请求过的图片。

预加载方法:

1、使用css背景图片。我们写一些样式,然后把图片的地址放到背景图片里面,让图片隐藏,也可以设置背景图片位置偏移出这个页面。浏览器解析到这些样式的时候就会去加载这些图片,然后等你需要显示的时候浏览器会从缓存里面取,就不需要再去请求。但是这个会造成解析过程中增加了解析时间。	
2、使用JavaScript配合css背景图片。原理就是在DOM和CSS都加载完了,就是在ready方法里面给这些样式添加背景图片,这样就不会造成解析时间边长的问题。
3、用JavaScript创建图片。创建一个对象,就是new Image(),然后给这个对象赋值src,也可以使用数组去实现需要加载很多图片的时候。
4、使用Ajax。就是发起一个get请求,地址是这张图片,因为请求后浏览器会缓存,这张图片就预加载到了本地。

适用情况:

比如需要几十张图片显示,但是有优先顺序,就使用懒加载,
如果是只有几张小图,页面渲染速度也够快,想要交互的时候响应快速,使用预加载。

拓展:图片加载的时机。

1、设置了display: none的img标签和元素背景图片,不会渲染但是会加载。
2、父元素div设置了display: none,那么这个父元素里面的子元素img标签会加 载,父元素里面子元素背景图片不会加载
3、重复或者加载过的图片只会加载一次
4、不存在元素的背景图片不会加载
5、伪类,比如hover,在触发后才会加载

58.MVVM和MVC区别?
1,MVC (Model-View-Controller)

M - Model :数据保存
V - View : 用户界面
C - Controller : 业务逻辑
MVC ,用户操作> View (负责接受用户的输入操作)>Controller(业务逻辑处理)>Model(数据持久化)>View(将结果通过View反馈给用户)

2,MVVM

M -Model
V - 
VM - 

MVVM是将“数据模型数据双向绑定”的思想作为核心,因此在View和Model之间没有联系,
通过ViewModel进行交互,而且Model和ViewModel之间的交互是双喜那个的,
因此试图的数据的变化会同事修改数据源,而数据源数据的变化也会立即反应到View上。

五十九.vue删除数据监测不到?

原因在Object.defineproperty()方法在操作数据和对象不会触发set方法所以视图不会更新
受现代 JavaScript 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属性的添加或删除。

解决方法:
1.this.$set(obj,‘b’,2)=》针对于对象
2.生成一个新的数组在使用数组的变异方法如push,splice,等,因为数组的变异方法,也不会触发set所以会出现视图不更新
60.编程:连接两个数组并返回?

1、concat

js的Array对象提供了一个叫concat()方法,连接两个或更多的数组,并返回结果。

var c = a.concat(b);//c=[1,2,3,4,5,6]

进行多次的数组合并时,会造成很大的内存浪费

2、for循环

大概的思路是:遍历其中一个数组,把该数组中的所有元素依次添加到另外一个数组中。直接上代码:

for(var i in b){
    a.push(b[i]);
}

这样的写法可以解决第一种方案中对内存的浪费,但是会有另一个问题:丑!

3、apply

函数的apply方法有一个特性,那就是func.apply(obj,argv),argv是一个数组。所以我们可以利用这点,直接上代码:

a.push.apply(a,b);

调用a.push这个函数实例的apply方法,同时把,b当作参数传入,这样a.push这个方法就会遍历b数组的所有元素,达到合并的效果。

这里可能有点绕,我们可以把b看成[4,5,6],变成这样:

a.push.apply(a,[4,5,6]);

然后上面的操作就等同于:

a.push(4,5,6);
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页