一、px和em和rem的区别
1、px
实际上就是像素,用PX设置字体大小时,比较稳定和精确。
但是px不支持用户进行浏览器缩放或者不同移动端的兼容,因为像素是固定的,屏幕大小是变化的。
2、em
是根据父元素来对应大小,是一种相对值;
em值 = 1/父元素的font-size*需要转换的像素值。
进行任何元素设置,都有可能需要知道他父元素的大小,这很不方便。
3、 rem
是根据根元素html的font-size来对应大小,
1rem = 16px,可以在根元素html中写固定像素也可以写百分比,然后在具体的标签上设置rem。
浏览器的兼容性
除了IE6-IE8r,其它的浏览器都支持em和rem属性,px是所有浏览器都支持。因此为了浏览器的兼容性,可“px”和“rem”一起使用,用"px"来实现IE6-8下的效果,然后使用“rem”来实现代浏览器的效果。
二、了解过flex吗?
答:flex是弹性布局.设为flex布局之后,子元素的float,clear,vertical-align属性将会失效
三、CSS中link 和@import的区别是?
(1)link是html标签,无兼容性问题,@import完全是css提供的一种方式
(2) 页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;
(3) import只在IE5以上才能识别,而link是HTML标签,无兼容问题;
(4) link方式的样式的权重 高于@import的权重.:在link标签引入的 CSS 文件中,使用@import时需注意,如果已经存在相同样式,@import引入的这个样式将被该 CSS 文件本身的样式层叠掉,表现出link标签引入的样式权重大于@import引入的样式这样的直观效果。
四、原型链继承
五、深拷贝,浅拷贝
浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,
深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,
Object.assign() 参数如果不是对象,会先将参数转成对象
基本数据类型:string,null,undefined,Boolean,number名和值存在栈内存
引用数据类型:object array function 名存在栈内存,值存在堆内存
深拷贝方法:
第一,JSON.parse(JSON.stringify())
第二,jquery $.extend(true,[],[1,2,3])
第三,Object.assign() 当拷贝的值是单层情况,简单类型
浅拷贝:
第一:Object.assign({},{a:1,b:2}) 当拷贝是多层时候(引用数
据类型)
第二:for in
第三:$.extend(false,[],[1])
(3)值类型和引用类型的区别
基本数据类型:基本数据类型的值是不可变的(我们不能给基本数据类型添加属性和方法);基本数据类型的比较是值的比较(只有他们的值相等的时候才是相等的);基本数据类型的变量是存放在栈里面的
引用数据类型:引用数据类型可以拥有属性和方法,且值是可变的;同时 存放在堆内存和栈内存引用数据类型的值是同时保存在栈内存和堆内存的对象值类型的名和值都存在栈内存,而引用类型得名存在栈内存,值存在堆内存,
(5)get和post的区别
get和post是HTTP的请求方法
1、get是从服务器获取数据,post是向服务器传递数据
2、get参数传递在url中,post则放在request body中
3、get相对post来说不安全,参数暴露在url,不能传递敏感的信息
4、get请求只能进行url编码(ASCII编码),而post接受多种编码方式
5、get请求参数会被完整保留在浏览历史记录中,而post不会
6、get请求速度快,有大小限制
幂等:不管进行多少次重复操作,都是实现相同的结果
get和put delete都是幂等的
(6)如何处理跨域
跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的
同源策略:"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
同源策略的限制:
1.) Cookie、LocalStorage 和 IndexDB 无法读取
2.) DOM 和 Js对象无法获得
3.) AJAX 请求不能发送
跨域解决方案
1、 通过jsonp跨域
通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。
2、 document.domain + iframe跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 postMessage跨域
6、 跨域资源共享(CORS)
7、 nginx代理跨域
8、 nodejs中间件代理跨域
9、 WebSocket协议跨域
(7)Dom事件流
页面中接受事件的顺序,现行的主流是事件冒泡
事件冒泡和事件捕获
(8)mvvm和mvc的区别
mvc(model(模型)-view(视图)-controller(控制器))
mvc的特点是将业务逻辑,模型数据,用户界面分离开来,m和v必须通过c承上启下。让开发者将数据与表现解耦。
mvvm(model-view-vm)
mvvm在概念上真正的将页面与数据逻辑分离的模式,它把数据绑定工作放在一个js去实现,而这个js的主要功能是完成数据的绑定,即将model绑定到ui上去。核心是提供对view和viewMODel的双向数据绑定,view和model之间没有直接的联系,而是通过viewmodel进行交互,view的变动自动反映在viewmodel上,反之亦然,这样就保证试图和数据的一致性。
总结
mvc和mvvm都是一种设计思想,主要是mvc中的c演变成mvvm中的viewModel。mvvm主要解决了mvc中大量dom操作使得页面渲染性能降低,加载速度变慢,影响用户体验。当model频繁发生改变时,开发者需要主动 更新到view的问题
(9)vue的优点
vue的优点:(1)双向数据绑定
(2)组件化开发
(3)轻量高效:Vue.js通过简洁的API提供高效的数据绑定和灵活的组件系统
(4)动画系统:Vue.js提供了简单却强大的动画系统,当一个元素的可见性变化时,用户不仅可以很简单地定义对应的CSS Transition或Animation效果,还可以利用丰富的JavaScript钩子函数进行更底层的动画处理。
(10)vue的缺点
4.缺点
不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。
(11)vue的核心是组件系统,数据驱动
(12)vue key的作用:
key的作用主要是为了高效的更新虚拟DOM。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。
(13)Computed 和 watch 的区别
1.computed不支持异步操作,watch支持
2.当你需要一个值或者属性时,且它需要一些处理时,写在模板里不直观,可以使用computed简化。
3.当你需要监控某个变量,这个变量改变后需要进行一些操作时,使用watch。
4.computed具有缓存性,页面重新渲染值不变化,计算属性会立即返回之前的计算结果,而不必再次执行函数。
5.watch无缓存性,页面重新渲染时值不变化也会执行
14vue 用了哪些新特性,请举例一下并详谈
一、深度作用选择器( >>> )
二、组件选项 provide/inject:
如果列举Vue组件之间的通信方法,一般都会说通过prop,自定义事件,事件总线,还有Vuex。provide/inject提供了另一种方法。
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。
三、作用域插槽 slot-scope
四、组件配置项inheritAttrs、组件实例属性listeners
15、标准盒子模型和IE盒子模型
都是margin+border+padding+content
标准盒子模型的content不包括padding和border,而IE盒子模型包括。IE5.5及更早的版本使用的是IE盒模型。IE6及其以上的版本在标准兼容模式下使用的是W3C的盒模型标准。W3C的盒模型方式被称为“content-box”,IE的被称为“border-box”,使用box-sizing: border-box;就是为了在设置有padding值和border值的时候不把宽度撑开。处理宽高的计算范围。
16、vue双向绑定原理
vue通过Object.defineProperty()方法属性截取的方式,把data里的每个数据转成getter/setter,当数据变化时通知视图更新。其中参数1为该对象(obj),参数2为要定义或修改的对象的属性名,参数3为属性描述符,属性描述符是一个对象,主要有两种形式:数据描述符和存取描述符。
var keyvalue=1;
var obj={};
Object.defineproperty(obj,"key",{
enumberable:true,
configurable:true,
set:function (newvalue) {
keyvalue=newvalue
console.log("keyvalue的值已经发生了改变,目前的值是:${keyvalue}")
},
get : function () {
return keyvalue
}
})
Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性
实现方式二:function observer (data) {
//判断如果没有传值,或者传的值不是一个对象,就直接return
if(!data || typeof data !== 'object') {
return;
}
Object.keys(data).forEach(item => {
observerProperty (data, item, data[item])
})
}
function observerProperty (target, key, value) {
observer (value)
Object.defineProperty(target, key, {
get () {
return value;
}
set (val) {
value = val
}
}
}
//这样就会对obj进行一个劫持,一旦改变obj内的属性,就返回相对应的数据,比如对obj的name进行了改变,observer()函数可能会返回一句obj的name已经改变为...
//observer (obj)
let obj = {
id:1,
name:zhngsan,
age: 20
}
</script>
vue的数据双向绑定是通过数据劫持和发布-订阅者功能来实现的
实现步骤:1.实现一个监听者Oberver来劫持并监听所有的属性,一旦有属性发生变化就通知订阅者
2.实现一个订阅者watcher来接受属性变化的通知并执行相应的方法,从而更新视图
3.实现一个解析器compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相对应的订阅者
17、作用域
全局作用域:最外层函数定义的变量,任何函数内部都可以调用。
局部作用域:一般只在固定的代码块可以用,而对外函数是无法访问的。
在函数内声明变量一定要用var,不然就是全局变量。函数内部定义了个局部变量,函数在解析的时候会对这个变量提前声明
18、作用域链
从内部函数可以访问到外部函数的机制,用链式查找决定哪些函数可以被查找到
19、js执行环境
每个函数运行都会产生一个执行环境,js为每个执行环境关联一个变量对象,环境中定义的所有变量和函数都存在这里。全局执行环境:window对象。
20、什么是闭包?为什么要使用闭包?闭包的应用场景有哪些?闭包的好处和坏处?
(1)闭包:可以访问其他函数变量的函数是闭包。是定义在一个函数内部的函数。本质上是将函数内部与外部连接起来的桥梁。
(2)因为闭包可以访问函数中的变量,可以使变量长期存储在内存中,生命周期较长。闭包不能滥用,否则会导致内存泄漏,影响网页性能,可以在使用完闭包后,释放资源,将变量指为null。
function f1() {
var name = 'Mozilla';
function f2() {
alert(name);
}
return f2;
}
var myFunc = f1();
myFunc();
f1是f2的父函数,f2被赋给了一个全局变量,
f2始终存在内存中,f2的存在依赖f1,
因此f1也始终存在内存中,不会在调用结束后,被垃圾回收机制回收。
(3)、闭包应用场景:setTimeOut、封装变量、回调、为节点循环绑定click事件
(4)、闭包的坏处:消耗内存,闭包使函数内部的变量不能被内存释放,这些变量就会占用内存,内存消耗大,可能会导致内存泄露。解决这个问题的办法就是在不使用这些变量时,及时把不需要的局部变量全部删除。性能问题,使用闭包时,会涉及到跨作用域访问,每次访问都会导致性能损失。因此在脚本中,最好小心使用闭包,它同时会涉及到内存和速度问题。不过我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响。
(5)闭包的好处:实现封装,防止变量跑到外层作用域中,发生命名冲突。.匿名自执行函数,匿名自执行函数可以减小内存消耗。可以使变量长期存储在内存中,生命周期较长。
(6)内存泄漏例子:
为什么会有闭包?
之所以出现闭包是因为JS的垃圾回收机制,JS 本身为了避免解释器过量消耗内存,造成系统崩溃, 自带有一套垃圾回收机制,垃圾回收机制能够检测到一个对象是不是无用的。检测到之后,就会把它占用的内存释放掉。但是实际工作中,我们也会需要一些变量不那么及时的被清理,所以就出现了闭包,用来达成这个效果。
44、js的闭包原理
其实是对js函数作用域特性的一种利用,因为函数内定义的局部变量不能被外部直接获取,而函数却可以访问到其外部作用域的变量。所以我们可以在函数内部定义一个访问局部变量的方法并将之输出给外部。在函数销毁后,通过函数输出的方法访问局部变量成了唯一途径。
21、undefined和null的区别,void
void 操作符 对任何表达式求值都返回 undefined ,undefined 表示一个变量自然的、最原始的状态值,而 null 则表示一个变量被人为的设置为空对象,而不是原始状态。所以,在实际使用过程中,为了保证变量所代表的语义,不要对一个变量显式的赋值 undefined,当需要释放一个对象时,直接赋值为 null 即可。
typeof null=>Object
23、同步和异步
js是单线程的,同个时间只能处理同个任务,所以出现了异步。同步任务是在主线程排队执行的任务,只有一个任务完成后,才能执行下一个任务,网站渲染过程,元素的渲染其实就是一个同步任务。
异步任务不进入主线程,进入任务队列,只有任务队列通知主线程,某个异步任务可以执行后,某个异步任务可以执行了,任务将会进入主线程,像图片的加载,音乐的加载就是一个异步任务,setTimeout setINterval也是异步,他们可以控制js执行顺序
异步:不等待执行结果就执行接下来的代码,
同步:等待异步代码执行完毕后才执行接下来的代码。
24、html,网页是如何渲染?
答:首先 是解析html,构建dom树,然后解析css,形成css对象模型,然后将css和dom合并,构建渲染树,再进行布局和绘制。(遍历渲染树,在页面上绘制每个节点)
26、如何实现图片动态加载(懒加载)
原理:先将img标签中的src链接设置为空,将真正的图片链接放在自定义属性(data-src),当js监听到图片元素进入到可视窗口的时候,将自定义属性中的地址存储到src中,达到懒加载的效果。
33、this指向问题
1:this永远指向一个对象;
2:this的指向完全取决于函数调用的位置;
1.函数调用模式
当一个函数并非一个对象的属性时,那么它就是被当做函数来调用的。在此种模式下,this被绑定为全局对象,在浏览器环境下就是window对象
function hxy() {
var name="123";
console.log(this.name);//undefined,this指向window
}
hxy()
2.方法调用模式
当函数被保存为一个对象的属性时,它就可称为这个对象的方法。当一个方法被调用时,this被绑定到这个对象上。如果调用表达式包含一个提取属性的动作(. 或 []),那么它被称为方法调用
var o = {
name: "hello",
sayName: function () {
console.log(this.name); //this指向o
},
};
o.sayName();//hello
3.构造函数调用模式
如果在一个函数前面加上new关键字来调用,那么就会创建一个连接到该函数的prototype成员的新对象,同时,this会被绑定到这个新对象上。这种情况下,这个函数就可以成为此对象的构造函数。
36、面向对象的特性
38、.DOM操作如如何新建、删除、获取节点
新建:document.createElement();
删除:document.remove()
获取:document.getElementById()
3.如何实现数组交换元素,例如[1,2,3,4]转换成[1,3,2,4]
使用中间变量
var arr = [1, 5, 42, 3]
var item = arr[1];
arr[1] = arr[2];
arr[2] = item
4.typeof能够判断哪些类型
typeof能判断所有值类型undefined string number Symbol boolean
typeof 可以判断是否是function
typeof 可以判断是否是引用类型,但是不可细分,如果需要判断是否是数组或者对象,需要用到instanceof
如果需要判断是否是数组或者对象,需要用到instanceof
b instanceof Array
typeof a
5、js循环机制是什么eventLoop
先执行主任务,把异步任务放入循环队列中,等待主任务执行完,再执行队列中的异步任务。异步任务先执行微观任务,再执行宏观任务,一直这样循环,反复执行,就是时间循环机制。
微观任务:主要包括Promise.process.nextTick
宏观任务有:setTimeout,setIntervval,script,I/O交互事件
先执行微观再执行宏观