JavaScript题
1、JavaScript有几种数据类型?
2、深浅克隆
什么是深克隆?什么是浅克隆
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
怎样进行浅克隆?
Object.assign(target,...source):可以把多个源对象自身的可枚举的属性拷贝给目标对象,然后返回的是目标对象const obj = { a: 1 };const copy = Object.assign({}, obj);console.log(copy); // { a: 1 }es6展开运算符也可以实现浅克隆var copyObj = {...a};
怎么自己实现一个浅克隆?
function simpleClone(initalObj) {var obj = {};for ( var i in initalObj) {obj[i] = initalObj[i];}return obj;}
怎样进行深克隆?
1、使用json序列化在反序列化方法,弊端是RegExp和date对象以及undefined会变为其toString后的字符串。
let obj = JSON.parse(JSON.stringify(initalObj));
2、使用递归实现深拷贝
function deepClone(obj) {if (obj === null) return nullif (typeof obj !== "object") return objif (obj instanceof RegExp) return new RegExp(obj)if (obj instanceof Date) return new Date(obj)let newObj = new obj.constructor;for (let key in obj) {if (obj.hasOwnProperty(key)) {newObj[key] = deepClone(obj[key])}}}
3、通过jQuery的extend方法实现深拷贝
var array = [1,2,3,4];var newArray = $.extend(true,[],array);
4、lodash函数库 lodash.cloneDeep()实现深拷贝
3、创建一个对象的时候new操作符都做了什么?
1、创建一个空对象,并且this 变量引用该对象,同时还继承了该函数的原型。
2、属性和方法被加入到this 引用的对象中。
3、新创建的对象由this 所引用,并且最后隐式的返回this 。
4、什么是回调地狱,怎样解决回调地狱?
由于回调函数是异步的,每一层的回调函数都需要依赖上一层的回调执行完,所以形成了层层嵌套的关系最终形成了回调地狱。
使用Promise解决
5、什么是promise?常用的有哪些方法?
Promise 是异步编程的一种解决方案。所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的API,各种异步操作都可以用同样的方法进行处理。
特点:1、自己身上有all、reject、resolve这几个方法
2、原型上有then、catch等方法
3、一旦建立,就无法取消,这是它的缺点
6、http和https的区别是什么?
1、默认端口号不同,前者是80,后者是443
2、后者会更安全。
7、get和post有什么区别?
1、get的所有参数全部在url上,服务器访问日志会记录下来,不安全;post的url中只有资源路径,不含参数,参数在请求体中,服务器不会记录参数,相对安全;
2、get提交的最大数据长度较小,post提交的数据能够提交的数据更大些。
8、跨域的解决方式?
1、jsonp
2、cors
3、开发webpack的sever服务代理 + 线上ngnix代理
优缺点:
jsonp 兼容性好,但是必须是get请求,而且需要后端返回指定格式数据;
cors要求ie10以上才支持。如果允许的是所有的ip都可以跨域访问,则无法携带cookie凭证;
9、常见的http状态码及其意义?
1、200(ok):请求成功
2、301:重定向
3、404:请求的资源在服务端未找到
4、500:服务器错误
10、vue双向数据绑定的原理?
vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
具体步骤:
第一步:需要对observe的数据对象进行递归遍历,包括子属性对象的属性,都加上setter和getter,这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化。
第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。
第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:1、在自身实例化时往属性订阅器(dep)里面添加自己2、自身必须有一个update()方法3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
第四步:MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化-> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。
11、请详细说下你对vue生命周期的理解?
总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。创建前/后:
1、在beforeCreated阶段,vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。
2、在created阶段,vue实例的数据对象data有了,$el还没有。
3、载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。
4、在mounted阶段,vue实例挂载完成,data.message成功渲染。
5、更新前/后:当data变化时,会触发beforeUpdate和updated方法。
6、销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在
