面经篇(一)

1. JS 基本数据类型和引用数据类型都有哪些,有什么区别?

  • 基本数据类型: String 、Boolean 、Number 、null 、undefined 、symbol
  • 引用数据类型: 统称为Object类型,细分包括:Object 、Function 、Array 、Date

区别: 基本数据类型的数据存储在中,而引用数据类型的数据存在中,在栈中保存数据的引用地址
扩展: 栈内存是自动分配内存的,而堆内存是动态分配内存的,不会自动释放。所以每次使用完对象时都要把它设置为 null,从而减少无用内存的消耗。

2. 闭包是什么?,作用(优点、缺点)以及应用场景有哪些?

闭包特性:

  • 函数嵌套函数;
  • 函数内部可以引用函数外部的参数和变量;
  • 参数和变量不会被垃圾回收机制回收。

作用
优点:

  • 希望一个变量长期存储在内存中
  • 避免全局变量的污染
  • 私有成员的存在

缺点:

  • 常驻内存,增加内存使用量
  • 内存泄漏

应用场景:

  • for循环中的保留 i 的操作
  • 设计模式中的单例模式
  • 防抖和节流
  • 函数柯里化

2.1 什么是内存泄漏?

答:内存泄漏是指 不再使用的内存没有被及时释放出来,导致该段内内存无法被使用。

2.2 为什么会导致内存泄漏?

答:内存泄漏指我们无法再通过 js 访问某个对象,而垃圾回收机制却认为该对象还在被引用,因此垃圾回收机制不会释放该对象,导致该内存永远无法释放,积少成多,系统会越来越卡以至崩溃。

2.3 垃圾回收机制都有哪些策略?

标记清除法:

  • 对于脱离作用域的变量进行回收,当进入作用域时,进行标记,离开作用域时,标记并回收这些变量.

引用计数法:

  • 引用计数是跟踪记录每个值被引用的次数。就是变量的引用次数,被引用一次则加1,当这个引用计数为0时,被视为准备回收的对象,每当过一段时间开始垃圾回收的时候,就把被引用数为0的变量回收。
  • 缺点:引用计数方法可能导致循环引用,类似死锁,导致内存泄露。.当两个对象循环引用时,引用计数无计可施。如果循环引用多次执行,会造成崩溃等问题。所有后来被 标记清除法 取代

参考

3. 原型,原型链

原型: 原型分为隐式原型和显式原型,每个对象都有一个隐式原型,它指向自己的构造函数的显式原型。每个构造方法都有一个显示原型。

  • _proto_是隐式原型;prototype是显式原型
  • 所有实例的_proto_都指向他们构造函数的prototype
  • 所有的prototype都是对象,自然它的_proto_指向的是Object()prototype
  • 所有的构造函数的隐式原型指向的都是Function()的显式原型
  • Object的隐式原型是null

原型链: 多个_proto_组成的集合成为原型链(概念类似于作用域链)

  • instanceof就是判断某对象是否位于某构造方法的原型链上。

4. 常见的布局方法有哪些?

CSS 布局的三种机制:普通流(标准流)浮动(float)和定位(position)。
另外还有:弹性(flex)布局圣杯布局双飞翼布局

4.1 如何实现圣杯布局和双飞翼布局?

以上两种布局理解:

  • 三栏布局,中间一栏最先加载和渲染(内容最重要)
  • 两侧内容固定,中间内容随着宽度自适应
  • 一般适用于 PC 页面

实现:

  1. 使用 float 布局;

  2. 两侧使用 margin 负值,以便和中间内容横线重叠;

  3. 防止中间内容被两侧覆盖,一个用 padding(圣杯布局),一个用 margin (双飞翼布局)。
    在这里插入图片描述
    双飞翼布局

  4. 三块 都给 左浮动 float:left

  5. 左边 给 margin-left:-100%

  6. 右边 给 margin-left:-右宽px

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>双飞翼布局</title>
    <style>
        .column {
            float: left;
        }
        
        #center {
            width: 100%;
            height: 200px;
            background-color: pink;
        }
        
        #left {
            width: 200px;
            height: 200px;
            margin-left: -100%;
            background-color: green;
        }
        
        #right {
            width: 200px;
            height: 200px;
            margin-left: -200px;
            background-color: powderblue;
        }
    </style>

    <body>

        <div id="center" class="column">#center</div>
        <div id="left" class="column">#left</div>
        <div id="right" class="column">#right</div>


    </body>

</html>

圣杯布局

  1. 三块 都给 左浮动 float:left
  2. 三块的父亲 给 padding-left:左盒子宽pxpadding-right:右盒子宽px
  3. 左盒子和右盒子 都给 定位 左右 position:relativeleft/right:-左右盒子宽px
  4. 左边 给 margin-left:-100%,右边 给 margin-left:-右宽px
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>圣杯布局</title>
    <style>
        .container {
            padding-left: 200px;
            padding-right: 200px;
        }
        
        .column {
            float: left;
        }
        
        #center {
            width: 100%;
            height: 200px;
            background-color: pink;
        }
        
        #left {
            position: relative;
            left: -200px;
            width: 200px;
            height: 200px;
            margin-left: -100%;
            background-color: green;
        }
        
        #right {
            position: relative;
            right: -200px;
            width: 200px;
            height: 200px;
            margin-left: -200px;
            background-color: powderblue;
        }
    </style>
</head>

<body>
    <div class="container">
        <div id="center" class="column">#center</div>
        <div id="left" class="column">#left</div>
        <div id="right" class="column">#right</div>
    </div>
</body>

</html>

5. 数据类型的判断有哪些?对象类型的判断方法?参数?

判断数据类型的方法有:typeofinstanceofconstructortoString四种。

  • typeof:可以检测基本数据类型,但检测 null 为 Object 类型。检测引用数据类型都返回 Object,其中检测引用类型的 function 返回 function。
console.log(typeof 2);               // number
console.log(typeof true);            // boolean
console.log(typeof 'str');           // string
console.log(typeof function(){});    // function
console.log(typeof {});              // object
console.log(typeof undefined);       // undefined
console.log(typeof null);            // object     null 的数据类型被 typeof 解释为 object
console.log(typeof []);              // object     []数组的数据类型在 typeof 中被解释为 object
  • instanceof:可以判断某对象是否位于某构造方法的原型链上.
console.log(2 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false  
console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object);                   // true    
//下面这俩比较特殊(JS发展过程中的失误)
// console.log(undefined instanceof Undefined);
// console.log(null instanceof Null);

在这里插入图片描述

  • constructor:JS中每个对象都有一个constructor属性,它引用了初始化该对象的构造函数,常用于判断未知对象的类型。
console.log((2).constructor === Number);		     // true
console.log((true).constructor === Boolean);		// true
console.log(('str').constructor === String);		// true
console.log(([]).constructor === Array);		   // true
console.log((function() {}).constructor === Function);		// true
console.log(({}).constructor === Object);		  // true
  • Object.prototype.toString.call():使用 Object 对象的原型方法 toString ,使用 call 进行狸猫换太子。
var a = Object.prototype.toString;
 
console.log(a.call(2));		// "[object Number]" 
console.log(a.call(true));		// "[object Boolean]"		
console.log(a.call('str'));		// "[object String]"
console.log(a.call([]));		// "[object Array]"
console.log(a.call(function(){}));		// "[object Function]"
console.log(a.call({}));		// "[object Object]"
console.log(a.call(undefined));		// "[object Undefined]"
console.log(a.call(null));		// "[object Null]"

参考:详情查看!!!(链接 可点击)

6. == 和 === 的不同

=== 是严格意义上的相等,会比较两边的数据类型和值大小

  • 类型不同返回 false
  • 数据类型相同,但值大小不同,返回 false

== 是非严格意义上的相等

  • 两边类型相同,比较大小
  • 两边类型不同,根据下方再进一步比较。

Null == Undefined ->true
String == Number -> 先将String转为Number,在比较大小
Boolean == Number -> 先将Boolean转为Number,在进行比较
Object == String,Number,Symbol -> Object 转化为原始类型

7. 数组方法有哪些,参数?

  1. cancat() 方法用于合并两个或多个数组。 (此方法不会更改现有数组,而是返回一个新数组)。
  2. find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
  3. findIndex() 方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回 -1。
  4. includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。
  5. indexOf() 方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回 -1。(通常用它判断数组中是否存在这个元素)
  6. join() 方法将一个数组(或一个 类数组对象)的所有元素拼接成一个字符串并返回这个字符串。(如果数组只有一个项,那么将返回改项而不使用分隔符。)
  7. pop() 方法从数组中删除最后一个元素,并返回该元素的值。(此方法可用于更改数组的长度)
  8. push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。
  9. shift() 方法从数组中删除第一个元素,并返回该元素的值。(此方法用于更改数组的长度)
  10. unshift() 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法用于修改原有数组)
  11. splice() 方法通过删除 / 替换现有元素 / 原地添加新的元素来修改数组,并以数组形式返回被修改的内容。(此方法会改变原数组)
  12. reverse() 方法将数组中元素的位置颠倒(翻转数组),并返回该数组。(该方法会改变原数组)
  13. sort() 方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是将元素转换为字符串,然后比较它们的 UTF-16 代码单元值序列时构建的。

7.1 数组的循环方法有哪几种?分别有什么作用?

  1. every() 方法测试一个数组内的所有元素是否能通过某个指定函数的测试。它返回一个布尔值。
  2. filter() 方法创建一个新数组,其包含通过所提供函数实现的测试的所有元素。
  3. forEach() 方法对数组的每个元素执行一次提供的函数。(遍历)
  4. some() 方法测试是否至少有一个元素可以通过被提供的函数方法。该方法返回一个 Boolean 类型的值。

8. 字符串方法有哪些,参数?

  1. charAt() 方法从一个字符串中返回指定的字符
  2. concat() 方法将一个或多个字符串与原字符串连接合并,形成一个新的字符串并返回。
  3. includes() 方法用于判断一个字符串是否包含在另一个字符串中,根据情况返回 true 或 false。
  4. indexOf() 方法返回调用它的 String 对象中第一次出现的指定值的索引,从 fromIndex 处进行搜索。如果未找到该值,则返回 -1.
  5. match() 方法检索返回一个字符串匹配正则表达式的结果。
  6. padStart() 方法用另一个字符串填充当前字符串(重复,如果需要的话),以便产生的字符串达到给定的长度。填充从当前字符串的开始(左侧)应用。(常用语时间补0)
  7. replace() 方法返回一个由替换值(replacement)替换一些或所有匹配的模式(pattern)后的新字符串。模式可以是一个字符串或一个正则表达式,替换值可以是一个字符串或一个每次匹配都要调用的回调函数。(原字符串不会改变)
  8. slice() 方法提取某个字符串的一部分,并返回一个新的字符串,且不会改动原字符串。
  9. split() 方法指定的分隔符字符串将一个String 对象分割成字符串数组,以将字符串分割为子字符串,以确定每个拆分的位置。
  10. substr() 方法返回一个字符串中从指定位置开始到指定字符串的字符(截取)。
  11. trim() 方法会从一个字符串的两端删除空白字符。在这个上下文中的空白字符是所有的空白字符
    (space, tab, no-break space 等) 以及所有行终止符字符(如 LF,CR)。

9. 字符串拼接有哪些方法?

10. new 一个实例对象然后发生了什么?(不记得具体问题。。)

  1. 创建一个新对象
  2. 使新对象的__proto__指向原函数的prototype
  3. 改变this指向(指向新的obj)并执行该函数,执行结果保存起来作为result
  4. 判断执行函数的结果是不是nullUndefined,如果是则返回之前的新对象,如果不是则返回result

11. 如何用 JS 实现继承?

12. 事件代理/委托?

详情点击1
2
3

13. 防抖?

14. diff算法

15. ElementUI 布局。

16. 作用域,作用域链

作用域: 规定变量和函数可使用范围称为作用域
作用域链: 每个函数都有一个作用域链,查找变量或函数时,需要从局部作用域全局作用域依次查找,这些作用域的集合称为作用域链。

17. 对同步和异步的理解 / JS的执行机制是怎样的?

  • js 是一个单线程异步非阻塞 I/O 模型event loop事件循环的执行机制。
  • 所有任务分为两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。
  • 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。
  • 异步任务指的是,不进入主线程、而进入“任务队列”(task queue)的任务,只有“任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

18. data 为什么是函数?

  1. vue 中组件是用来复用的,为了防止data复用,将其定义为函数。
  2. vue 组件中的 data 数据都应该是相互隔离互不影响的,组件每复用一次,data数据就应该被复制一次,之后,当某一处复用的地方组件内data数据改变时,其他复用地方组件的data数据不受影响,就需要通过data函数返回一个对象作为组件的状态。
  3. 当我们将组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data拥有自己的作用域,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。
  4. 当我们组件的date单纯的写成对象形式,这些实例的是同一个构造函数,由于javascript的特性所导致,Object 是引用数据类型,里面保存的是内存地址,单纯的写成对象形式,所有的组件实例共用了一个data,就会造成一个变了全都会变的结果。

19. watch 和 computed 的区别

computed 计算属性 就是为了简化 template 里面模板字符串的计算复杂度、防止模板太过冗余。它具有 缓存特性
computed 用于监控自己定义的变量,该变量不在 data 里面声明,直接在 computed 里面定义,然后就可以在页面上进行双向绑定展示出结果或者用作其他处理;

watch 主要用于监控 vue 实例的变化,它监控的变量当然必须在 data 里面声明才可以,它可以监控一个变量,也可以是一个对象,一般用于监控路由、input 输入框值得特殊处理等等,它比较适合的场景是一个数据影响多个数据,它不具缓存性。

  • watch:监测的是属性值,只要属性值发生变化,其都会触发执行回调函数来执行一系列操作。
  • computed:监测的是依赖值,依赖值不变的情况下其会直接读取缓存进行复用,变化的情况下才会重新计算。

除此之外,重要的区别:计算属性不能执行异步任务,必须同步执行。也就是说计算属性不能向服务器请求或者执行异步任务。如果遇到异步任务,就交给侦听属性。watch 也可以检测 computed 属性。

20. 怎么缓存整个页面?

21. this 指向问题

this 取什么值是在函数执行的时候确认的,不是在函数定义的时候确定的。

  1. 普通函数中的 this 指向 Window
  2. 定时器中的 this 指向 window
  3. 自调用函数中的 this 指向 window
  4. 箭头函数没有 this,它的 this 指向取决于 外部环境(取上级作用域的值)
  5. 事件中的 this 指向 事件的调用者
  6. 构造函数中的 this 和原型对象中的 this,都是指向 构造函数 new 出来的实例对象
  7. 类 class 中的this 指向 由 constructor 构造器 new 出来的实例对象
  8. 在 class 的方法中调用,返回对象本身
  9. 作为 对象方法 被调用,返回对象本身
  10. 使用 callapplybind传入什么绑定什么

22. null == undefined 为什么相等? null === undefined?

结果:

null == undefined    // true   
null === undefined   // false

原因:

  • ECMAScript规范里规定了在 == 两端的变量类型不同时的判断规则,其中有一条规则是 当 == 两端是 null 和 undefined 时返回 true
  • 而对于 === ,由于 null 和 undefined 是JS中两种不同的类型,自然返回 false

参考:详情点击这里!!!

23. 事件轮询 / 事件循环(Event loop 的机制)

23.1 首先要知道 event loop 是什么?

Event loop 即 事件循环,是指 浏览器 或 Node 的一种解决 javaScript 单线程运行时不会阻塞的一种机制。(可以说是 异步回调的实现原理)

Event loop 执行过程:
在这里插入图片描述

  1. 同步代码,一行一行放在call stack调用栈)执行
  2. 遇到异步,先记录下(放在Web APIs处理定时或异步的API)中),等待时机(定时、网络请求等)
  3. 时机到了,就移动到callback queue回调函数队列
  4. 如果call stack为空(即同步代码执行完了)Event loop事件轮询)开始工作
  5. 轮询查找callback queue,如有就移动到call stack中
  6. 然后继续轮询查找(像永动机一样)

24. vue 的生命周期

vue 的生命周期就是 vue实例创建销毁的过程
也就是从开始创建初始化数据编译模板挂载 DOM --> 渲染更新 -->渲染销毁等一系列过程。
vue 的生命周期常见的主要分为 4 大阶段8 大钩子函数
一、创建前/后
beforeCreate 生命周期函数执行的时候 ,data 和 method 还没有初始化
created 生命周期函数执行的时候,data 和 method 已经初始化完成
二、渲染前/后
beforeMount 生命周期函数执行的时候,已经编译好了模板字符串,但还没有真正渲染到页面中去
mounted 生命周期函数执行的时候后,已经渲染完毕,可以看到页面
三、数据更新前/后
beforeUpdate 生命周期函数执行的时候,已经可以拿到最新的数据,但还没渲染到视图中去。
updated 生命周期函数执行的时候,已经把更新后的数据渲染到到视图中去了。
四、销毁前/后
beforeDestroy 生命周期函数执行的时候,实例进入准备销毁的阶段,此时 data、methods、指令等还是可用状态。
destroyed 怎么周期函数执行的时候,实例已经完成销毁,此时 data、methods、指令等都不可用。

常用生命周期函数:

  • keep-alive 主要用于保留组件状态或者避免重新渲染。
    -activated只有在 keep-alive 组件激活时调用。
  • deactivated 只有在 keep-alive 组件停用时调用。
  • errorCapured 当捕获一个来自子组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

25. 对 vuex 的了解

  1. 首先 vuex 的出现是为了解决 web 组件化开发的过程中,各组件之间传值的复杂和混乱的问题
  2. 将我们在多个组件中需要共享的数据到store中,
  3. 获取格式化数据需要使用getters
  4. 改变store中的数据,使用mutation,但是只能包含同步的操作,在具体组件里面调用的方式
    this.$store.commit(‘xxxx’)
  5. Action也是改变store中的数据,不过是提交的mutation,并且可以包含异步操作,在组件中的调
    用方式 this.$store.dispatch(‘xxx’) ; 在actions里面使用的commit(‘调用mutation’)

细说一下8 ~

  • store(仓库) 是 Vuex 应用的核心。相当于是一个容器,里面包含着应用中大部分的状态(state)
  • state 相当于 vue 的 data 属性,用来保存所有组件的公共数据
  • getter 相当于 vue 的计算属性,监测依赖值的改变,具有缓存性,只有依赖值改变才会重新计算;
  • mutation 相当于 vue 的方法属性,里面保存着更改数据的回调函数,该函数名官方规定叫 type, 第一个参数是 state, 第二参数是payload, 也就是自定义的参数。mutation 必须是同步函数。mutations 对象里的方法需要使用 store.commit 调用;
  • action 跟mutation一样,但是大多用于实现异步函数,提交的是 mutation 而不是直接变更状态。action 可以包含任意异步操作。actions 对象里的方法需要使用 store.dispatch 调用。Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
  • modules装载一个或多个store状态模块,每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。

26. 对 ES6 的了解

ES6 是 2015年推出的一个新的版本,这个版本相对于ES5的语法做了很多优化,例如:

  • 新增了letconst。let 和 const具有块级作用域,不存在变量提升的问题。
  • 新增了箭头函数,简化了定义函数的写法,同时可以巧用箭头函数的this(注意箭头函数本身没有 this,它的this取决于外部的环境)
  • 新增了 promise 解决了回调地狱的问题
  • 新增了模块化、利用importexport 来实现导入、导出
  • 新增了解构赋值,ES6 允许按照一定模式,从数组和对象中题取值,对变量进行赋值,称为解构(Destructuring)
  • 新增了class类的概念,类似于对象

27. tcp的三次握手

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值