9/28实习一面

9/28实习一面

⏳昨天面试了一家公司,面试官人很好,而且他还对我的简历提出了一些建议,也帮我解答了一些问题。虽然没能一起工作,但我也不留遗憾。接下来和我一起看一看面试官的问题吧!

1.var,let,const的区别

  • 首先letconst是ES6新增的关键字。

  • let,var用来声明变量,可以只声明不赋值。

  • const用来声明常量,const一经过声明就必须赋值。

  • let,和const都是块级作用域,而var是函数作用域。

  • let和const没有变量提升功能,而var有变量提升。

  • 最外层的作用域,也就是全局作用域,用var声明的变量,会作为window的一个属性。而用let和const声明的变量或常量并不会作为window的属性。

2.Promise的了解

  • Promise这块我感觉答的还可以,主要前些时间正在学这个内容,知道的也大体说出来了。关于Promise这块,我单独写了一篇文章Js手写面试提5-Promise看完应该可以解决你读困惑。

3. Promise.all方法

里面有多个请求,把这些请求发送到网络中是如何发送的,是同时发送的,还是有先后顺序?

4.闭包

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

  • 闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域

  • 闭包的特性:

    • 函数内再嵌套函数
    • 内部函数可以引用外层的参数和变量
    • 参数和变量不会被垃圾回收机制回收
  • 使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念

  • 闭包 的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中

  • 闭包的另一个用处,是封装对象的私有属性和私有方法

  • 好处:能够实现封装和缓存等;

  • 坏处:就是消耗内存、不正当使用会造成内存溢出的问题

使用闭包的注意点

  • 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露
  • 解决方法是,在退出函数之前,将不使用的局部变量全部删除

5.call和apply的api

我之前写过一个文章JavaScript原型链里面有这部分的内容。

  • 首先,他们是用来改变this指向的api,使用call,和apply都可以改变this的指向,而call里面的的参数是值,而apply里的参数是数组。同时它们的返回值就是函数的返回值。

6.typeScript里继承的概念

这块我说的是js里的5中继承方法,包括作用域链继承,组合继承,组合寄生式继承,以及extend继承的这几种方法。我之前也写过一篇文章Js面试手写题第二天这块我记性不太好,没全部说出来。

  • 原型链继承
function Father(){
    this.name = '父亲'
    this.age = 45
};

function Son(){};

Son.prototype = new Father();
  • 使用构造函数来继承
function Father(){
    this.name = '父亲'
    this.age = 45
}

function Son(){
    Father.call(this)
}
  • 组合继承
function Father(){
    this.name = '父亲'
    this.age = 19
}

function Son(){
    Father.call(this,name);
}

Son.prototype = new Father()
Son.prototype.constructor = Son

这里注意实例化了两次father,所以一会提到的组合寄生式方法就出炉了。

  • 寄生式组合继承
function Father(){
    this.name = '父亲'
    this.age = 45
}

function Son(){
    Father.call(this,name);
}

Son.prototype = Object.create(Father.prototype);
Son.prototype.constructor = Son;
  • 类实现继承
class Father{
	constructor(){
        this.name = 'father'
        this.age = 45
    }
}

class Son extends Father{
    constructor(){
        super();
        this.color = color;
    }
}

7. 盒子水平居中的方案

我之前写的博客里有在文章末尾有提到

8.link/@import的区别

  1. link是html方式,而@import是Css方式
  2. link最大限制支持并行加载,而@import过多嵌套导致串行下载,出现FOUC(文档样式短暂失效)
  3. link可以通过rel="alternate stylesheet"指定候选样式
  4. 浏览器对link的支持早于@import,可以使用@import对老样式隐藏样式
  5. @import必须在样式规则之前,可以在css文件中引入其他文件
  6. 总体来说link优于@import

9.盒子模型

一张图,可以说的很清楚了。

css盒子模型

10.不同分辨率的兼容问题

方法一

按照原型图开发好固定尺寸后,根据分辨率进行方法和缩小

// 优点:不用考虑适配问题,按设计稿进行固定尺寸开发
function bodyScale() {
var devicewidth = document.documentElement.clientWidth;//获取当前分辨率下的可是区域宽度
var scale = devicewidth / 1366; // 分母——设计稿的尺寸
document.body.style.zoom = scale;//放大缩小相应倍数
}
bodyScale();

方法二

根据分别率的宽度,计算当前屏幕的分辨率宽与设计高宽成一定的比例。

11.element-ui栅格空行

Row 组件 提供 gutter 属性来指定每一栏之间的间隔,默认间隔为 0。

Element-ui栅格

12.cavans和svg的区别

  • svg绘制出来的每一个图形的元素都是独立的DOM节点,能够方便的绑定事件或用来修改。canvas输出的是一整幅画布
  • svg输出的图形是矢量图形,后期可以修改参数来自由放大缩小,不会失真和锯齿。而canvas输出标量画布,就像一张图片一样,放大会失真或者锯齿

13.使用画布的话支持事件处理吗?

之前基本没有过canvas做过小作品。

答案是当然可以:根据坐标,根据每个图形在画布上不同的坐标来区分每个图形对应的事件。这就需要大量的判断以及对坐标的精确定位。canvas提供了isPointInPath(x,y)方法来判断坐标是否在当前路径上。

canvas详解(2)-事件处理

14.SEO

  • 合理的titledescriptionkeywords:搜索对着三项的权重逐个减小,title值强调重点即可,重要关键词出现不要超过2次,而且要靠前,不同页面title要有所不同;description把页面内容高度概括,长度合适,不可过分堆砌关键词,不同页面description有所不同;keywords列举出重要关键词即可
  • 语义化的HTML代码,符合W3C规范:语义化代码让搜索引擎容易理解网页
  • 重要内容HTML代码放在最前:搜索引擎抓取HTML顺序是从上到下,有的搜索引擎对抓取长度有限制,保证重要内容一定会被抓取
  • 重要内容不要用js输出:爬虫不会执行js获取内容
  • 少用iframe:搜索引擎不会抓取iframe中的内容
  • 非装饰性图片必须加alt
  • 提高网站速度:网站速度是搜索引擎排序的一个重要指标

15.vue2.0和vue3.0的区别

  1. 初始化就存在区别,vue3.0提供了一种可视化创建脚手架,可以方便的对插件进行管理和配置,同时两个版本的目录结构也有区别。

  2. vue3.0的底层变化还是挺大的

    • Vue2.0借助Object.defineProptety()对数据进行一个劫持,结合发布订阅的方式实现。
    • Vue3.0使用了ES6中的ProxyAPI对数据代理,通过reactive()函数给每一个对象都包一层proxy,通过proxy监听属性的变化,从而实现对数据的监控。

proxy对于Object.defindprotoy的优势:

  1. definedproty只能监听某个属性,不能对全对象进行监听。
  2. 可以监听数组,不用再去单独的对数组做特异性操作,可以通过Proxy可以拦截所有对象类型数据的操作。

16.Vue双向绑定的原理

vue2.0

Object.defineProperty(obj, prop, descriptor)方法,接收三个参数,分别为obj(定义其上属性的对象)prop(定义或修改的属性)descriptor(具体的改变方法),就是用这个方法来定义一个值,当调用时我们使用了它里面的get方法,当我们给这个属性赋值时,又用到了它里面的set方法。

实现Vue双向绑定的原理是采用数据劫持结合发布者订阅者模式的方式,通过Object.definedProperty()来劫持各个属性的setter,getter,在数据变动的时候发布消息给订阅者,触发相应的监听回调,getter函数里面执行的任务是watcher订阅者,而setter函数执行的任务是发布者,双向数据绑定原理的实现就是如下几步。

  • 实现一个数据监听者Observer,可以对数据进行监听,当对象的属性有变化时,可拿到最新值并通知订阅者。
  • 实现一个执行解析者Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数。
  • 实现一个Watcher,作为连接Observer和Compile的中间桥梁,能够订阅并收到每个数据对象属性变动的同志,执行指令绑定的相对回调函数,从而达到更新视图的目的。
  • mvvm的入口。

vue3.0

使用了 es6 的 ProxyAPI 对数据代理,通过 reactive() 函数给每一个对象都包一层 Proxy,通过 Proxy 监听属性的变化,从而实现对数据的监控。

17.Vue的首屏加载缓慢

  1. 缩小项目体积
  • 使用webpack对项目体积进行一个压缩,开启gzip压缩文件
  • 相同的样式我们可以使用全局设置。
  • 减少图片的体积,加载图标可以同一图片加载。
  1. 减少请求次数/体积
  • 通过精灵图来减少小图标的请求数。
  • 图片太多,可以用懒加载。

js原生实现图片懒加载

先将img标签中的src的路径设置为同一张图片(空白图片),将真正的图片路径保存在data-src属性中,通过scrollTop方法获取浏览器窗口顶部与文档顶部之间的距离,通过clientHeight方法获取可视区高度。对window.scoll触发时,执行事件载入data-src(对每个images标签DOM来求其offsetTop,如果images距离顶部的高度 >=可视区高度+窗口距离文档顶部的距离 )。
原文链接

vue实现图片懒加载

通过安装vue-lazyload依赖=>全局引入vue-lazyload依赖=>配置依赖

npm install vue-lazyload --save
 //main.js 文件
import VueLazyload from 'vue-lazyload'	//引入依赖
Vue.use(VueLazyload)
// 配置项
Vue.use(VueLazyload, {
  preLoad: 1.3,	//表示lazyload的元素,距离页面底部距离的百分比.计算值为(preload - 1),默认值为1.3
  error: 'dist/error.png',	//加载失败后图片地址
  loading: 'dist/loading.gif',	//加载时图片地址
  attempt: 1	//	图片加载失败后的重试次数,默认值为3
})

原文链接

  1. 将大文件上传到CDN,使用CDN加速。

CDN的全称是Content Delivery Network,即内容分发网络。其通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。 因为CDN的这些特性,我们可以将体积较大的文件或是图片上传到CDN中,通过CDN来加载,减轻了服务器的请求压力,同时也可以通过CDN来获取、加载依赖。

  1. 减少加载模块

单页面应用我们可以按需加载,路由懒加载优化。

  • 按需加载,使用requier.ensure()将多个相同类的组件打包成一个文件。下面的代码就是将两个组件打包成一个js文件,名称为person
{
     path: '/personList',	//path路径	
     name: 'personList',	//组件名
     component: r => require.ensure([], () => 	r(require('../components/personList')), 'person')	//person类型的组件
},
{
     path: '/personOrder',
     name: 'personOrder',
     component: r => require.ensure([], () => r(require('../components/personOrder')), 'person')//person类型的组件
}
  • 动态加载,通过import来实现路由的动态加载,这个时候对于路由的加载时是动态的,用到的时候才会加载。
export default new VueRouter({
    routes: [
        {
            path: '/',
            component: () => import('../components/Navigator')
        }
    ]
})

18.import导包的懒加载

这块的内容我竟然不记得,后来找到才发现自己用过。。。。

export default new VueRouter({
    routes: [
        {
            path: '/',
            component: () => import('../components/Navigator')
        }
    ]
})

使用路由懒加载的写法,只会在进入当前这个路由时候才会走 component ,然后在运行import编译加载相应的组件。

注意import会返回一个Promise对象,可以链式调用。

19.请求的封装

vueAdminaxios拦截器封装,这块下去找项目学一下,的确没怎么用到过。

20.动态路由

动态的路由,和角色校验有关,不同不同的角色会获取到不同的路由,根据用户端角色,根据角色获取路径。从数据库中获取到他的path(字符串),路由路径持久化处理。

21.什么是MVVM,与MVC的区别

  • MVVM 模式是由经典的软件架构 MVC 衍生来的。当 View(视图层)变化时,会自动更新到 ViewModel(视图模型),反之亦然。View 和 ViewModel 之间通过双向绑定(data-binding)建立联系。与 MVC 不同的是,它没有 Controller 层,而是演变为 ViewModel
  • ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而 ViewModel 之间的同步工作是由 Vue.js 完成的,我们不需要手动操作 DOM,只需要维护好数据状态。
posted @ 2022-09-29 22:55  抗争的小青年  阅读(27)  评论(0编辑  收藏  举报