js相关面试题
1.js原型链与继承
原型:prototype,函数特有。
原型链:_proto _=> [[prototype]](谷歌浏览器改版显示),对象数组都有。
实例属性查找原则:先从当前实例属性去寻找,如果有就返回,否则顺着原型链一层一层往上找;直到找到null,如果没找到就报错。
hasOwnProperty()
判断是否是私有属性,调用方式:
Person.hasOwnProperty('age')
2.防抖与节流
防抖:固定时间内,事件处理函数只执行一次。应用场景:页面resize事件。
节流:一定时间内多个事件合为一个。应用场景:提交表单、高频监听事件。
相同点:都是为了防止统一内多次执行事件,消耗浏览器性能。
不同点:防抖是在同一时间段执行多次,那么就清楚前面的事件,执行性最后一次;
节流是在同一时间段,如果事件没有超过指定的时间间隔那么就不去执行下一次。
https://segmentfault.com/a/1190000018428170
3.闭包
函数里返回另一个函数。
闭包存在的意义:延长变量的生命周期;创建私有环境。
应用场景:计数器、vue中data
vue中data为什么使用函数:每一个组件都有自己的私有作用域,确保各组件数据不会相互干扰。
4.深拷贝与浅拷贝
深拷贝:基本数据类型(string、number、Boolean、null、undefined、symbol)
浅拷贝:引用类型(object、array、function)
引用类型拷贝的是内存地址,值是存在堆内存中。
深拷贝方法:
(1)
JSON.stringify() JSON.parse()
适用于80%场景,如果有function则不行。
(2)深层递归
function deepClone(source) {
const target = source.constructor === Array ? [] : {}
for (let keys in source) {
if(source.hasOwnProperty(keys)) {
if (source[keys] && typeof source[keys] === 'object') {
// 数组、对象、方法需要递归
target[keys] = source[keys].constructor === Array ? [] : {} // 维护层代码,方便理解,可以不写
target[keys] = deepClone(source[keys])
} else {
// 基本数据类型直接赋值
target[keys] = source[keys]
}
}
}
return target
}
(3)解构赋值
只适用于一维数组和对象拷贝,多维就是浅拷贝。
判断是否是数组
Array.isArray(arr)
arr.constructor === Array
instanceof用法
直接量不能使用instanceof的。instanceof的用途是判断一个对象是否在某个对象原型链上。或者说判断一个对象是某个对象的实例。
var a = 1;
a instanceof Number;
//false
var b = "123";
b instanceof String;
//false
var a = Number(1);
a instanceof Number;
//true
var b = String("123");
b instanceof String;
//true
es相关面试题
var、let、const
var:声明提升、变量覆盖、没有块级作用域。
const:声明之后必须赋值,否则报错;定义的值不能修改,否则报错;块级作用域,一般使用大写字母定义。
let:变量未声明之前不能使用会报错,变量不能重复定义。
Promise
异步解决方案
出现原因:回调地狱:业务逻辑复杂,回调增多,代码可维护性降低。
状态:pending(待定的)、fulfilled(已解决)、rejected(已拒绝)
手写promise:基本结构、then方法、支持异步、链式调用、
vue相关面试题
v-model数据双向绑定原理
<input placeholder="请输入名字" id="username"/>
<p id="uName"></p>
let obj = {}
Object.defineProperty(obj, 'username', {
set: function(val) {
document.getElementById("uName").innerHTML = val
},
get: function() {
return ''
}
})
document.getElementById("username").addEventListener('input', function() {
obj.username = event.target.value
})
https://segmentfault.com/a/1190000006599500
v-if和v-show区别
v-if:是否渲染dom,用于单次判断。
v-show:是否隐藏dom,相当于style中display:none。可用于多次切换,不能用于权限操作。
虚拟dom详解
(1)虚拟dom是什么?
vue2.x才有虚拟dom,本质是js对象=>跨平台。
(2)虚拟dom在vue中做了什么?
a.将真实dom转换成虚拟dom(js对象)
b.数据更新的时候做对比
(3)虚拟dom是如何提升vue的渲染效率的?
a.局部更新节点数据
b.将直接操作dom的地方拿到两个js对象中去做比较
diff算法的patch方法
1.初始化的时候将真实dom转换成虚拟dom
2.数据更新时,将真实dom和虚拟dom进行深层次递归进行对比
vue响应式原理
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 ES5特性Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
注意:由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。
对于对象:
Vue 无法检测 property 的添加或移除。
解决方案:Vue.set(object, propertyName, value)
对于数组:
Vue 不能检测以下数组的变动:
1.当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue。
解决方案:
Vue.set(vm.items, indexOfItem, newValue)
vm.items.splice(indexOfItem, 1, newValue)
2.当你修改数组的长度时,例如:vm.items.length = newLength。
解决方案:
vm.items.splice(newLength)
// 代码示例
this.$set(this.arr, 1, 100)
this.$set(this.arr, 1, 100)
Vue.$set(this.obj, 'city', '南京')
Vue.set(this.obj, 'city', '南京')
//为已有对象赋值多个新 property
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
css相关面试题
css居中对齐
body{ display: flex };
div{ margin: auto };
padding和margin有什么不同
作用对象不同,padding作用于自身,margin作用于外部对象
vw与百分比有什么区别
vw只和屏幕分辨率有关系,百分比有继承关系
行内与块级元素
行内:内容元素宽度
块级元素:独占一行、有继承关系
如何让谷歌浏览器支持小字体
transform: scale(0.8);
bfc
mvvm、mvc
设计模式
构造函数、class、继承
原型、原型链
回流
html、css、js加载顺序
菜单权限
4.快捷键:
创建html:! + tab
创建vue:sc + tab