前端面试题

本文列举了CSS面试中关于创建三角形和元素垂直水平居中的几种方法,以及JavaScript面试中涉及的数组去重、继承策略和闭包概念。同时讨论了堆栈内存、数据类型以及浅拷贝和深拷贝的差异,并介绍了防抖和节流技术在性能优化中的应用。
摘要由CSDN通过智能技术生成

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
    }
  • 未完成…
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值