前端面试题-01

本文详细阐述了HTML中的src与href区别,BFC概念及其应用,以及不同方法实现水平垂直居中布局。在JavaScript部分,讨论了new操作符的工作原理,var、let、const的差异,作用域与作用域链,闭包,箭头函数的特性,以及this的指向规则。此外,还涵盖了数组API,Vue组件生命周期和Vue-router的路由守卫机制。
摘要由CSDN通过智能技术生成

一、HTMLCSS相关

1、srchref的区别

src指向的资源,一般会嵌入到页面中,所以会阻塞式的进行下载;

href指向的资源,是并行下载的

2、BFC是什么

BFC就是一块独立的布局空间,该空间的布局,不会影响空间外部的布局。

所以可以利用BFC来解决坍塌、重合等问题。

可以使用浮动、绝对/相对定位等方法来将一块区域变为BFC

3、如何实现水平垂直居中布局

绝对定位

如果子元素,有固定的宽高:

.class {
    margin: auto;
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
}

绝对定位

如果子元素没有固定宽高,则使用百分比移动,然后使用过渡:

.class {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(50%, 50%);

}

flex

.class {
    display: flex;
    justify-content: center;
    align-items: center;
}

inline-block

将子元素设置为inline-block,然后父元素设置内容居中

.container {
    line-height: 100px;
    text-align: center;
}

.class {
    display: inline-block;
}

二、JavaScript基础

1、关于new操作符

1.1 构造函数调用时,判断是否使用了new操作符

如果是通过new来调用的函数,在函数内部会有一个对象new.target,可以通过是否有这个,来进行判断。

1.2 new操作符的实现过程

new操作符,用于创建一个类型的实例。使用了new操作符的构造函数,会执行以下步骤:

  • 使用当前构造函数的原型,来创建一个对象
  • 将该对象,绑定为构造函数的上下文
  • 然后执行构造函数,给对象进行初始化
  • 最后返回构造函数的this。如果构造函数手动返回了对象,则会覆盖掉this

1.3 手写一个new函数,能实现new操作符的功能

function Base() {
    this.name = '基类'
}

//打印标准的实例
const testInstance = new Base()
console.log(testInstance)

// 模拟new的函数
function handleNew(cls) {
    const instance = Object.create(cls.prototype);
    cls.call(instance)
    return instance
}

// 测试实例
const newInstance = handleNew(Base)
console.log(newInstance)
// 判断类型
console.log(newInstance instanceof Base)

2、变量相关let,const,var

2.1 var

历史语法。

在执行环境的活动对象上进行取值,未声明或已声明未赋值,都是undefined。 所以表现为变量声明后,代码提升到了作用域顶部,只不过值是undefined

同理,使用function声明的函数,也会放在活动对象上,所以在任何地方声明后,都可以调用。

如果一个变量,即使用了var声明,也使用了function声明,那么在代码刚刚开始执行的时候,这个变量的值就是函数。

2.2 letconst

  • 只在块级作用域生效
  • 暂时性死区,也就是在作用域里,只有声明之后才能使用
  • 不允许重复声明
  • const声明的变量,指针固定,所以基本类型的数据不可以修改;引用类型的数据可以更改堆内容

2.3 作用域和作用域链

作用域,就是执行栈中,一个执行环境的可访问行。

一个执行环境,包含了互动对象,作用域链等部分。

执行栈顶部的执行环境,作用域链中会包含执行栈底部环境的作用域链,这样在顶部的执行环境,就能完成沿着作用域链的变量查找。

2.4 闭包

当一个执行环境中,使用了另外一个执行环境的变量,造成另外的执行环境无法释放内存的情况,就是闭包。

就是函数,和其上下文,形成了绑定的引用,可以用于匿名自执行函数、结果缓存等。

3、数组

数组相关的API:

  • Array.from:将可迭代对象,转为数组
  • keys,values,entries:将数组的内容,包装为一个迭代器返回,可以用for...of等方法进行迭代
  • flat:拉平数组,可以传入参数,代表拉平的层数,如果全部拉平,可以传入Infinity
  • fill:使用一个值,填充数组。如果是对象,则数组所有元素持有的是一个对象
  • filter,map:返回数组元素的浅拷贝,对数组的每一个元素,都调用一个回调函数
  • pop,push,shift,unshift:对数组元素进行操作,返回数组长度
  • slice(start,end):返回指定区间的数组元素的浅拷贝
  • splice(start,count,items):原地更换数组数据,并将切片出来的数据,进行返回
  • sort排序,回调返回负数,交换位置;所以a-b是从小到大排列
  • at:返回固定索引的元素,可以为负数
  • Array.isArray:用来判断是否为数组

4、箭头函数

  • 内部没有this,this是从作用域链中查找到的上一层执行栈
  • 都是匿名函数
  • 没有原型对象,也没有super关键字,所以不可以当作构造函数,new的话会报错
  • 可以解决内部函数的this指向问题。因为内部函数直接调用时,this是指向全局,而不是当前函数作用域的this,除非使用bind,call等方法解决。利用箭头函数可以解决

5、this的指向

5.1 this指向

  • 默认绑定:函数没有调用上下文,直接执行,this绑定到全局
  • 隐式绑定:有调用上下文,例如通过对象调用,this绑定到上下文
  • 显式绑定:通过api进行强制绑定,例如bind,call
  • new操作符:this就是new时新建的那个对象

5.2 bind,call

  • bind:用于永久的更改函数执行时的this,该函数会返回一个新的函数
  • call:临时绑定this来执行函数

6、原型

原型,用于实现类型,和类型之间的继承。

6.1 原型的指向

原型对象,就是构造函数的一个属性,构造函数的prototype属性,指向构造函数的原型对象。

当使用构造函数来实例化一个对象的时候,会在实例化对象上,增加一个__proto__属性,该属性也指向原型对象。

原型对象,用于给实例对象提供通用的属性和方法,使某个构造函数的多个实例化对象拥有相同功能的方法。当在实例化对象上进行属性或方法的查找时,如果未发现该属性或方法,就会沿着__proto进入到原型对象中进行查找。

instanceof操作符就是来判断某个构造函数,是否能在一个实例化对象的原型链中查询到,从而判断该对象是否属于这个类型。

6.2 继承

ES5中,需要基于原型,手动实现类型的继承:

// 声明 父类
function BaseCls() {
    this.name = '父类';
}

//声明子类
function ChildCls() {
    BaseCls.call(this);
    this.name = "子类";
}

// 实现原型继承
ChildCls.prototype = Object.create(BaseCls.prototype)

6.3 判断类型

使用内置的函数Object.toString.call(obj)可以判断一个对象,是否为内建类型的实例。

例如:

Object.prototype.toString.call('') // [object String]
Object.prototype.toString.call(new Date()) // [object Date]

但是,无法判断是否为自定义的引用类型。

7、=====

7.1 ==相等

相等判断比较宽松

  • 如果是比较两个引用类型,就比较指针
  • 如果是比较两个基本类型,会触发类型隐式转换
  • 一个基本类型,和一个引用类型,会调用引用类型的toString方法,转为基本类型
  • 对于nullundefined,对上nullundefined都为true
  • 基础类型隐式转换,有string先转string,没有的话判断number,转number

7.2 ===严格相等

不会进行类型转换,直接进行类型和值的校验

7.3 Object.is

相当于加强版的严格相等,其中-0和0不相等;NaNNaN相等

8、for...infor...of

8.1 for...of

在可迭代对象上,创建一个迭代。

可迭代对象包括Array , String , Map

8.2 for...in

在任意的一个对象上,迭代其可枚举属性,包括继承的可枚举属性。

9、函数

9.1 函数柯里化

函数柯里化,就是函数返回一个可执行的函数,也是闭包的经典用法。

9.2 防抖

多次触发,只执行一个函数,用于屏蔽频繁操作

9.3 节流

稀释函数执行的次数,功能实现类似于防抖

JavaScript实现:

let status = 1; // 0,1
let timer = null;

function fn() {
    if (status === 1) {
        console.log('执行')
        timer = setTimeout(() => {
            status = 0;
            timer = clearTimeout(timer)
        }, 2000)
    } else {
        console.log('节流中')
    }
}

10、事件

事件冒泡的阶段:事件捕获 -> 目标触发 -> 事件冒泡

阻止事件默认行为:preventDefault

阻止事件冒泡:stopPropagation

11、promise

11.1 promise介绍

promise是一种异步编程的解决方案。它是一个对象,来存储异步执行的状态,有进行中、结束、失败三个状态。

promise在初始化执行的时候,处理所有的操作,然后把异步执行的状态进行存储,并且返回promise对象。

然后在需要读取promise对象异步结果的地方,执行then就能读取成功状态的异步结果。

11.2 async/await

async就是promise的语法糖,使用了async标识的函数,其返回值自动封装为一个promise对象。

在使用了async标记的函数内部,通过使用await来添加一个异步回调操作,也就是说await就是then的语法糖。

12、proxy

12.1 proxy代理

proxy代理,就是重载对象的各种操作符,然后执行一些特定的监听处理函数。这些操作符包括.操作符、迭代等。

proxy的优点:

  • 不会对对象进行入侵,只是一层拦截,然后就可以将操作转发到对象上
  • 重载了对象的所有操作符,包括. , in , delete ,索引等

相比较与原始Vue2中使用的Object.defineProperty的缺点:

  • 需要对对象的所有属性都设置存取器才能实现操作拦截
  • 部分操作无法进行拦截,例如数组的索引操作,这时就需要重写数组的操作方法
  • 未来该API会被删除掉,所有操作都以标准化的reflect对象进行操作

12.2 reflect

reflect也是标准的对象操作API,将所有的对象操作,进行标准化的耦合。

并且,reflect对象在使用get和set处理函数的时候,可以给函数设置this,能解决部分边界情况造成的this丢失

三、Vue相关

1、vue-router是如何监听url变化的

对于使用了hash模式的路由来说,当url变化时,是不会重新请求后端的。

所以这时候就需要使用原生的监听模式onhashchange来监听url是否发生了变化

如果是使用了history模式的路由,当路由变化时,不能直接刷新url,而是需要使用原生的history API来 将要变更的url加入到url栈中,以此来实现页面不刷新。但是在此情况下,需要后端进行支持,否则后端url会报错。

2、Vue的组件生命周期

  • setup:
  • beforCreate
  • init Options API
  • created
  • complate template
  • beforeMount
  • init render, create & insert dom
  • mounted
  • beforeUpdate
  • patch
  • updated
  • beforeUnmount
  • unmounted

3、Vue-router的路由守卫

  • 导航触发
  • 失活的组件里调用beforeRouteLeave
  • 调用全局前置守卫beforeEach
  • 重用的组件里调用beforeRouteUpdate
  • 然后在路由配置的页面里,调用beforeEnter
  • 然后解析组件
  • 在被激活的组件里,调用beforeRouteEnter
  • 全局解析后的守卫beforeResolve
  • 导航成功
  • 全局后置钩子,注意,不是守卫afterEach
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值