面试题分享

161 阅读14分钟

1.闭包

什么是闭包:函数嵌套函数,内部函数被return,内部函数能够访问到外部函数的变量。
优点:可以隔离作用域,避免全局污染。
缺点:闭包驻留内存,长期下去内存得不到释放。
如何释放内存:将暴露在外部的闭包变量设置为null。

sequenceDiagram
Alice->>John: Hello John, how are you?
John-->>Alice: Great!
Alice-)John: See you later!
 let obj={
        name:'张三',
        func:function(){
            return this.name
        }
    }
    obj.func();
    obj=null;

this指向

sequenceDiagram
Alice->>John: Hello John, how are you?
John-->>Alice: Great!
Alice-)John: See you later!
   function fn1(){
       console.log(this);
   }
   fn1()//window
   window.fn1()//window

   let obj={
       name:'张三',
       func:function(){
           return this.name
       }
   }
    obj.func();//obj

    <div id="box">啦啦啦</div>
    let dom=document.getElementById('box');
    dom.addEventListener('click',function(){
        console.log(this);//dom
    })

    setTimeout(() => {
        console.log(this);//window
    });
    setInterval(() => {
        console.log(this);//window
    });

    var num=1;
    var obj={
        num:2,
        fn:function(){
            console.log(this.num);//2
        }
    }
    obj.fn()

    var num=1;
    var obj={
        num:2,
        fn:()=>{
            console.log(this.num);//1
        }
    }
    obj.fn()

箭头函数的特点

没有构造函数,不能使用new,箭头函数没有this指向,this指向父级,箭头函数不能使用arguments,箭头函数没有原型。
特点:箭头函数使表达更加简洁,隐式返回值。

    // 普通函数
    const isEven=function(a){
        return a%2===0;
    }
    const square=function(n){
        return n*n;
    }
    // 箭头函数
    const isEven=n=>a%2===0;
    const square=n=>n*n;

    // 箭头函数用于简化回调函数
    // 普通函数写法
    [1,2,3].map(function(x){
        return x*x
    });
    // 箭头函数写法
    [1,2,3].map(x=>x*x);//[1,4,9]

var let const 区别

var的变量会挂载到window,let const不会
    var a=1;
    console.log(a);//1
    console.log(window.a);//1

    let b=2;
    console.log(b);//2
    console.log(window.b);//undefined

    const c=3;
    console.log(c);//3
    console.log(window.c);//undefined
var可以重复声明,let const 不可以,声明即报错
    var a=1;
    var a=100;
    console.log(a);//100

    let b=1;
    let b=100;
    console.log(b);//Uncaught SyntaxError: Identifier 'b' has already been declared
    
    const c=1;
    const c=100;
    console.log(c);//Uncaught SyntaxError: Identifier 'c' has already been declared
var有变量提升,let const 没有
    console.log(a);//undefined
    var a=100;

    console.log(b);//Uncaught ReferenceError: Cannot access 'b' before initialization
    let b=100;
    
    console.log(c);//Uncaught ReferenceError: Cannot access 'c' before initialization
    const c=100;
let const 生成块级作用域
   if (1) {
       var a=100;
       let b=10;
       console.log(b);//10
   }
   function fn(){
       return{
           a:100,
       }
   }
   fn()
   console.log(a);//100
   console.log(b);//Uncaught ReferenceError: b is not defined
let const 会形成一个暂时性死区
    var a=100;
    function func(){
        console.log(a);//100
    }
    func()
    var b=200;
    function fn(){
        console.log(b);//Uncaught ReferenceError: Cannot access 'b' before initialization
        let b=20;
    }
    fn()//暂时性死区
const定义常量
  1. 一旦声明必须赋值。
  2. 声明过后不可修改。
  3. 如果声明的为复合类型数据,可修改其属性。
    const a=10;
    a=100;
    console.log(a);//报错 Uncaught TypeError: Assignment to constant variable.

    const arr=[];
    arr=[1,2,3];
    console.log(arr);//报错 改变了内存指针的指向 Uncaught TypeError: Assignment to constant variable.

    const obj={};
    obj={name:"张三"};
    console.log(obj);//报错 改变了内存指针的指向 Uncaught TypeError: Assignment to constant variable.

    const obj1={};
    obj1.name="张三";
    console.log(obj1);//{name: '张三'} 不报错 指针没有被改变,只改变了内存中的属性

js内存存储机制

基本数据类型:number,string,boolean,undefined,null,symbol,bigInt.
引用类型:object,function,array.
基本数据类型放在栈内存里面。
引用数据类型有一个占位牌放在栈里,数据放在堆内存里,占位牌有一个指针指向队内存里。
为什么const可以对原引用数据类型进行修改,不能直接重新赋值一个新对象?
第一种指针未发生变化,第二种指针指向新的内存地址,所以报错

14638845-226a-4d8a-ad54-8a7ac765be7b.png

js的值传递和引用传递

    function fun(i){
        console.log(i);//20
        i=18;
        console.log(i);//18 i改变不会影响外面的age
    }
    let age=20;
    fun(age);
    console.log(age);//20

重绘-回流

重绘

当render tree中的一些元素需要更新属性,重绘只是影响元素的外观、风格,不会影响布局,比如,background-color,就称做重绘。

回流

当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。就称做回流。每个页面至少需要一次回流,就是在页面第一次加载的时候,这时候是一定会发生回流的,因为要构建render tree。在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程成为重绘。

区别

回流必将引起重绘,而重绘不一定会引起回流。比如:只有颜色改变的时候就只会发生重绘而不会引起回流
当页面布局和几何属性改变时就需要回流
比如:添加或者删除可见的DOM元素,元素位置改变,元素尺寸改变——边距、填充、边框、宽度和高度,内容改变。

new都干了什么

  • 创建一个新的对象obj
  • 将对象与构建函数通过原型链连接起来
  • 将构建函数中的this绑定到新建的对象obj
  • 根据构建函数返回类型作判断,如果是原始值则被忽略,如果是返回对象,需要正常处理

js如何判断一个数组

js如何判断一个数组.png

href与src的区别

href与src的区别.png

ajax原理或交互过程

ajax的原理或交互过程.png

SEO搜索引擎优化

是一种方式,利用搜索引擎的规则提高网站有关搜索引擎内的自然排名。目的是让其在行行业占领领先地位,获得品牌收益。是一种网站经营者的一种商业行为,将自己或公司的排名前提。

http状态码

http状态码.png

盒模型

盒模型IE和W3C.png

媒体查询如何使用

Media Queries能在不同的条件下使用不同的样式,使页面在不同在终端设备下达到不同的渲染效果。使用媒体查询必须使用@media开头。

not关键词

使用关键词“not”是用来排除某种制定的媒体类型,也就是用来排除符合表达式的设备。

only关键词

only用来指定某种特定的媒体类型,可以用来排除不支持媒体查询的浏览器。

css让元素看不见的方法

display:none;

opacity:0;

visability:hidden;

scale(0);

脱离文档流

z-index:-1;

常见的设计模式有哪些

单例模式:保证整个系统中一个类只有一个对象的实例,实现这种功能的方式就叫单例模式。

观察者模式:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得通知并被自动更新。

装饰者模式:动态的给对象添加一些额外的职责,类似钢铁侠可以组装不同武器。

适配器模式:将两种完全不同的事物联系到一起,就像现实生活中的变压器。

工厂模式:工厂模式是一种用来创建对象的设计模式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

代理模式(proxy):为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

谈谈对promise的理解

Promise 是异步编程的一种解决方案:从语法上讲,promise是一个对象

promise有三种状态: pending(等待态),resolved(成功态),rejected(失败态);

状态一旦改变,就不会再变。创造promise实例后,它会立即执行。

1、Promise是一个构造函数,可以通过 new Promise()得到一个 Promise 的实例;

2、在 Promise 上,有两个函数,分别叫做 resolve(成功之后的回调函数) 和 reject(失败之后的回调函数);

3、在 Promise 构造函数的 Prototype 属性上,有一个 .then() 方法,也就说,只要是 Promise 构造函数创建的实例,都可以访问到这个.then() 方法 ;

4、Promise 表示一个 异步操作;每当我们 new 一个 Promise 的实例,这个实例,就表示一个具体的异步操作;

5.、Promise 只能有两种状态:

状态1: 异步执行成功了,需要在内部调用 成功的回调函数 resolve 把结果返回给调用者;

状态2: 异步执行失败了,需要在内部调用 失败的回调函数 reject 把结果返回给调用者;

6、 Promise 是一个异步操作,所以,内部拿到 操作的结果后,无法使用 return 把操作的结果返回给调用者;

 这时候,只能使用回调函数的形式,来将成功 或 失败的结果,返回给调用者;

7、我们可以在 new 出来的 Promise 实例上,调用 .then() 方法,【预先】为 这个 Promise 异步操作,指定成功(resolve) 和 失败(reject) 回调函数;

map与forEach的区别

forEach()方法不会返回执行结果,而是undefined。也就是说,forEach()会修改原来的数组。而map()方法会得到一个新的数组并返回。

防抖-节流

防抖:在事件被触发n秒后再执行回调函数,如果在这n秒内又被触发,则重新计时。

节流:规定一个时间,在这个时间内,只能有一次触发事件的回调函数执行,如果在同一个时间内某事件被触发多次,只有一次能生效。

浏览器的缓存策略

浏览器的缓存过程如下

  • 开始加载,域名解析,DNS缓存
  • 本地缓存(memory缓存)
  • Http缓存(强缓存和协商缓存)
  • 服务端缓存(cdn缓存)

强缓存和协商缓存;

强缓存包括Expires和Cache-Control,主要是在过期策略生效时应用的缓存。

弱缓存包括Last-Modified和ETag,是在协商策略后应用的缓存。

强弱缓存之间的主要区别: 在于获取资源时是否会发送请求。
点击了解浏览器的缓存策略

清除浮动的方法

1、使用伪元素来清除浮动(:after,注意:作用于浮动元素的父亲)

  • 原理:IE8以上和非IE浏览器才支持:after,zoom(IE专有属性)可解决ie6,ie7浮动问题
  • 优点:浏览器支持好,不容易出现怪问题(目前:大型网站都有使用,如:腾迅,网易,新浪等等)
  • 缺点:代码多,不容易理解原理。

2、添加新的元素对其应用 clear:both

  • 原理:添加一个空元素,利用css提供的clear:both清除浮动,让父级div能自动获取到高度。
  • 优点:简单,代码少,浏览器支持好,不容易出现怪问题。
  • 缺点:如果页面浮动布局多,就要增加很多空页面标签,造成结构的混乱。

3、父级div定义overflow:hidden

  • 原理:使用overflow:hidden时,浏览器会自动检查浮动区域的高度。
  • 优点:简单,代码少,浏览器支持好。
  • 缺点:不能和position配合使用,因为超出的尺寸的会被隐藏。

4、父级div定义overflow:auto

  • 原理:使用overflow:auto时,浏览器会自动检查浮动区域的高度
  • 优点:简单,代码少,浏览器支持好
  • 缺点:内部宽高超过父级div时,会出现滚动条。

computed和watch的区别

computed计算属性

computed是用来计算出来一个值的,这个值调用的时候不需要加括号,会根据依赖进行缓存,依赖不变,computed的值不会重新计算。

支持缓存,只有依赖数据发生改变,才会重新进行计算。

不支持异步,当computed内有异步操作时无效,无法监听数据的变化

watch是监听

watch是来监听的,有2个选项,

immediate:表示是否要在第一次渲染的时候执行这个函数

deep:如果我们监听一个对象,那么我们是否要看这个对象里面属性的变化

如果某个属性变化了,就去执行一个函数。

不支持缓存,数据变,直接会触发相应的操作;

watch支持异步;

vue3常用的api

setup、ref、reactive、userStore......
vue3常用api

js创建对象有哪些方式或者js常见的创建方式

js常用的几种创建对象的方式有:

1、{}

2、new Object()

3、使用字面量

4、工厂模式

5、构造函数模式(constructor)

6、原型模式(prototype)

7、构造函数+原型模式
常用创建对象方式

阻止事件冒泡的方式

1.event.stopPropagation()方法

$('.btn').click(function (even) {
    even.stopPropagation(); 
    alert('按钮被点击了');
})

这个方法会阻止冒泡事件,但是不会阻止默认事件
2、return false

$('.btn').click(function (even) {
    alert('按钮被点击了');
    return false; 
})

既阻止冒泡事件也阻止默认事件
拓展:

还有一个方法,虽然不能阻止冒泡,但是可以阻止默认事件

event.preventDefault()

http请求方法有哪些

http1.0定义了三种请求: get、head、post、

http1.1新增了六种请求方法:options、 put、patch、 delete、trace、connect、

http请求方式.png

rem和em区别

em相对于父元素,rem相对于根元素。

em:是相对于父元素的字体大小来说的。

rem:是相对于html元素的字体大小来说的,rem单位的优点就是可以通过修改html里面的文字大小也就是根元素的大小来改变页面中的元素大小。

v-for与v-if的区别

v-for比v-if优先级高,就说明v-if 会重复运行在每个v-for 循环中。所以,不推荐v-if和v-for同时使用。

number和parseInt区别

1.parseInt():

  parseInt(string,radix):将字符串 (String)类型转为整数类型。,返回的是整数;

   string:待被解析的字符串;

   radix:表示要解析转换的进制

当遇到数字后带有字符串,则只返回前面的数字(例parseInt(123mgn)=123),如果字符串的第一个字符不能被转换为数字,那么 parseFloat() 会返回 NaN。

2.Number()

number:把对象 (Object)的值转换为数字

  如果对象的值无法转换为数字,那么 Number() 函数返回 NaN。

  如果参数是 Date 对象,Number() 返回从 1970 年 1 月 1 日至今的毫秒数。

axios的封装有哪些

axios的封装有哪些.png
axios封装

vueRouter的原理

vue-router通过hash与History interface两种方式实现前端路由。

 1.默认 hash

 2. history。如果浏览器不支持 history 新特性,则采用 hash

 3. 如果不在浏览器环境下,就采用 abstract(Node环境下)

js垃圾回收机制

标记清除

原理:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。

  1. 垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记。
  2. 去掉环境中的变量以及被环境中的变量引用的变量的标记。
  3. 再被加上标记的会被视为准备删除的变量。
  4. 垃圾回收器完成内存清除工作,销毁那些带标记的值并回收他们所占用的内存空间。

引用计数

原理:跟踪记录每个值被引用的次数。

  1. 声明了一个变量并将一个引用类型的值赋值给这个变量,这个引用类型值的引用次数就是1。
  2. 同一个值又被赋值给另一个变量,这个引用类型值的引用次数加1。
  3. 当包含这个引用类型值的变量又被赋值成另一个值了,那么这个引用类型值的引用次数减1。
  4. 当引用次数变成0时,说明没办法访问这个值了。

async和await

async 和 await 是用来处理异步的。

async 是一个修饰符,async 定义的函数会默认的返回一个Promise对象resolve的值,对async函数可以直接进行then操作,返回的值即为then方法的传入函数。

await 也是一个修饰符,

await 关键字 只能放在 async 函数内部, await关键字的作用 就是获取 Promise中返回的内容, 获取的是Promise函数中resolve或者reject的值

// 如果await 后面并不是一个Promise的返回值,则会按照同步程序返回值处理。

就分享到这里啦~

自己打败自己是最可悲的失败,自己战胜自己是最可贵的胜利。加油!!!