我的初稿
JavaScript篇
1. 如何对一个数组去重?比如arr=[1,2,3,4,3,2,1],有哪几种方式
答:用filter或for和indexOf搭配筛选是否存在进入新数组,或者使用ES6的new Set和...解析去重赋值。
参考:https://www.cnblogs.com/ajaemp/p/11820339.html
2. 复杂的数组如何去重(包含对象、数组、NaN、字符串等)?
(简单来说就是遍历原数组取到第一个遍历项之后,还要遍历第二个数组取到所有第二个遍历项,再根据第一个遍历项的数据类型,用合适的方法将第一个遍历项与所有第二个遍历项分别进行比较,最终在没有匹配到的情况下,将第一个遍历项压入第二个数组)
答:(1)声明另外一个数组,初始为空数组,遍历原数组。
(2)先通过typeOf判断当前项是不是object类型,这个判断包含了对象与数组的判断,是的话遍历另外一个数组,取出同样为object类型的新的项,用JSON.stringify比较当前项与新的项是否相等,相等则终止对另外一个数组的遍历,否则当另外一个数组遍历完毕还找不到相等的,则将当前项压入数组。
(3)如果不是对象,则再通过当前项是否等于自身来判断是不是为NaN,是的话将NaN压入,同时设置一个标记为true,后续不再压入NaN。
(4)最后剩下的直接判断是否存在于另外一个数组中,不存在则压入,最后另外一个数组就是去重后的数组。
3. typeOf和instanceof 的原理?
答:(1)typeOf的原理: 数据在底层都表示为二进制, 在 JavaScript 中,二进制前三位都为 0 的是object 类型,包括数组前三位也是0; 010的是number类型;100的是string类型;110的是boolean类型; 特殊的null 的二进制全是 0; undefined用 −2^30 整数表示。typeOf就是根据二进制的前三位数据来判断数据类型的。(所以执行 typeof(null、array) 时会返回“object”。)
(2)instanceof 的原理:instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false。
4. New实例化构造函数创建对象后,对象固定有属性_proto_和构造函数的prototype原型的指向问题?
答:对象固定有属性_proto_,作用就是用来找构造函数的prototype原型,而构造函数固定有prototype原型,它也是一个对象,因此prototype原型上也有个属性_proto_,最终指向Object()内置函数的prototype原型,而最后的Object()内置函数的prototype原型的_proto_属性指向null。(constructor是一个指针,关联当前原型与构造函数)。
5. 关于this指向问题?
答:1.对象中的this指向我们创建的对象本身。
2.直接调用函数时的this指向window。
3.构造函数中的this指向函数本身。
4.通过new实例化构造函数后,this指向对象实例。
6. 实参与形参?
答:实参是指传递给函数的参数,都必须是确定的值,以便把这些值传送给形参,再由函数内部接收处理。
形参是一个虚拟的变量,用来接收调用函数时传入的参数。在调用函数的时候,实参将赋值给形参。
7. bom有哪些对象?
答:1.window(核心)。2.document对象。3.location对象(当前页面地址)。4.navigation对象(浏览器本身相关信息)。
5.screen对象(屏幕相关)。6.history对象(浏览器历史相关)。
8. 如何阻止事件冒泡和阻止默认事件?
答:阻止事件冒泡:ev.stopPropagation();
阻止默认事件(1)return false;(2) ev.preventDefault();
9. 对proxy的了解?
答:Proxy可以理解成在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此可以对外界的访问进行过滤和改写。es6提供了Proxy构造函数来生成proxy。
Tips:Proxy 代理目标对象后,若存在this,this则指向Proxy。
10. es6新增的Symbol 是什么?
答:Symbol 其实也是一种基本数据类型,它的作用就是保证常量或者对象的key值的命名是唯一的。因为在ES5中,对象属性名都是字符串容易造成属性名冲突。为了避免这种情况的发生,ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。
但是Symbol不同于es5的基本数据类型,Symbol() 函数返回的是 Symbol 类型的值,且该类型具有一些方法和属性可以调用访问。
Tips: Symbol()函数不能通过new实例化,将Symbol作为key值的对象,也不能用Object.keys()或者for...in来遍历获得对象的属性名。
小程序篇
1. 微信小程序wxss设置background的url后读取不到本地文件?
答:需要用网络地址,不能直接用相对/绝对路径设置图像背景哦。
2. 小程序拒绝授权后是否还能拉起授权?
答:如果授权是指button的getPhoneNumber,即授权手机号。是可以在拒绝之后,再次点击按钮时直接拉起授权弹窗。如果是类似于保存图片到本地的wx.getSetting和wx.authorize被拒绝授权后,官方规定短时间内点击不能再触发授权弹窗,避免影响体验。需要隔一段时间后才能触发。
3. 小程序如何跳转另外一个小程序?
答:首先,在app.json里面配置navigateToMiniProgramAppIdList(是一个数组),填写要跳转小程序的appid。然后在对应跳转的页面js中使用wx.navigateToMiniProgram即可跳转
正式的可以跳预览版或体验版吗(不可以)预览可以跳预览吗(不可以)
体验版可以跳正式版吗(可以)不同公众号关联之间的正式版小程序可以相互跳转吗(可以)
4. 小程序bindtap和cacthtap之间有什么作用和区别?
(1) 相同点:首先他们都是作为点击事件函数,就是点击时触发。在这个作用上他们是一样的,可以不做区分。
(2) 不同点:他们的不同点主要是bindtap是冒泡的,catchtap是非冒泡的。
以冒泡事件tap(手指触摸后马上离开,也就是点击事件)为例子来区别bind和catch事件
bindtap? 事件绑定不会阻止冒泡事件向上冒泡
catchtap? 事件绑定可以阻止冒泡事件向上冒泡
5. 小程序之间数据传递有哪几种传递方式?页面之间,组件之间
答:页面之间:跳转路由url带参数传递,或者在app.js中设置全局变量app.globalData,还有本地缓存 wx.setStorageSync
组件之间:可以通过监听事件,用triggerEvent触发传递。可以在properties中绑定变量值,然后在父组件中直接传递。如:<child test="{{值}}"></child>
6. 小程序模板里面可以用indexOf去做判断隐藏显示吗?
严格上来说小程序是不支持用indexOf做隐藏显示的。因为mastache语法不支持js语言,包括Object.keys()和toString(),即在页面标签中,使用以下js方法无效
Tips:如果非要这么做,那么只能通过WXS(脚本语言)做
7. 微信小程序在IOS/真机上出现左右上下滑动页面出现空白解决?或者怎么禁止橡皮筋效果
答:空白解决:在wxss中page标签加入overflow-x:hidden。
禁止橡皮筋:在对应页面的page.json中设置style: { disableScroll: true }
8. 微信小程序头部Bar栏怎么去除?也就是不要它自带的标题栏
答:在不需要标题栏的文件页面json中加入"navigationStyle":"custom",则会消除掉标题栏,只留下右上角的胶囊按钮。
9. 去除头部Bar栏后,怎么自定义导航栏高度并且适应各个机型
答:确定json的navigationStyle为custom,先用getSystemInfoSync获取手机机型,并用getMenuButtonBoundingClientRect获取胶囊位置,由此计算
导航栏高度 = 状态栏到胶囊的间距(胶囊距上距离-状态栏高度) * 2 + 胶囊高度 + 状态栏高度
10. 如何转换rpx与px之间的关系,适配各类机型。
答:需要先getSystemInfo获得当前设备的屏幕宽度windowWidth,用iPhone6的750为基础进行计算。具体如下
onLoad () { wx.getSystemInfo({ success (res) { const windowWidth = res.windowWidth // 这里输出的单位是px // 假如是平移666rpx,则计算如下,以此类推 console.log(666 / 750 * windowWidth) } }) },
Vue篇
1. 为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?
答:
-
Object.defineProperty具有一些局限性,比如对数组的变动监测,会多次触发getter,对此vue阻止了对数组的监测,并通过自定义的数组api进行折中处理。另外对数据对象的监测,只能监测到属性,而且是通过层层递归遍历来实现,这些都是影响性能的。
-
Proxy 可以劫持和监听整个对象,并返回一个新的对象。可以直接监听数组以及动态增加的属性等,性能也不错。(唯一的缺点是兼容性不比Object.defineProperty)
2. vue-router的实现原理?
答:
-
在我们new VueRouter实例化VueRouter对象的时候,我们传入了路由模式类型mode和路由对象routers,此时vue-router会根据路由模式类型来执行不同的路由进退以及监听路由事件;同时解析路由对象,使得每个路由能匹配到对应的组件。
-
然后通过监听监hashchange事件或者popstate事件,当路由变化时,取出路由对应的组件,放到render函数去渲染,更新页面。
3. 请说一下怎么做路由鉴权?
答:做路由鉴权的基本思路是,首先要先有一个路由表数组,每个路由都有自己的一个id,然后在路由前拦截器router.beforeEach中请求一个接口得到当前登录账号的权限id数组,遍历路由表数组,看看路由id是否在权限id数组中,存在则取出该路由信息压入新数组中,最终得到的新数组就是可访问的路由数组,最后将该路由数组丢给router.addRoutes()方法,完成路由添加即可。
4. vue接收props后需要进行转换等操作,也就是改变props,怎么处理?
答:直接改变props是不行的,但是可以使用计算属性,使用props进行计算后返回新值。
5. 像vue-router,vuex他们都是作为vue插件,请说一下他们分别都是如何在vue中生效的/ 怎么写一个vue插件?
答:主要是用vue提供的install方法以及vue.use方法,还有vue.mixin,将插件代码混入到组件去。
6. vue获取后端数据放在created还是mounted方法里面?
答:这个要看情况,一般是放在created,在页面dom还未渲染好前开始拿数据可以节省时间;但是如果涉及到dom操作,就要在mounted,同时建议在$nextTick里。
7. vue.mixin与vue.extend区别?
答:vue.mixin只是对我们在初始化Vue实例时,对vue实例里的配置选项进行扩展,是将其他选项合并到组件中去;而vue.extend是vue实例的扩展构造器,继承vue实例的配置选项,与传入的其他选项合并。
8. $nextTick的作用?
答:Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。所以修改数据后页面dom更新,要保证dom更新后才执行逻辑,就要用$nextTick 。
9. 内置组件keep-alive的实现原理?
答:(1) keep-alive实际上也是一个组件,不过这个组件是用vue的render函数写的,而这个render函数会接收包裹起来的每个组件的标记name值以及虚拟dom对象。
(2) 然后在keep-alive组件的created阶段,会先初始一个缓存对象,将获取到的每个组件的name值作为key,以及将每个组件的虚拟dom对象作为值,存在缓存对象中。
(3) 最后在mounted阶段,根据我们设置的include以及exclude属性,遍历缓存对象,看看哪些组件是要被缓存的,当缓存的组件被激活时,就直接从缓存对象取出对应的虚拟dom对象直接使用。
10. JavaScript 的什么限制,导致Vue 不能检测到数组和对象的变动?
答:表面原因:因为往数组和对象里面新增的数据不存在于已经初始化的data选项上,不是响应式数据,所以无法被监测到,要用$set使其变成响应式数据。
根本原因:是因为在js方面,直接往数组和对象里面新增数据的这种方式会多次触发Object.defineProperty()其中的getter和setter,影响性能,对此vue停止对这种方式添加的数据的监测。
React篇
1. react组件之间是怎么通信的?
答:父传子:利用props
子传父:利用props 传入回调函数,或者redux等状态管理框架
跨级组件通信:使用context,或者redux等状态管理框架
2. 在 React 中,refs 的作用是什么?
答:Refs 可以用于获取一个 DOM 节点或者 React 组件的引用。何时使用 refs 的好的示例有管理焦点/文本选择,触发命令动画,或者和第三方 DOM 库集成。你应该避免使用 String 类型的 Refs 和内联的 ref 回调。Refs 回调是 React 所推荐的。
3. 解释 React 中 render() 的目的。
每个React组件强制要求必须有一个 render()。它返回一个 React 元素,是原生 DOM 组件的表示。如果需要渲染多个 HTML 元素,则必须将它们组合在一个封闭标记内,例如 <form>
、<group>
、<div>
等。此函数必须保持纯净,即必须每次调用时都返回相同的结果。
4. 应该在 React 组件的何处发起 Ajax 请求?
答:在 React 组件中,应该在 componentDidMount 中发起网络请求。这个方法会在组件第一次“挂载”(被添加到 DOM)时执行,在组件的生命周期中仅会执行一次。更重要的是,你不能保证在组件挂载之前 Ajax 请求已经完成,如果是这样,也就意味着你将尝试在一个未挂载的组件上调用 setState,这将不起作用。在 componentDidMount 中发起网络请求将保证这有一个组件可以更新了。
5. 父组件的值更改会带动子组件的重新渲染吗?
答:解决父组件渲染引起子组件的重新渲染。
使用钩子函数:shouldComponentUpdate(nextProps,nextState)
通过这个钩子函数的返回值来判断是否重新渲染,返回true表示重新渲染,返回false表示不再重新渲染这个组件。
6. 什么是PureComponent?
答:PureComponent其实就是一个继承自Component的子类,会自动加载shouldComponentUpdate函数。当组件需要更新的时候,shouldComponentUpdate会对组件的props和state进行一次浅比较。如果props和state都没有发生变化,那么render方法也就不会出发,当然也就省去了之后的虚拟dom的生成和对比,在react性能方面得到了优化。
7. 讲一下React的Hook,包含哪几个基础Hook以及你知道的额外Hook
答:基础Hook:useState、useEffect、useContext。额外Hook:useReducer、useCallback、useMemo、useRef、useImperativeHandle、useLayoutEffect、useDebugValue
8. React的Hook中每个Hook对应的用途或用法?
9. 何为 redux ?
答:Redux 的基本思想是整个应用的 state 保持在一个单一的 store 中。store 就是一个简单的 javascript 对象,而改变应用 state 的唯一方式是在应用中触发 actions,然后为这些 actions 编写 reducers 来修改 state。整个 state 转化是在 reducers 中完成,并且不应该有任何副作用
10. 类组件(Class component)和函数式组件(Functional component)之间有何不同?
答:1.类组件不仅允许你使用更多额外的功能,如组件自身的状态和生命周期钩子,也能使组件直接访问 store 并维持状态
2.当组件仅是接收 props,并将组件自身渲染到页面时,该组件就是一个 '无状态组件(stateless component)',可以使用一个纯函数来创建这样的组件。这种组件也被称为哑组件(dumb components)或展示组件