前端面试总结

2 篇文章 0 订阅
1 篇文章 0 订阅

vue的双向绑定原理是什么?里面的关键点在哪里?

  • 双向绑定是采用数据劫持,结合发布者,订阅者模式的方式,通过Object.difineProperty来劫持各个属性的setter和getter
  • 然后当数据发生改变时发布信息给订阅者,触发对对应的监听回调,去实现数据的双向绑定
  • 关键点在于Object.defineProperty方法去劫持属性

现水平垂直居中的方式?

  • flex布局居中
  • 绝对定位
  • tabel-cell垂直居中
  • gril设置居中
  • 容器添加微元素,等同容器高度,子级设置display:inline-block
  • 容器固定宽高,相对定位,上左下右为0,margin为默认

用伪元素有哪一些?

  • :first-letter 向文本的第一个字母添加特殊样式
  • :first-line 向文本的首行添加特殊样式
  • :before 在元素之前添加内容
  • :after 在元素之后添加内容
  • :placeholder 匹配占位符,不过该元素设置了placeholder属性,伪元素才会生效
  • :selection CSS伪元素应用于文档中被用户高亮的部分

移动动端如何适配不同屏幕尺寸?

  • 使用js去修改rem的大小
  • 媒体查询去匹配
  • flex布局

本地存储有哪一些?他们三者有什么区别?

cookie,sessionStorage,localStorage

  • 存储大小区别,cookie数据大小不超过4k。localStorage和sessionStorage数据大小5mb,不过跟浏览器厂商有关系
  • 有效时长区别,cookie设置的会⼀直有效。即使窗⼝或浏览器关闭,localStorage持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。sessionStorage和
    localStorage使用方法基本一致,唯一不同的是生命周期,一旦页面会话关闭,sessionStorage 将会删除数据
  • 交互方式区别,cookie的数据会主动向服务器传递。sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存

JS的数据类型?如何判断js的数据类型?

js的数据类型分为两种,基本数据类型、引用数据类型

  • 基本数据类型:string,number,null,undefined,boolean
  • 引用数据类型:array,function,object
  • 判断数据类型的方法
    • typeof,instanceof,constructor,object.prototype.tostring.call()

讲一下ES6的新特性有哪些?

  • 新增了let、const、symbol关键字
  • 新增解构赋值
  • 数据类型判断
  • 新增了模块化,export和import
  • promise
  • 新增class关键字
  • 模板字符串
  • Map和Met

let、const、var三者有什么区别?

  • var存在变量提升,let和const不存在变量提升
  • var定义的变量可以被声明多次。let和const不能声明多次,会报错
  • var和let声明的变量可以被再次赋值,const声明的变量不能再次赋值
  • var声明的变量没有自身的作用域,而let、const声明的变量有自身的作用域

数组去重有哪些办法?

  • 新增构造函数set,利用set具有天然去重功能
  • 数组迭代

说一下深拷贝和浅拷贝,如何自己实现一个深拷贝?

  • 浅拷贝创造新的数据,对原有数据属性值得一份精确拷贝
 let a=[0,1,2,3,4], b=a; 
 console.log(a===b); 
 a[0]=1; 
 console.log(a,b);
  • 深拷贝开辟一个新的栈,两个对象完全相同,但是对应不同的地址,修改一个对象的属性,不会改变另一个对象的属性
   //原理其实很简单,先将对象转成JSON字符串后并复制一份,再通过stringfy还原成对象,依次达到深拷贝的目的:
    function deepClone(obj) { // 转JSON字符串并复制 
        let _obj = JSON.stringify(obj),
            // 还原成对象 
            objClone = JSON.parse(_obj);
        return objClone
    }

    let a = [0, 1, [2, 3], 4], b = deepClone(a);
    a[0] = 1;
    a[2][0] = 1;
    console.log(a, b);

两者区别在于浅拷贝只拷贝属性指向某个对象的指针,而不是对象本身,修改拷贝后的数据,原数据也会修改。深拷贝则会创造一个一模一样的对象,新对象与原对象不共享内存,修改新对象的数据不会对原数据进行修改

Vue的生命周期有哪一些?说一下它们每个阶段做什么操作?

Vue实例从创建到销毁的过程,就是生命周期。 也就是:开始创建->初始化数据->编译模板->挂载dom->数据更新重新渲染虚拟 dom->最后销毁。这一系列的过程就是vue的生命周期。所以在mounted阶段真实的DOM就已经存在了

组件通讯方式有哪一些?

  • Props适用于父传子,也适用于子传父(首先要求父组件给子组件传一个函数用来接收回调)

  • 绑定自定义事件

  • 全局事件总线eventBus

  • ref和#ref

  • provide/inject

  • parent和children

    parent和$children这两种方法是直接获取组件实例,可以直接调组件的方法或者数据

  • Vuex

Vuex有几个属性及作用?

Vuex 的 5 个核心属性分别是 State、 Getter、Mutation 、Action、 Module

  • state 为单一状态树,在 state 中需要定义我们所需要管理的数组、对象、字符 串等等,只有在这里定义了,在 Vue.js 的组件中才能获取你定义的这个对象的状态。
  • getter 有点类似 Vue.js 的计算属性,当我们需要从 store 的 state 中派生出一些 状态,那么我们就需要使用 getter,getter 会接收 state 作为第一个参数,而且 getter
    的返回值会根据它的依赖被缓存起来,只有 getter 中的依赖值(state 中的某个需 要派生状态的值)发生改变的时候才会被重新计算。
  • 更改 store 中 state 状态的唯一方法就是提交 mutation,就很类似事件。每个 mutation 都有一个字符串类型的事件类型和一个回调函数,我们需要改变 state
    的值就要在回调函数中改变。我们要执行这个回调函数,那么我们需要执行一个 相应的调用方法:store.commit。
  • action 可以提交 mutation,在 action 中可以执行 store.commit,而且 action 中可 以有任何的异步操作。在页面中如果我们要调用这个 action,则需要执行 store.dispatch
  • module模块化其实只是解决了当state中很复杂臃肿的时候,module可以将store 分割成模块,每个模块中拥有自己的 state、mutation、action 和 getter

Vue的监听属性和计算属性有什么区别?

computed特性

  1. 是计算值,
  2. 应用:就是简化tempalte里面{{}}计算和处理props或$emit的传值
  3. 具有缓存性,页面重新渲染值不变化,计算属性会立即返回之前的计算结果,而不必再次执行函数

watch特性

  1. 是观察的动作,
  2. 应用:监听props,$emit或本组件的值执行异步操作
  3. 无缓存性,页面重新渲染时值不变化也会执行

说一下防抖和节流。怎么实现?

防抖:高频事件下,控制执行最后一次
function debounce(func, wait) { var timeout; return function () { clearTimeout(timeout) timeout = setTimeout(func, wait); } } function get() { setTimeout(()=>{ console.log('111') },3000) } debounce(get(),3000)
节流:高频事件下,控制(函数)执行的次数。也就是一个单位时间内,只允许执行1次。

function throttle(func, wait) {
        var context, args;
        var previous = 0;
        return function () {
            var now = +new Date();
            context = this;
            args = arguments;
            if (now - previous > wait) {
                func.apply(context, args);
                previous = now;
            } // 时间没到,啥都不干 } } function get() { setTimeout(()=>{ console.log('111')
        }, 3000
    )
    }

    throttle(get(), 3000)

Vue的导航守卫有哪一些?

  1. 全局前置守卫beforeEach
  2. 全局解析守卫beforeResolve
  3. 路由独享的守卫beforeEnter
  4. 组件内的守卫beforeRouteEnter、beforeRouteLeave

你的登录拦截怎么实现的?

  • 首次登录,前端调用后端的登录接口,发送用户名和密码

  • 后端收到请求,验证用户名密码,验证成功,返回token

  • 前端拿到token,存储token,并跳转路由

    有用过图表吗?用的多吗?

闭包是什么?如何实现?

  • 闭包是指能够读取其他函数内部变量的函数

  • 实现方法,在函数的内部,定义一个函数,把内部函数座位返回值

function a() { 
	var num = 10;
   return function () {
   		console.log(num);
  		 }
   }
   var b = a();
   b();

Vue2.0和vue3.0有什么区别?

vue3相对于vue2来说更小更快

  • vue2采用的是面向对象变成,vue3采用的是函数式变成

  • vue3修改了细腻dom算法,只针对变化的层进行diff,而vue2是对所有的dom进行diff

  • 加强了typescript的支持

  • api一致性,提高可维护能力

  • 把更多的底层功能开放出来,比如render,依赖收集功能

  • vue2使用的是defineProperty,vue3使用的是proxy

Vue常用的指令有哪些?

v-if、v-for、v-show、v-bind、v-model、v-on等

v-If和v-show有什么区别?

v-if会操纵dom实行添加删除操作,v-show使用display来实现显示和隐藏

v-for为什么要加一个key?

key是给每一个vnode的唯一id,也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点

你是如何封装一个组件的?

创建封装成全局组件的文件、构建组件结构、注册组件、使用组件

有自己从0到1搭建过项目吗?

如果有,引文:从0到1搭建一个前端项目,具体过程

  • 项目启动

  • 项目搭建初始化

  • 项目功能配置

  • 项目优化配置

有用过uni-app吗?

。。。

你会写后台吗?有搞过服务端渲染吗?

。。。

说一下你项目中遇到的难点,如何解决?

。。。

Url到浏览器的一个过程有哪些步骤?

  1. 用户在浏览器输入url

  2. 浏览器解析域名得到服务器ip地址

  3. Tcp三次握手建立客户端和服务端的链接

  4. 客户端发送http请求获取服务器端的静态资源

  5. 服务器发送HTTP响应报文给客户端,客户端获取到页面静态资源

  6. TCP四次挥手关闭客户端和服务器的连接

  7. 浏览器解析文档资源并渲染页面

如何实现小程序的request封装及拦截?

  1. 创建一个request.js

  2. 确定http、upload和websocket前缀

  3. 封装wx.request

  4. 导出模块

  5. 使用request

  6. 拦截器完整代码

 const apiHttp = "https://*****.com";
    const socketHttp = "wss://*****.com/wss";

    function fun(url, method, data, header) {
        data = data || {};
        header = header || {};
        let sessionId = wx.getStorageSync("UserSessionId");
        if (sessionId) {
            if (!header || !header["SESSIONID"]) {
                header["SESSIONID"] = sessionId;
            }
        }
        wx.showNavigationBarLoading();
        let promise = new Promise(function (resolve, reject) {
            wx.request({
                url: apiHttp + url,
                header: header,
                data: data,
                method: method,
                success: function (res) {
                    if (typeof res.data === "object") {
                        if (res.data.status) {
                            if (res.data.status === -200) {
                                wx.showToast({
                                    title: "为确保能向您提供最准确的服务,请退出应用重新授权",
                                    icon: "none"
                                });
                                reject("请重新登录");
                            } else if (res.data.status === -201) {
                                wx.showToast({

                                    title: res.data.msg,
                                    icon: "none"
                                });
                                setTimeout(function () {
                                    wx.navigateTo({
                                        url: "/pages/user/supplement/supplement"
                                    });
                                }, 1000);
                                reject(res.data.msg);
                            }
                        }
                    }
                    resolve(res);
                },
                fail: reject,
                complete: function () {
                    wx.hideNavigationBarLoading();
                }
            });

        });
        return promise;
    }

    function upload(url, name, filePath) {
        let header = {};
        let sessionId = wx.getStorageSync("UserSessionId"); //从缓存中拿该信息
        if (sessionId) {
            if (!header || !header["SESSIONID"]) {
                header["SESSIONID"] = sessionId; //添加到请求头中
            }
        }
        wx.showNavigationBarLoading();
        let promise = new Promise(function (resolve, reject) {
            wx.uploadFile({
                url: apiHttp + url,
                filePath: filePath,
                name: name,
                header: header,
                success: function (res) {
                    resolve(res);
                },
                fail: reject,
                complete: function () {
                    wx.hideNavigationBarLoading();
                }
            });
        });
        return promise;
    }

    module.exports = {
        apiHttp: apiHttp,
        socketHttp: socketHttp,
        "get": function (url, data, header) {
            return fun(url, "GET", data, header);
        },
        "post": function (url, data, header) {
            return fun(url, "POST", data, header);
        },
        upload: function (url, name, filePath) {
            return upload(url, name, filePath);
        }
    };

在vue的项目应用中,不使用框架,怎么封装?

  • 创建vue实例
<div id="app">
	//里面引入公共组件
	<com></com>
</div>
  • 定义外部vue模板组件,且是公共组件
<template id="box">
		<div>
			<h1>我是一个公共组件</h1>
		</div>
	</template>
	
		var app = new Vue({
			el: '#app',
			data: {},
			method: {},
		});
  • 开始封装公共组件
Vue.component('com', {
	template: '#box'
})

什么是Js原型?原型链是什么?

原型在JavaScript是一个很重要的概念,它是面向对象可以继承的基础。知道吗,JavaScript的设计模式就是原型模式(二十三个经典设计模式之一),正是因为它有这个模式,所以它才十分的灵活。可以基于原型模式实现更多的面向对象设计模式。

原型链是原型的查找机制,是一条寻址链。其实原型上的方法或属性查找,都是按照一定的顺序沿着原型链进行查找的。如果查找到最后仍然没有找到这个原型和方法,那么就真的没有了

用闭包的原理做过哪些?

闭包是什么

闭包是一种特殊的对象。 它由两部分组成。执行上下文(代号A),以及在该执行上下文中创建的函数(代号B)。
当B执行时,如果访问了A中变量对象中的值,那么闭包就会产生。
在大多数理解中,包括许多著名的书籍,文章里都以函数B的名字代指这里生成的闭包。而在chrome中,则以执行上下文A的函数名代指闭包。

闭包的应用场景分为柯里化和模块化

  • 函数柯里化就是我们给一个函数传入一部分参数,此时就会返回一个函数来接收剩余的参数。
  • 模块化开发是一种管理方式,一种生产方式,一种解决问题的方案。一个模块就是实现某个特定功能的文件,我们可以很方便的使用别人的代码,想要什么模块,就引入那个模块。

作用域是什么?

作用域是在运行时代码中的某些特定部分中变量,函数和对象的可访问性。换句话说,作用域决定了代码区块中变量和其他资源的可见性。

function outFun2() {
    var inVariable = "内层变量2";
}
outFun2();//要先执行这个函数,否则根本不知道里面是啥
console.log(inVariable); // Uncaught ReferenceError: inVariable is not defined

操作数组的方式有哪些?

for、forEach、concat、filter、slice、push等

0.1 + 0.2 等于 0.3吗?为什么?如何解决?

。。。

keep-alive是什么?有哪几个生命周期阶段?

keep-alive是 Vue 提供的一个内置组件,用来对组件进行缓存

当引入keep-alive的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated

判断一个变量是否是数组,有哪些办法?

  • isArray
  • 对象原型
  • instanceof
  • Object.prototype.toString.call()

判断一个变量是否是对象,有哪些办法?

  • typeof
  • instanceof
  • constructor
  • Object.prototype.toString.call()

(附加) 讲解下Object.prototype.toString.call()

Object.prototype.toString.call()方法可以精准判断变量类型,它返回[object constructorName]的字符串格式,这里的constructorName就是call参数的函数名

对象/数组常用方法有哪些?

toSting、pop、join、slice、shift、push等

创建一个空数组/空对象有哪些方式?

空数组

var arr = [ ] ;
var arr = new Array( );

空对象

var obj = {};
var obj=new Object()

哪些遍历方式会改变原数组?

forEach、map

Set和Map各是什么?

Set

set类似于数组,但是成员的值都是唯一的,没有重复的值。可以用于数组去重。

Map

JavaScript对象object本质上是键值对的集合,Hash结构。

如何改变一个函数a的上下文?

  • 将函数挂载在对象上
  • call
  • apply
  • bind

Call和replay有什么区别?

共同

call和apply都是用来修改函数中this的指向问题;

不同

传参方式不同。call方法可以传给该函数的参数分别作为自己的多个参数,而apply方法必须将传给该函数的参数合并成一个数组作为自己的一个参数。

Evenbus是什么东西?

全局事件总线

父子组件生命周期执行顺序是怎么样的?

父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted

mixins有几个生命周期阶段?

弹性布局,一行两列,一列固定宽,如何实现?

mixin的beforeCreate > 父beforeCreate > mixin的created > 父created > mixin的beforeMount > 父beforeMount > 子beforeCreate > 子created > 子beforeMount > 子mounted > mixin的mounted >父mounted

Flex:1 包含哪三种属性

flex-grow、flex-shrink 、 flex-basis

同源策略和跨域

同源

同源策略会阻止一个域的javascrip脚本和另一个域的内容进行交互,是用于隔离潜在恶意文件的关键安全机制;

跨域

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

rem和em区别

  1. rem是相对于根元素进行计算,而em是相对于 当前元素或父元素的字体大小。
  2. rem不仅可以设置字体的大小,还支持元素宽、高等属性。
  3. em是相对于当前元素或父元素进行换算,层级越深,换算越复杂。而rem是相对于根元素计算,避免层级关系。

http和https区别

http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议 http和https使用的是完全不同的连接方式用的端口也不一样

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值