知识点

180 阅读11分钟

1、从浏览器地址栏输入url到显示页面的步骤

  • 浏览器查看缓存,如果请求资源在缓存中而且未失效,则直接提供给客户端。否则将重新请求。
  • 浏览器根据请求的url交给DNS域名解析,找到真实IP,向服务器发起请求。
  • 服务器交给后台处理完成后返回数据,浏览器接收文件(HTML、JS、CSS、图象等)
  • 浏览器对加载到的资源(HTML、JS、CSS等)进行语法解析,建立相应的内部数据结构(如HTML的DOM)
  • 载入解析到的资源文件,渲染页面,完成。

2、html5有哪些新特性、移除了那些元素?

  • 绘画 canvas

  • ⽤于媒介回放的 video 和 audio 元素

  • 本地离线存储 localStorage ⻓期存储数据,浏览器关闭后数据不丢失 sessionStorage 的数据在浏览器关闭后⾃动删除

  • 语意化更好的内容元素,⽐如 article 、 footer 、 header 、 nav 、 section

  • 表单控件, calendar 、 date 、 time 、 email 、 url 、 search

  • 新的技术 webworker 、 websocket 、 Geolocation

请描述⼀下 cookies , session、sessionStorage 和 localStorage 的区别?

一、存储的时间有效期不同

  1. cookie的有效期是可以设置的,默认的情况下是关闭浏览器后失效
  2. sessionStorage的有效期是仅保持在当前页面,关闭当前会话页或者浏览器后就会失效
  3. localStorage的有效期是在不进行手动删除的情况下是一直有效的

二、存储的大小不同

  1. cookie的存储是4kb左右,存储量较小,一般页面最多存储20条左右信息
  2. localStorage和sessionStorage的存储容量是5Mb

三、与服务端的通信

  1. cookie会参与到与服务端的通信中,一般会携带在http请求的头部中,例如一些关键密匙验证等。
  2. localStorage和sessionStorage是单纯的前端存储,不参与与服务端的通信。

11、闭包

  • 闭包就是能够读取其他函数内部变量的函数
  • 闭包是指有权访问另⼀个函数作⽤域中变量的函数,创建闭包的最常⻅的⽅式就是在⼀个 函数内创建另⼀个函数,通过另⼀个函数访问这个函数的局部变量,利⽤闭包可以突破作⽤链域
  • 闭包的特性: 函数内再嵌套函数 内部函数可以引⽤外层的参数和变量 参数和变量不会被垃圾回收机制回收

对闭包的理解

  • 使⽤闭包主要是为了设计私有的⽅法和变量。闭包的优点是可以避免全局变量的污染,缺 点是闭包会常驻内存,会增⼤内存使⽤量,使⽤不当很容易造成内存泄露。在js中,函数即 闭包,只有函数才会产⽣作⽤域的概念
  • 闭包 的最⼤⽤处有两个,⼀个是可以读取函数内部的变量,另⼀个就是让这些变量始终保 持在内存中
  • 闭包的另⼀个⽤处,是封装对象的私有属性和私有⽅法
  • 好处:能够实现封装和缓存等;
  • 坏处:就是消耗内存、不正当使⽤会造成内存溢出的问题

另一种解释:

闭包就是那些引用了外部作用域中变量的函数。

为了更好的理解,我们将内部函数拆成闭包和纯函数两个方面:

1、闭包是那些引用了外部作用域中变量的函数。

2、纯函数是那些没有引用外部作用域中变量的函数,它们通常返回一个值并且没有副作用。

首先闭包可以引用函数外部变量,并且会沿着原型链向上寻找; 其次,闭包引用的变量在闭包存在时不会被回收,类似于,电脑里面一个文件夹中的文件被别的程序使用了就无法被删除到回收站,这时候需要把那个程序关掉,文件夹才能被删除,闭包也是这个道理

13、Object.create()方法 常用于继承使用

Object.create()接收两个参数:

  • 第一个参数是作为新对象的原型的对象
  • 第二个参数是定义为新对象增加额外属性的对象(这个是可选属性)
  • 如果没有传递第二个参数的话,就相当于直接运行object()方法

比如说我们现在要创建一个新对象B,那么要先传入第一个参数对象A,这个A将被作为B prototype;

var A  = {
    name:'A',
    color:['red','green']
}

//使用Object.create方法先复制一个对象
var B = Object.create(A);

这时候我们console.log(B)

可以看到结果 所以它是可以直接把A对象作为了B的原型对象的

这是我们再看看第二个参数的用法

var A  = {
    name:'A',
    color:['red','green']
}

//使用Object.create方法先复制一个对象
var B = Object.create(A, {
    age: {
        value: 24
    }
});

这时候console.log(B)

14、new操作符具体干了什么呢?

www.jianshu.com/p/fc50c2a7d…

1.当使用了构造函数,并且new 构造函数(),后台会隐式执行new Object()创建对象;

2.将构造函数的作用域给新对象,(即new Object()创建出的对象),而函数体内的this就代表new Object()出来的对象。

3.执行构造函数的代码。

4.返回新对象(后台直接返回);

15、如何进行跨域

20、es6中class类

22、如何通过JS判断⼀个数组

1、instanceof ⽅法

instanceof 运算符是⽤来测试⼀个对象是否在其原型链原型构造函数的属性

var arr = [];
arr instanceof Array; // true

2、constructor ⽅法

constructor 属性返回对创建此对象的数组函数的引⽤,就是返回对象相对应的构造 函数

var arr = [];
arr.constructor == Array; //true

3、Object.prototype.toString.call(value)

blog.csdn.net/Aer_7z/arti…

4、ES5 新增⽅法 isArray()

var a = new Array(123);
var b = new Date();
console.log(Array.isArray(a)); //true
console.log(Array.isArray(b)); //false

23、数组的排序

// 升序
var arr = [1,2,3,4,5,6,7,8,9,10]
arr.sort(function(a, b){
 return a - b
})

//倒序
var arr = [1,2,3,4,5,6,7,8,9,10]
arr.sort(function(a, b){
 return b - a
})

//乱序
var arr = [1,2,3,4,5,6,7,8,9,10]
arr.sort(function(){
 return Math.random() - 0.5
})

24、怎样添加、移除、移动、复制、创建和查找节点

blog.csdn.net/qi127119979…

性能优化

使用虚拟列表来优化渲染性能,采用keep-alive缓存组件,第三方库的按需引用,路由的懒加载,防抖节流函数的使用,通过构建工具的一些配置来加快构建速度和压缩打包的体积。

长列表怎么优化 虚拟列表

juejin.cn/post/738906…

27、前端⾯试之MVVM浅析

juejin.cn/post/736123…

28、实现⼀个函数clone

可以对 JavaScript 中的5种主要的数据类型,包括 Number 、 String 、 Object 、 Array 、 Boolean )进⾏值复

Object.prototype.clone = function(){
 var o = this.constructor === Array ? [] : {};
 for(var e in this){
 o[e] = typeof this[e] === "object" ? this[e].clone() : th
 }
 return o;
}

36、计算属性computed和侦听器watch

37、webpack的mode设置为prodction后做了什么?

  • tree shaking

    tree shaking 是一个术语,通常用于打包时移除 JavaScript 中的未引用的代码(dead-code),它依赖于 ES6 模块系统中 importexport静态结构特性。

    开发时引入一个模块后,如果只使用其中一个功能,上线打包时只会把用到的功能打包进bundle,其他没用到的功能都不会打包进来,可以实现最基础的优化

  • scope hoisting

    scope hoisting的作用是将模块之间的关系进行结果推测, 可以让 Webpack 打包出来的代码文件更小、运行的更快

    scope hoisting 的实现原理其实很简单:分析出模块之间的依赖关系,尽可能的把打散的模块合并到一个函数中去,但前提是不能造成代码冗余。 因此只有那些被引用了一次的模块才能被合并。

    由于 scope hoisting 需要分析出模块之间的依赖关系,因此源码必须采用 ES6 模块化语句,不然它将无法生效。 原因和tree shaking一样。

let a = 1
let b = 2
let c = 3
console.log(a + b + c)

如上面的代码 打包完后代码后只会显示console.log(6) 而定义a b c的代码将会被清除掉,因为prodction模式会提前推测出结果

  • 代码压缩

    所有代码使用UglifyJsPlugin插件进行压缩、混淆

39、Vue 内部是怎么知道 computed 依赖的?

www.jianshu.com/p/c9e3df578…

41、Vue.extend使用

blog.csdn.net/lixianghai2…

www.cnblogs.com/hentai-miao…

42、VUE修饰符sync

www.jianshu.com/p/d42c508ea…

13、常用数组去重方法总结

方法一、利用ES6 Set去重(ES6中最常用)

function unique (arr) {
  return Array.from(new Set(arr))
  // return [...new Set(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", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]

方法二、利用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))

方法三、利用indexOf去重

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array = [];
    for (var i = 0; i < arr.length; i++) {
        if (array .indexOf(arr[i]) === -1) {
            array .push(arr[i])
        }
    }
    return array;
}
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", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}]  //NaN、{}没有去重

方法四、利用includes

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array =[];
    for(var i = 0; i < arr.length; i++) {
            if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值
                    array.push(arr[i]);
              }
    }
    return array
}
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", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]     //{}没有去重

14、防抖/节流

segmentfault.com/a/119000001…

【Vue原理】响应式原理 - 白话版

mp.weixin.qq.com/s?__biz=MzU…

【Vue原理】月老Computed - 白话版

zhuanlan.zhihu.com/p/53219652

32、Proxy 相比于 defineProperty 的优势

Object.defineProperty() 的问题主要有三个

  • 不能监听数组的变化
  • 必须遍历对象的每个属性
  • 必须深层遍历嵌套的对象

Proxy 在 ES2015 规范中被正式加入,它有以下几个特点

  • 针对对象:针对整个对象,而不是对象的某个属性,所以也就不需要对 keys 进行遍历。这解决了上述 Object.defineProperty() 第二个问题
  • 支持数组:Proxy 不需要对数组的方法进行重载,省去了众多 hack,减少代码量等于减少了维护成本,而且标准的就是最好的。

除了上述两点之外,Proxy 还拥有以下优势:

  • Proxy 的第二个参数可以有 13 种拦截方法,这比起 Object.defineProperty() 要更加丰富
  • Proxy 作为新标准受到浏览器厂商的重点关注和性能优化,相比之下 Object.defineProperty() 是一个已有的老方法。

v-model讲解

v-model本质上是语法糖,v-model在内部为不同的输入元素使用不同的属性并抛出不同的事件

  • text 和 textarea 元素使用 value 属性和 input 事件
  • checkbox 和 radio 使用 checked 属性和 change 事件
  • select 字段将 value 作为 prop 并将 change 作为事件 所以我们可以v-model进行如下改写:
<input v-model="sth" />
//  等同于
<input :value="sth" @input="sth = $event.target.value" />

juejin.cn/post/722449…

36、说一下vue2.x中如何监测数组变化

使用了函数劫持的方式,重写了数组的方法,Vue将data中的数组进行了原型链重写,指向了自己定义的数组原型方法。这样当调用数组api时,可以通知依赖更新。如果数组中包含着引用类型,会对数组中的引用类型再次递归遍历进行监控。这样就实现了监测数组变化。

38、再说一下虚拟Dom以及key属性的作用

  • 由于在浏览器中操作DOM是很昂贵的。频繁的操作DOM,会产生一定的性能问题。这就是虚拟Dom的产生原因

  • Virtual DOM本质就是用一个原生的JS对象去描述一个DOM节点。是对真实DOM的一层抽象

  • VirtualDOM映射到真实DOM要经历VNode的create、diff、patch等阶段 key的作用是尽可能的复用 DOM 元素

  • 新旧 children 中的节点只有顺序是不同的时候,最佳的操作应该是通过移动元素的位置来达到更新的目的

  • 需要在新旧 children 的节点中保存映射关系,以便能够在旧 children 的节点中找到可复用的节点。key也就是children中节点的唯一标识

39、Vue中组件生命周期调用顺序说一下

  • 组件的调用顺序都是先父后子,渲染完成的顺序是先子后父。
  • 组件的销毁操作是先父后子,销毁完成的顺序是先子后父

1、加载渲染过程:

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

2、子组件更新过程:

父beforeUpdate->子beforeUpdate->子updated->父updated

3、父组件更新过程:

父 beforeUpdate -> 父 updated

4、销毁过程:

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

40、SSR了解吗

SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端

SSR有着更好的SEO、并且首屏加载速度更快等优点。不过它也有一些缺点,比如我们的开发条件会受到限制,服务器端渲染只支持beforeCreate和created两个钩子,当我们需要一些外部扩展库时需要特殊处理,服务端渲染应用程序也需要处于Node.js的运行环境。还有就是服务器会有更大的负载需求

41、你都做过哪些Vue的性能优化

编码阶段

  • 尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher
  • v-if和v-for不能连用
  • 如果需要使用v-for给每项元素绑定事件时使用事件代理
  • SPA 页面采用keep-alive缓存组件
  • 在更多的情况下,使用v-if替代v-show
  • key保证唯一
  • 使用路由懒加载、异步组件
  • 防抖、节流
  • 第三方模块按需导入
  • 长列表滚动到可视区域动态加载
  • 图片懒加载

SEO优化

  • 预渲染
  • 服务端渲染SSR

打包优化

压缩代码

  • Tree Shaking/Scope Hoisting
  • 使用cdn加载第三方模块
  • 多线程打包happypack
  • splitChunks抽离公共文件
  • sourceMap优化

用户体验

  • 骨架屏
  • PWA 还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。

44 v-on 的.stop、.prevent、.self、.once

  • .stop 该修饰符将阻止事件向上冒泡。同理于调用 event.stopPropagation() 方法
  • .prevent 该修饰符会阻止当前事件的默认行为。同理于调用 event.preventDefault() 方法
  • .self 该指令只当事件是从事件绑定的元素本身触发时才触发回调
  • .once 该修饰符表示绑定的事件只会被触发一次

48、清除浮动的方法

blog.csdn.net/muxianer/ar…

50、何为构建工具

“构建”也可理解为“编译”,就是将开发环境的代码转换成运行环境代码的过程。开发环境的代码是为了更好地阅读,而运行环境的代码是为了更快地执行,两者目的不一样,因此代码形式也不一样。例如,开发环境写的 JS 代码,要通过混淆压缩之后才能放在线上运行,因为这样代码体积更小,而且对代码执行不会有任何影响。总结一下需要构建工具处理的几种情况:

  • 处理模块化:CSS 和 JS 的模块化语法,目前都无法被浏览器兼容。因此,开发环境可以使用既定的模块化语法,但是需要构建工具将模块化语法编译为浏览器可识别形式。例如,使用 webpack、Rollup 等处理 JS 模块化。
  • 编译语法:编写 CSS 时使用 Less、Sass,编写 JS 时使用 ES6、TypeScript 等。这些标准目前也都无法被浏览器兼容,因此需要构建工具编译,例如使用 Babel 编译 ES6 语法。
  • 代码压缩:将 CSS、JS 代码混淆压缩,为了让代码体积更小,加载更快。

53、查找字符串中出现最多的字符和个数

let str = "abcabcabcbbccccc"

let arr = str.split('')

let obj = {}
arr.forEach(item => {
    if (Reflect.has(obj, item)) {
        obj[item]++
    } else {
        obj[item] = 1
    }
})
console.log(obj) // {a: 3, b: 5, c: 8}

v-for key的作用

当Vue用 v-for 正在更新已渲染过的元素列表是,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue将不是移动DOM元素来匹配数据项的改变,而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。

为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。key属性的类型只能为 string或者number类型。

key 的特殊属性主要用在Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes。如果不使用 key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用key,它会基于key的变化重新排列元素顺序,并且会移除 key 不存在的元素。

怎样将图片资源放在cdn上

将图片资源放在 CDN 上是一种通过将图片缓存在多个节点,实现快速响应和减轻服务器压力的方法。以下是实现将图片资源放在 CDN 上的步骤:

  1. 注册一个 CDN 服务商。常见的服务商包括阿里云、腾讯云、七牛云等。
  2. 在 CDN 后台设置图片存储空间和访问域名。
  3. 选择将图片资源上传到 CDN 的方式。常见的方式包括手动上传和通过程序批量上传。
  4. 在程序中配置 CDN 的相关参数,如图片链接地址、防盗链设定等。
  5. 测试图片加载速度和响应时间,确认 CDN 是否能起到加速和减压的作用。

以上是常见的将图片资源放在 CDN 上的方法。需要注意的是,选择 CDN 服务商需要根据自己的需求和网络状况进行选择,避免过度投资。同时需要对网站图片资源进行合理的设计,以便更好地利用 CDN 的加速和减压功能。 blog.csdn.net/2301_819222…

vue2与vue3的区别

vue3对于vue2来说,最大的变化就是composition Api 替换了vue2的options Api

响应式原理由vue2的Object.defineproperty替换为vue3的proxy

其中proxy有着以下这些优点:

  • 1:对象新增的属性不需要使用$set添加响应式,因为proxy默认会监听动态添加属性和删除属性等操作
  • 2:消除数组上无法监听数组索引、length属性,不再进行数组原型对象上重写数组方法
  • 3:Object.defineproperty是劫持所有对象的属性设置为getter、setter,然后遍历递归去实现。而proxy则是代理了整个对象。
  • 4:vue2使用Object.defineproperty拦截对象的get和set属性进行操作。而proxy有着13种拦截方法。
  • 5:由vue2的响应式原理可以看出,vue底层需要对vue实例的返回的每一个key进行get和set操作,无论这个值有没有被用到。所以在vue中定义的data属性越多,那么初始化开销就会越大。而proxy是一个惰性的操作,它只会在用到这个key的时候才会执行get,改值的时候才会执行set。所以在vue3中实现响应式的性能实际上要比vue2实现响应式性能要好

重写了虚拟Dom实现,提高了渲染性能

使用setup代替了之前的beforeCreate和created

vue3通过使用了treeshaking与构建工具的结合,使打包的体积更小

11. vite比webpack快在哪里

一、开发模式的差异

在开发环境中,Webpack 是先打包再启动开发服务器,而 Vite 则是直接启动,然后再按需编译依赖文件。(大家可以启动项目后检查源码 Sources 那里看到)

这意味着,当使用 Webpack 时,所有的模块都需要在开发前进行打包,这会增加启动时间和构建时间。

Vite 则采用了不同的策略,它会在请求模块时再进行实时编译,这种按需动态编译的模式极大地缩短了编译时间,特别是在大型项目中,文件数量众多,Vite 的优势更为明显。

二、底层语言的差异

Webpack 是基于 Node.js 构建的,而 Vite 则是基于 esbuild 进行预构建依赖。esbuild 是采用 Go 语言编写的,Go 语言是纳秒级别的,而 Node.js 是毫秒级别的。因此,Vite 在打包速度上相比Webpack 有 10-100 倍的提升。

webpack知识点: juejin.cn/post/735053…