前端面试题总结

1 html的标签元素可以分为哪几种?具体说明哪几个种类 举例说明

html的标签元素可以分为3类:

块状元素(块元素)

        举例: <div> <h1> - <h6> <ul> <ol> <li> <p>

行内元素(内联元素)

举例: <span> <em> <i> <strong>

行内块状元素(可变元素)

<img> <input>

2 假如现在需要把一个div水平垂直居中,你有多少种方法?

        确定宽高

             1 绝对定位和负margin(宽高的一半)

             2 绝对定位 + left/right/bottom/top + margin(知道父和子容器的宽高的时候可以这么用)

        不定宽高

                1 绝对定位和tranfrom(宽高的一半)

                 2 flex 布局 justify-content:center 和 align-items: center;

                 3 grid布局 搭配margin使用(父元素设置displaay:grid,子元素设置margin:auto)

                 4 table-cell + vertical-align + inline-block/margin: auto (父元素设置display: table-cell;   text-align: center;  vertical-align: middle; 子元素设置 display:inline-black; || margin: auto)

3 tranfrom 那个translate为什么是-50%

        因为定位默认是左上角定位  假设屏幕中间有一个十字,那么定位之后 他就在第四象限,而我们需要这个div的中间在中间,所以我们需要再往左,往上偏移自身的一半

4 简单介绍一下flex布局

        布局的传统解决方案,基于盒子模型,依赖display属性+position属性+float属性,他对于特殊布局不方便,为此,2009年  w3c引入了一种新的布局方式——flex布局,他可以简单,完整,响应式的实现各种页面布局。目前是所有的浏览器都支持。采用flex布局之后,其所有的子元素都成为容器成员,成为felx项目。然后,它的属性有:

  • flex-direction             决定主轴的方向 flex默认分为主轴和侧轴,设置flex布局之后默认按                                          row排列
  • flex-wrap                     默认是在一条线上排列 如果一条线上排列不下的时候,他决定是否换                                       行,默 认有warp
  • flex-flow                      flex-direction和 flex-wrap的简写,默认是row nowarp
  • justify-content             justify-content属性定义了项目在主轴上的对齐方式。
  • align-items                  align-items属性定义项目在交叉轴上如何对齐。
  • align-content               align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴                                     线,该属性不起作用。

5 刚才有聊到定位 简单介绍一下定位 它的属性 简单说一下

        定位他有五个值  

position:static;

        代表默认值,没有定位,也可以用来取消之前设置的定位值。

position:absolute;   

       绝对定位,它的参照物是包含块,也就是离自己最近的有定位属性的祖先级元素。如果祖先元素都没有定位属性,则默认按照浏览器的窗口(body)来定位。我们可以通过给祖先元素设置position:relative/absolute/fixed来让祖先元素变成包含块,通常情况下,我们会用position:relative来设置祖先元素为包含块,因为它不会脱离文档流,不会对布局造成影响。通过left、top、right、bottom来给绝对定位的元素设置偏移值。绝对定位是脱离文档流的,它原来所占位置不会保留   

position:fixed; 

        固定定位,fixed参照物是浏览器的整个窗口。也会使元素脱离文档流。也是通过设置left、top、right、bottom来确定位置。

position:relative;

   相对定位,它的参照物是自己本身,可以通过left、top、right、bottom 设置偏移值。它并没有脱离文档流,所以原来所占的位置依然会保留。相对定位并不会影响其他元素的布局。

position:sticky

        黏性定位。设置该属性后,只有当滑动到这个位置时,才会生效。生效后效果相当于固定定位fixed。也是通过设置left、top、right、bottom来确定位置。

6 假如给一个盒子设置相对定位给他设置top left 各20 那他是根据谁进行偏移的呢

        相对于自身进行偏移     相对定位不设置偏移量的时候 对元素没有任何影响,设置了偏移量,则基于自身初始的位置进行偏移

7 有了解过防抖跟节流吗? 简单介绍一下

防抖:就是在用户操作某事件之后等待多少秒才执行的函数,如果再次期间用户点击了,那么就清空重新计时,

	function getfn(fn,wait){
			
			let timeout=null;	// 设置一个时间戳
			return ()=>{
				//逻辑: 首先timeout为null 所以他走的是false  
				//		但是因为settimeout设置了延迟2秒,所以他不会立即输出 
				//		而同时也将settimeout()执行结果赋值给了timeout 所以此时timeout为真
				//		然后因为在两秒之内用户一直输入,再次执行这个方法,
				//		进行判断的时候,timeout为真 所以把上一个定时器给清除了
				//		当两秒之后事件执行完毕,此方法被回收了,再次调用此方法相当于重新调用
				if(timeout){	
					clearTimeout(timeout);
				}
				timeout=setTimeout(fn,wait)
			}
		}

节流: 节流就是原本频繁发生的事件,在运用节流后减少了事件发生的次数,一定程度上优化了性能,,也是设置一个时间戳为空,刚开始对时间戳取反,

function fengzhuang(fn,wait){
			let timeout=null;
			return function(){
				if(!timeout){
					
					timeout=setTimeout(()=>{
						fn(),
						timeout=null;
					},wait);
				}
			}
		}

8 你说一下js的数据类型有哪些?

基本数据类型:

        字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)

引用数据类型(对象类型)

对象(Object)、数组(Array)、函数(Function)。

9 基本数据类型和对象类型存储的区别?

        基本数据类型的值直接在栈内存中存储,值与值之间独立存在,修改一个变量不会影响到其他变量。

        对象是保存在堆内存中的,每创建一个新对象,就会在堆内存中开辟出一个新空间,而变量保存的是对象的内存地址(对象的引用),如果两个变量保存的是同一个对象引用,当其中一个通过变量修改属性时,另一个也会受到影响。

10 var let 跟const的区别

        var 声明的范围是函数作用域,let 和 const 声明的范围是块作用域

        var 声明的变量会被提升到函数作用域的顶部,let 和 const 声明的变量不存在提升,且具有暂时性死区特征

        var 允许在同一个作用域中重复声明同一个变量,let 和 const 不允许

        在全局作用域中使用 var 声明的变量会成为 window 对象的属性,let 和 const 声明的变量则不会

        const 的行为与 let 基本相同,唯一 一个重要的区别是,使用 const 声明的变量必须进行初始化,且不能被修改

关键字变量提升块级作用域重复声明同名变量重新赋值
var×
let××
const×××

11 用const 定义了一个数组 里边是一个1那么它可以改吗

                可以   我们知道const的特点是 声明一个不可修改的常量,且必须在声明的同时初始化值。但是const还有一个特点就是可以更改对象的属性 

Array和Object都是引用类型,当用const声明数组和对象时,const声明的常量保存的仅仅是目标的指针,这就意味着只要保证数组和对象的指针不发生改变,修改其中的值是被允许的。

const arr = [1,2,3,4,5]
arr[0] = 2			// 合法
arr.push(6)			// 合法
console.log(arr)	//[2,2,3,4,5,6]
arr = [1,2,3]		// 错误

12 简单说一下深浅拷贝

        浅拷贝:

        浅拷贝就是通过赋值的方式进行拷贝,那为什么说这是浅拷贝呢?就是因为赋值的方式只会把对象的表层赋值给一个新的对象,如果里面有属性值为数组或者对象的属性,那么就只会拷贝到该属性在栈空间的指针地址,新对象的这些属性数据就会跟旧对象公用一份,也就是说两个地址指向同一份数据,一个改变就会都改变。

        深拷贝:

        是会一个一个的进行拷贝,不会说,新对象的属性数据会跟旧对象公用一份,他是完全独立的

	  function deepClone(source){
		  	const targetObj= source.constructor == Array? [] :{};	//定义了一个空容器
		  	for(let keys in source){	//将source对象中的属性一一赋值给keys
		  		if(source.hasOwnProperty(keys)){	//判断source对象是否有这个属性
		  		
		  			if(source[keys] && typeof source[keys]=='object'){		//如果有这个属性并且是引用数据类型
		  				targetObj[keys]= source.constructor == Array? [] :{};//判断这个子属性是数组还是对象(这是引用层代码)
		  				// 引用数据类型
		  				targetObj[keys]=deepClone(source[keys]);	//进行递归,直至都是基本数据类型
		  			}else{
		  				// 基本数据类型
		  				targetObj[keys]=source[keys];	//基本数据类型直接赋值
		  			}
		  		}
		  
		  	}
		  	return targetObj;
		  }

13 深拷贝的方法 除了刚刚那个递归拷贝

                1 json.对象的方法实现(常用)  json.parse(JSON.stringify(arr))

                2 jqery里面的extend方法; 

var b = $.extend(true, {}, a); // 第一个参数true为深拷贝,第二个参数为目标对象,第三个参数为源对象即你用拷贝那个数据

14 如何判断一个数组为空? 你有多少种方法

         1 通过数组中的.length属性进行判断  array.length == 0 判断是否为空

         2 通过直接比较判断是否为空   array == false ?console.log(’为空‘) :console.log('不为空')

         3 JSON.stringify(data) ==="[]" ? console.log(’为空‘) :console.log('不为空')

15 如何判断一个对象为空?

         1 通过json自带的stringfy()方法进行判断

                 JSON.stringify(obj) ==="{}"? console.log(’为空‘) :console.log('不为空')

        2 通过for in 进行判断  若不为空 其中有item项 返回false 不为空 若是空数组 返回true 为空

function isEmptyObj(obj) {
	    for(let item in obj) {
	        return false
	    }
	    return true
	}
	console.log('对象是否为空:', isEmptyObj({a:"123"}))

        3 通过es6 的object.keys进行判断

              Object.keys()返回的是一个数组 所以有length的属性可以进行 ===0 的判断

  Object.keys(obj).length === 0

         4 Object.getOwnPropertyNames()方法

                Object.getOwnPropertyNames()方法会返回一个数组,如果传入的是数组,那么返回的就是原数组索引组成的一个新的数组,如果传入的是一个对象,那么,返回的是对象中的属性组成的新数组。

Object.getOwnPropertyNames(obj).length === 0

16 如何判断一个对象是否为数组,函数。       

//方法一:instanceof
    var arr = [1,2,3,1];
    console.log(arr instanceof Array); // true
    var fun = function(){};
    console.log(fun instanceof Function); // true

//方法二:constructor:
    var arr = [1,2,3,1];
    console.log(arr.constructor === Array); // true
    var fun = function(){};
    console.log(arr.constructor === Function); // true

//方法三 Object.prototype.toString()
    Object.prototype.toString()
    let arr =[]
	let obj = Object.prototype.toString.call(arr);

//方法四 判断数组 Array.isArray()
    console.log(Array.isArray(arr)); //返回true

17 你使用过git吗 能简单的说一下命令吗

        git clone                                 从远程仓库克隆代码到本地

        git init                                      初始化本地仓库

        git add 文件名|*                      将文件提交到暂存区

        git commit -m  '注释'             将文件提交到本地仓库

        git status                                查看状态,是否还有文件没有提交   

        git push                                  将本地仓库中的代码上传到之前克隆的远程仓库中

        git log                                      查看历史提交记录

        git reset --hard  版本号           版本回退

18 你es6了解多少,简单说一下?

es6 新增语法  
		let 
			let所声明的变量只有所处的块级作用域有效
			关键字就是用来声明变量的
			防止循环变量	编程全局变量
			使用let关键字声明的变量没有变量提升
			使用let关键字声明的变量具有暂时性四死区特征
		const 
			const声明的变量是一个常量
			既然常量不能重新进行赋值,如果是基本数据类型,不能更改值,如果是复杂数据类型,不能更改地址值
			声明const的时候必须给定值
        let const var 的区别
			使用var 声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象
			使用let声明的变量,其作用域为该语句所在的代码块中,且不存在变量提升
			使用const 声明的是常量,在侯敏出现的代码中不可以再修改该常量的值
        解构赋值
			解构赋值就是把数据结构分解,然后给变量进行赋值
			如果结构不成功,变量跟数值个数不匹配的时候,变量的值为undefined
			数组解构用中括号包裹,多个变量用逗号隔开,对象解构用花括号包裹,多个变量用逗号隔开
			利用解构赋值能够让我们方便的去取对象中的属性跟方法
		箭头函数
			箭头函数中不绑定this,箭头函数中的this指向是它所定义的位置,
			可以简单理解成,定义箭头函数中的作用域的this指向谁,它就指向谁
			箭头函数的优点在于解决了this执行环境所造成的一些问题。比如:
			解决了匿名函数this指向的问题(匿名函数的执行环境具有全局性),
			包括setTimeout和setInterval中使用this所造成的问题
		剩余参数
			function(...event){}
			剩余参数语法允许我们将一个不定数量的参数表示为一个数组,不定参数定义方式,这种方式很方便的去声明不知道参数情况下的一个函数
        构造函数方法:Array.from()
			Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)
		实例方法
			find() 找出第一个符合条件的数组成员 没有找到返回undifined
			findIndex() 找出第一个符合条件的数组成员的位置 如果没有找到返回-1
			includes() 判断某个数组是否包含数组的值 返回布尔值
			startswith() 表示参数字符串是否在原字符串的头部,返回布尔值
			endswith()	表示参数字符串是否在原字符串的尾部,返回布尔值
			repeat()    repeat方法表示将原字符串重复n次,返回一个新字符串
		字符串创建
			ES6新增的创建字符串的方式,使用反引号定义(模板字符串)
			在模板字符串中 可以解析变量 ${变量名}
			在模板字符串中 可以调用方法 ${方法名()}
        Set 数据结构
			ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值
			Set本身是一个构造函数,用来生成 Set 数据结构
			

            

19 比如说现在数组需要去重  你用es6的方法可以用几种?

//(1)拓展运算符 + new Set 方法
		  let narr1 = [...new Set(arr)]
//(2)Array.from + new Set 方法
		  let narr2 = Array.from(new Set(arr))
//(3)new Map() + filter方法
		  let myMap = new Map()
		  let narr3 = arr.filter((item) => {
		    return !myMap.has(item) && myMap.set(item, 1)
		  })

 其他的去重方法

    1、利用for嵌套for,然后splice去重(ES5中最常用)

function unique(arr){            
        for(var i=0; i<arr.length; i++){
            for(var j=i+1; j<arr.length; j++){
                if(arr[i]==arr[j]){         //第一个等同于第二个,splice方法删除第二个
                    arr.splice(j,1);
                    j--;
                }
            }
        }
return arr;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
    //[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}]     //NaN和{}没有去重,两个null直接消失了

        2、利用indexOf去重

function unique(arr){
    if(!Array.isArray(arr)){
        alert("error")
        return 
    }
    
    let array = []
    for(let i=0; i<arr.length; i++){
        if(array.indexOf(arr[i]) === -1 )){
               array.push[arr[i]]
        }
    }
}

        3、利用includes

function unique(arr){
    if(!Array.isArray(arr)){
        alert("error")
        return 
    }
    
    let array = []
    for(let i=0; i<arr.length; i++){
        if(!array.includes(arr[i]) )){ //includes 检测数组是否有某个值
               array.push[arr[i]]
        }
    }
}

20.Cookie、storage 的区别?什么时候使用?

1. cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。localStorage不会自动把数据发给服务器,仅在本地保存。

2. cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。

3. 存储大小限制也不同,cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。

4. 数据有效期不同,

    localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;

    cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。

5. WebStorage 支持事件通知机制,可以将数据更新的通知发送给监听者。

6. WebStorage 的 api 接口使用更方便。

使用场景:

localStorage可以用来统计页面访问次数。

cookie一般存储用户名密码相关信息,一般使用escape转义编码后存储。

补充


21 BFC

BFC(Block Formatting Context),即块级格式化上下文,它是页面中一个独立的容器,容器中的元素不会影响到外面的元素

触发条件

触发BFC的条件包含不限于:

  • 根元素,即HTML元素
  • 浮动元素:float值为left、right
  • overflow值不为 visible,为 auto、scroll、hidden
  • display的值为inline-block、inltable-cell、table-caption、table、inline-table、flex、inline-flex、grid、inline-grid
  • position的值为absolute或fixed

  

22 清除浮动的方法

方法一:使用带 clear 属性的空元素

在浮动元素后使用一个空元素,并在 CSS 中赋 予.clear{clear:both;}属性即可清理浮动。

方法二:使用 CSS 的 overflow 属性

给浮动元素的容器添加 overflow:hidden;或 overflow:auto;可以清除浮动,另外在 IE6 中还 需要触发 hasLayout ,例如为父元素设置容器宽高或设置 zoom:1。 在添加 overflow 属性后,浮动元素又回到了容器层,把容器高度撑起,达到了清理浮动 的效果。

方法三:给浮动的元素的容器添加浮动

给浮动元素的容器也添加上浮动属性即可清除内部浮动,但是这样会使其整体浮动,影 响布局,不推荐使用。

方法四:使用 CSS 的:after 伪元素

结合:after 伪元素(注意这不是伪类,而是伪元素,代表一个元素之后最近的元素)和 IEhack ,可以完美兼容当前主流的各大浏览器,这里的 IEhack 指的是触发 hasLayout。 给浮动元素的容器添加一个 clearfix 的 class,然后给这个 class 添加一个:after 伪元素实 现元素末尾添加一个看不见的块元素清除浮动

23 数组常用方法

     增

        前三种是对原数组产生影响的增添方法,第四种则不会对原数组产生影响

                        push()  接受任意数量的参数,并把他们添加到数组的末尾,返回数组的最新长度

                        unshift() 开头添加

                        splice() 

array.splice(index,howmany,item1,.....,itemX)                          

index必需。规定从何处添加/删除元素。
该参数是开始插入和(或)删除的数组元素的下标,必须是数字。
howmany可选。规定应该删除多少元素。必须是数字,但可以是 "0"。
如果未规定此参数,则删除从 index 开始到原数组结尾的所有元素。
item1, ..., itemX可选。要添加到数组的新元素

                        concat()  首先会创建一个当前数组的副本,然后再把它的参数添加到副本末尾,最后返回这个新构建的数组,不会影响原始数组

     删

                下面三种都会影响原数组,最后一项不影响原数组

                        pop() 删除数组的最后一项,同时减少数组的length 值,返回被删除的项

                        shift() 删除数组的第一项,同时减少数组的length 值,返回被删除的项

                        splice()  传入两个参数,分别是开始位置,删除元素的数量,返回包含删除元素的数组

                        slice()  创建一个包含原有数组中一个或多个元素的新数组,不会影响原始数组

arrayObject.slice(start,end)

start 必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2指倒数第二个元素,以此类推。

end 可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。

        改       

            即修改原来数组的内容,常用splice

传入三个参数,分别是开始位置,要删除元素的数量,要插入的任意多个元素,返回删除元素的数组,对原数组产生影响

        查

                即查找元素,返回元素坐标或者元素值

                indexOf() 返回要查找的元素在数组中的位置,如果没找到则返回 -1

                find() 返回第一个匹配的元素

                includes() 返回要查找的元素在数组中的位置,找到返回true,否则false

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值