css面试题
一.css三角形(这里举例4种,其余以此推理)
.up{
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
.left{
width: 0;
height: 0;
border-top: 50px solid transparent;
border-right: 100px solid red;
border-bottom: 50px solid transparent;
}
.topLeft{
width: 0;
height: 0;
border-top: 100px solid red;
border-right: 100px solid transparent;
}
.bottomleft {
width: 0;
height: 0;
border-bottom: 100px solid red;
border-right: 100px solid transparent;
}
二.垂直水平居中方法
1.第一种:
.parent{
width: 500px;
height: 500px;
background-color:#ccc;
display: flex;
justify-content: center;
align-items: center;
}
.son{
width: 200px;
height: 200px;
background-color:red;
}
2.第二种
.parent{
background-color: #ccc;
position: relative;
width: 500px;
height: 500px;
}
.son{
width: 200px;
height: 200px;
background-color: red;
position: absolute;
top: 0;left: 0;right: 0;bottom: 0;
margin: auto;
}
3.第三种
.parent{
background-color: #ccc;
position: relative;
width: 500px;
height: 500px;
}
.son{
width: 200px;
height: 200px;
background-color: red;
position: absolute;
top: 50%;left: 50%;
transform: translate(-50%,-50%);
}
4.第四种
.parent{
position: relative;
display: table-cell;
text-align: center;
vertical-align: middle;
width: 500px;
height: 500px;
background-color: #ccc;
}
.son{
width: 200px;
height: 200px;
background-color: red;
display: inline-block;
}
js面试题
一.js去重的方法
1.第一种
let arr = [1,2,3,4,1,2,3,8,8]
let newArr = [];
for(let i in arr){
if(newArr.indexOf(arr[i]) == -1){ //如果找到该字符,则为 value 的索引位置;否则如果未找到,则为 -1。
newArr.push(arr[i])
}
}
console.log(newArr) //[1, 2, 3, 4, 8]
2.第二种
let arr = [1,2,3,4,1,2,3,8,8]
let newArr = arr.filter((item,index,array)=>{ //item(必须):当前元素的值 index(可选):当前元素的索引值 array(可选):当前元素属于的数组对象
return array.indexOf(item) === index // 如果找到该字符,则为 value 的索引位置;否则如果未找到,则为 -1。
})
console.log(newArr) //[1, 2, 3, 4, 8]
3.第三种
let arr = [1,2,3,4,1,2,3,8,8]
let newArr = [...new Set(arr)]
console.log(newArr) //[1, 2, 3, 4, 8]
4.第四种
let arr = [1,2,3,4,1,2,3,8,8]
for(let i=0;i<arr.length;i++){
for(let j= i+1;j<arr.length;j++){
if(arr[i] == arr[j]){
arr.splice(j,1) // j:下标 1:删除的个数
j--
}
}
}
console.log(arr) //[1, 2, 3, 4, 8]
二.js继承的方法
1.原型链继承:通过修改子类的原型为父类的实例,实现子类可以访问到父类的构造函数以及原型上的属性和方法
缺点:其中一个子类实例改变,会导致另一个实例改变
function Parent(){
this.arr = [1,2,3]
}
function Child(){}
Child.prototype = new Parent()
let val = new Child()
let val2 = new Child()
val2.arr.push(4)
console.log(val.arr) // [1, 2, 3, 4]
2.构造函数继承:通过修改父类构造函数的this来实现继承,在子类构造函数中执行父类的构造函数,同时把父类的构造函数修改为子类的构造函数(用new关键字调用的函数称之为构造函数,不使用new操作符调用就是普通函数)
缺点:所有方法都定义在构造函数中,每次都需要重新创建
function Parent(){
this.name = ['parent']
}
function Child(){
Parent.call(this)
}
var val = new Child()
val.name.push('child')
console.log(val) //['parent','child']
var val2 = new Child()
console.log(val2) //['parent']
3.组合继承 :通过调用父类的构造函数,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
缺点:父类的构造函数被调用了两次,子类实例以及子类原型上都会存在name
function Parent(){
this.name = ['parent']
}
function Child(){
Parent.call(this)
}
Child.prototype = new Parent()
Child.prototype.constructor = Child; //组合继承也是需要修复构造函数指向的
var val = new Child()
console.log(val.name) //['parent']
4.es6-class继承 :在子类的构造方法中调用父类的构造方法
class Parent{
constructor(name){
this.name = name
}
Handle(){
console.log(this.name) //xx
}
}
class Child extends Parent{
constructor(name){
super(name)
}
}
let val = new Child('xx')
val.Handle()
三.获取地址参数
let url = "http://www.baidu.com?name=张三&age=25&sex=男&wife=小红"
function getUrl(url){
var urlStr = url.split("?")[1]
var newStr = urlStr.split("&")
var obj = {}
for(var i in newStr){
let arr = newStr[i].split("=")
obj[arr[0]] = arr[1]
}
return obj
}
console.log(getUrl(url));
四.什么是闭包
闭包是指一个函数内部包含一个函数,内部函数引用可以外部函数的变量,当外部函数执行后,正常情况外部函数的整个作用域就会被销毁,但是内部函数的作用域还在使用,所以不会对其进行回收,就形成了闭包;这和内部函数在外部函数作用域内还是作用域外执行无关
1 闭包的作用(优点)
(1)函数嵌套函数。
(2)参数和变量不会被垃圾回收机制回收
(3)避免全局变量的污染
(4)封装对象的私有属性和私有方法。(然后在全局作用域中通过调用闭包就能访问函数中的变量)
2 闭包的缺点(坏处)
由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,过度使用闭包可能会导致内存占用过多的问题。
所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
五.普通函数和箭头函数的区别
1.箭头函数是匿名函数,不能作为构造函数,不能使用new
2.箭头函数的this,始终指向父级的上下文,普通函数this指向被调用的对象
3.箭头函数不能通过call() apply() bind()方法直接修改他的this指向(会默认忽略第一个参数,可以正常传参)
六.什么是堆和栈
堆:先进先出,动态分配大小不一的内存空间,不会自动释放,存取速度慢但是使用灵活
栈:先进后出,自动分配相对固定大小的内存空间,系统自动释放,存取速度快但是使用不灵活
引用数据类型是存在堆内存中的(引用地址存放在栈内存中),基本数据类型是存在栈内存中的
七.基本数据类型和引用数据类型
基本数据类型:
es5有5种基本数据类型:Number、String、Boolean、Undefined、Null
es6新增了1种基本数据类型:Symbol (表示独一无二的值,不与其他值相等)
谷歌67版本出现了一种:bigInt 指的是安全存储、操作大整数(很多人不把这个作为类型)
引用数据类型
object:里面包含Function、Array、Data等
八.浅拷贝和深拷贝
是否和原数据指向同一对象 | 第一层数据为基本数据类型 | 原数据中包含子对象 | 方法 |
---|---|---|---|
直接赋值 是 | 改变会使原数据一同改变 | 改变会使原数据一同改变 | |
浅拷贝 否 | 改变不会使原数据一同改变 | 改变会使原数据一同改变 | Object.assign({},xx) – {…xx} – 通过数组的 slice 和 concat 方法 |
深拷贝 否 | 改变不会使原数据一同改变 | 改变不会使原数据一同改变 | JSON.parse(JSON.stringify(xx)) – 手写deepClone方法 |
slice:arr.slice(start-必填{ -1指最后一个元素},end可选{不填默认到数组最后})
concat:arr.concat()用于连接两个或多个数组
1.function deepClone(obj){
if(obj == null){
return null
}
if(obj instanceof RegExp){
return new RegExp(obj)
}
if(obj instanceof Date){
return new Date(obj)
}
var objClone = Array.isArray(obj) ? [] : {}
for(let key in obj){
if(obj.hasOwnProperty(key)){
//如果还是对象,就递归
if(obj[key] && typeof obj[key] === "object"){
objClone[key] = deepClone(obj[key])
}else{
objClone[key] = obj[key]
}
}
}
return objClone
}
2.function deepClone(obj){
if(obj instanceof RegExp){
return new RegExp(obj)
}else if(obj instanceof Date){
return new Date(obj)
}else if(obj instanceof Function){
return obj
}else if(obj instanceof Array){
return obj.map(item => deepclone(item))
}else if(obj instanceof Object){
let newObj = {}
for(let i in obj){
newObj[i] = deepclone(obj[i])
}
return newObj
}else{
return obj
}
}
九.防抖和节流
相同点:
都是防止函数多次被调用
不同点:
防抖:减少频率次数, 重复调用时,只有最后的一次会执行
let inp = document.querySelector("input")
inp.oninput = debounce(function(){
console.log(this.value)
},500)
/*利用闭包封装防抖函数*/
function debounce(fn,delay){
let t = null
return function(){
if(t !== null){
clearTimeout(t) //如果有东西执行了,先清除定时器,
}
t = setTimeout(()=>{
fn.call(this) //改变this指向input
},delay)
}
}
节流:减少频率次数,重复操作时,间隔一定的的时间才调用,控制执行的次数
let flag = true //定义开关初始值为true
window.onscroll = function(){
if(flag){
setTimeout(()=>{
console.log('111')
flag = true
},1000)
}
flag = false
}
- 未完成…