• 二阶段面试题——JavaScript


    ■ 符号说明

    💘 课题

    🌟 常见重要

    🌛 需要有印象的

    💘 Week1

    🌟 说出JS数据类型有哪些

    原始类型/基本类型:null、undefined、boolean、number、string、symbol、bigint

    对象类型/引用类型/复杂/复合类型:

    可调用/执行对象「函数」:function
    标准普通对象:object
    标准特殊对象:Array、Date、Math、RegExp、Error……
    非标准特殊对象:Number、String、Boolean……
    
    • 1
    • 2
    • 3
    • 4

    🌟 JS引用类型object、array还有哪些

    可调用/执行对象「函数」:function
    标准特殊对象:Array、Date、Math、RegExp、Error……
    非标准特殊对象:Number、String、Boolean……
    
    • 1
    • 2
    • 3

    🌟 如何把数据强制转换为数值型

    说明:面试概率低、工作概率高

    语法:parseInt、parseFloat、Number

    🌛 说出数据转换为布尔型的结果

    null、undefined、0、NaN、空字符串结果是false、其他都是true

    🌛 说出数据转换为字符串型的结果

    都字符串

    String(内容)、内容.toString()

    🌛 说出数据转换为数值型的结果

    Number(数据)

    数据 结果
    null 0
    undefined NaN
    true/false 1/0
    123/NaN 123/NaN
    ‘’/‘123’/‘123a’ 0/123/NaN

    🌛 说出下述隐式转换的结果

    var result = 100 + true + 21.2 + null + undefined + “Tencent” + [] + null + 9 + false;

    [] + [] // “”

    [] + {} // “[object object]”

    {} + [] // 0 对于编译器而言,代码块不会返回任何的值, 接着+[]就变成了一个强制转number的过程

    true+true+true===3 // true

    true-true // 0

    true==1 // true

    true===1 // false

    9+“1” // 91

    91-“1” // 90

    []==0 // true Number([]) 0

    🌛 null 和 undefined 有什么区别?

    undefined 表示未定义,新定义的变量没有赋值就是undefined

    null表示清空,当一个变量不用的时候,除了等待网页关闭销毁,也可以把它赋值为null。此时游览器会进行一个回收也就是清空内存。

    了解1

    typeof(null)会是一个object。最初这么设计的原因为:通常用作一个空引用一个空对象的预期,就像一个占位符。typeof的这种行为已经被确认为一个错误,虽然提出了修正,出于后兼容的目的,这一点已经保持不变。
    
    • 1

    了解2

    null == undefined    true
    null === undefined   false
    
    • 1
    • 2

    🌛 为什么 0.1 + 0.2 !== 0.3? 你如何解决这个问题?

    因为 0.1 这样的数值用二进制表示你就会发现无法整除,

    最后算下来会是0.0001100110011001…由于存储空间有限,位数是无限的,只能取近似。

    代码:0.1 + 0.2 == 0.3 // false

    代码:0.625 + 0.625 == 1.25 // true

    进制转换规则:https://www.runoob.com/w3cnote/decimal-decimals-are-converted-to-binary-fractions.html

    十进制整数 -> 转二进制

    举例:(5).toString(2) // 结果 101
    转换:除2反向取余
    2| 5    --- 余1
     ------
    2| 2    --- 余0
     ------
       1    
       
    举例:(13).toString(2) // 结果 1101
    转换:除2反向取余
    2| 13    --- 余1
     ------
    2| 6     --- 余0
     ------
    2| 3     --- 余1
     ------
       1    
       
    核对:https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fwww.pianshen.com%2Fimages%2F732%2Faf802c5be33b4934e6a6fec52a208734.png&refer=http%3A%2F%2Fwww.pianshen.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1642634303&t=293eccde3cc561a3ed2d38f8cf57eea9
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    十进制小数 -> 转二进制

    举例:(0.625).toString(2) // 结果 0.101
    转换:乘2正向取整
    0.625*2=1.25======取出整数部分1 
    0.25*2=0.5========取出整数部分0 
    0.5*2=1==========取出整数部分1 
    
    举例:(0.7).toString(2)  // 结果 0.101100110011001100110011 0011 ...
    0.7*2=1.4========取出整数部分1 
    0.4*2=0.8========取出整数部分0 
    0.8*2=1.6========取出整数部分1 
    0.6*2=1.2========取出整数部分1 
    0.2*2=0.4========取出整数部分0  
    0.4*2=0.8========取出整数部分0 
    0.8*2=1.6========取出整数部分1 
    0.6*2=1.2========取出整数部分1 
    0.2*2=0.4========取出整数部分0
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    🌟 实战购物车小数计算精度丢失如何解决?

    推荐解决: 浮点数转化成整数

    实战使用:购物车结算时,商品价格(33.01)-优惠券价格(5),本应该是28.01,但是实际的结果是28.009999999999998

    33.01 - 5 = 28.009999999999998
    
    (33.01*100 - 5*100) / 100 = 28.01
    
    • 1
    • 2
    • 3

    es6 解决办法

    es6 提供了 Number.EPSILON,这个值等于 2^-52 ,这个值非常非常小,在底层计算机已经帮我们运算好,并且无限接近 0,但不等于 0,这个时候我们只要判断误差值在这个范围内就可以说明是相等的。
    
    function numbersequal(a,b){
        return Math.abs(a-b)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    四舍五入

    采用四舍五入方法,取了一个 10 位小数

    function numTofixed(num) {
        if (typeof num == 'number') {
            num = parseFloat(num.toFixed(10))
        }
        return num;
    }
    
    numTofixed(0.1 + 0.2);
    // 0.3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用第三方库

    math.js
    bignumber.js
    ....
    
    • 1
    • 2
    • 3

    💘 Week2

    • day1

    🌟 说出变量在内存中的分配

    栈:存 原始类型【名字】&【数据】、对象类型的【名字】&【堆地址】

    堆:对象类型数据

    🌟 说出变量赋值内存分配

    原始类型:变量赋值,栈开辟内存直接存数据 -> 数据互补影响

    对象类型:变量赋值,栈开辟内存,存放堆地址 -> 数据相互影响

    切记切记切记:上课讲的形参也会出现传值、传地址问题

    var num = 100      
    function fn(n) {  
      // var 形参 = 实参
      // var n = num也就是100   原始类型 传值 不影响
      n = 200		 
      console.log(n)   // 打印: 200
    }
    fn(num)             
    console.log(num)   // 打印: 100
    
    // --------------------------
    
    var obj = { name: 'Jack' }    
    
    function fn(o) {	 	  
      // var 形参 = 实参
      // var o  = obj    对象类型赋值 传地址  相互影响
      o.name = 'Rose'	  	//    
      console.log(o.name) //  打印:Rose
    }
    fn(obj)				  
    console.log(obj.name) //  打印:Rose
    
    栈   		   						  								  	 堆
    obj:地址1	  																  地址1:{ name: 'Jack改成Rose' }  
    fn函数里面的o变量:地址1 函数调用完毕o变量就销毁了 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • day2

    🌟 判断是否是数组

    方法1:通过语法 Array.isArray()

    方法2:instanceof

    方法3:原型链(constructor)

    Array.isArray([1, 2 ,3])     	 // true
    [1, 2 ,3] instanceof Array 	   // true
    [1, 2 ,3].constructor === Array // true
    
    Array.isArray('aa')     	 // false
    'aa' instanceof Array 	   // false
    'aa'.constructor === Array // false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    🌛 如何交换两个变量的值

    • 临时变量法

      var a = 1
      var b = 2;
      var temp = a
      a = b
      b = temp

    • 加减法

      var a = 1
      var b = 2;
      a = a+b // a = 1+2 = 3
      b = a-b // b = 3-2 = 1
      a = a-b // a = 3-1 = 2

    • 解构赋值法 week3

      var a = 1
      var b = 2;

      [a, b] = [b, a]

    • 数组法

      var a = 1
      var b = 2
      a = [a, b]
      b = a[0]
      a = a[1]

    • 对象法

      var a = 1
      var b = 2
      a = { a: b, b: a }
      b = a.b
      a = a.a

    • 等等太多了

    🌟 说出数组有哪些方法

    ·数据操作:shift/unshift/pop/push

    遍历数据: forEach/map/filter/find/findIndex

    工作常用:concat/join/indexOf/includes

    学习常用:reverse/splice

    了解:sort

    🌟 说出数组哪些方法会改变原数据

    数据操作:shift/unshift/pop/push

    学习常用:reverse/splice

    了解:sort

    🌟 如何实现数组去重

    方法1:通过es6新增的Set数据结构、和展开运算符去重 […new Set(重复数组)] week3

    方法2:通过filter配合indexOf实现数组去重

    方法3:定义空数组,通过forEach遍历重复的数组,通过indexOf判断当前值是否在数组中,不在就push

    方法4:定义空数组,通过forEach遍历重复的数组,通过includes判断当前值是否在数组中,不在就push

    方法5:利用对象的属性去重

    方法6:…

    // 方法1:通过es6新增的Set数据结构结果     [...new Set(重复数组)]
    var arr = [1,2,3,2,3]
    console.log([...new Set(arr)])
    
    
    // 方法2:通过filter配合indexOf实现数组去重
    var arr = [1,2,3,2,3]
    var newarr = arr.filter(function(item, i) {
        // i=0  item值是1  arr.indexOf(item)  返回0  真
        // i=1  item值是2  arr.indexOf(item)  返回1  真 
        // i=2  item值是3  arr.indexOf(item)  返回2  真
        // i=3  item值是2  arr.indexOf(item)  返回1  假
        // i=4  item值是3  arr.indexOf(item)  返回2  假
        return i === arr.indexOf(item);
    }) 
    console.log(newarr)
    
    
    // 方法3:定义空数组,通过forEach遍历重复的数组,通过indexOf判断当前值是否在数组中,不在就push
    var newarr = []
    var arr = [1,2,3,2,3]
    arr.forEach(function(item, i) {
        if (newarr.indexOf(item) === -1)
        {
            newarr.push(item)
        }
    })
    console.log(newarr)
    
    
    // 方法4:定义空数组,通过forEach遍历重复的数组,通过includes判断当前值是否在数组中,不在就push
    var newarr = []
    var arr = [1,2,3,2,3]
    arr.forEach(function(item, i) {
        if (!newarr.includes(item))
        {
            newarr.push(item)
        }
    })
    console.log(newarr)
    
    // 方法5:利用对象的属性去重
    var arr = [1,2,3,2,3]
    var newarr = []
    var obj = {}
    arr.forEach(function(item) {
    	if (!obj[item]) {
    		obj[item] = item // 出现记录
        newarr.push(item)
    	}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • day3

    🌟 说出字符串常用方法

    工作常用:数组、查找、替换、截取、大小、空格

    split、replace、substr、toUpperCase/toLowerCase、trim、slice

    学习:.length、lastIndexOf、repeat

    🌛 JS如何去空格

    说明: 通过 trim 去左右空格

    留心:中间不能去

    追问:JS如何去所有空格

    解决:通过2021年 ES12新增语法replaceAll来解决

    ’ a b c ‘.replaceAll(’ ', ‘’)

    解决:通过正则

    ’ a b c '.replace(/\s/g, ‘’)

    • day4&5

    🌛 伪数组

    长得像数组,能用少部分的属性 例如length 但是所有方法都不可以使用,在js中常见的伪数组有

    document.qsa、arguments等等

    🌟 谈谈你对this指向的理解

    面试: 调用当前方法的对象 也就是谁调用的打印的就是谁

    举例:

    function fn1() {} 
    fn1() // 最大全局变量window调用的
    
    标签对象.事件类型 = 处理函数  // 标签对象触发后调用的
    
    • 1
    • 2
    • 3
    • 4

    学习

    普通函数   window
    对象函数   对象本身
    事件函数   事件源
    定时器函数  window
    箭头函数   父function中的this  父没有function就是window
    自定义     call/apply/bind
    构造函数   this === 实例化对象 === 公共空间/原型对象上方法中的this 
    
    
    其他:事件、构造函数、公共空间/原型对象上方法-优先使用普通函数写法,当需要明确改变this指向的时候再换箭头函数,
    其他全不优先使用箭头函数。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    🌟 图片懒加载原理

    好处:减少HTTP请求

    原理:

    1、监控滚动条滚动
    2、获取总可视内容高度(可见视口高度+滚动条滚动高度)
    3、获取所有图片
    4、遍历步骤3(或这说:遍历伪数组)
    5、在步骤4中判断,图片.offsetTop <= 步骤2    成立-修改src属性为data-src、失败-不管
    6、节流防抖优化
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    留心:有时候图片高度获取怎么不到?

    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    🌟 性能优化:网站首屏加载过慢如何解决

    function lazyload() 
    {
        // 1 每次获取最新的 可见视口 + 滚动的高度
        // 2 获取所有图片
        // 3 遍历
        // 4 判断:当前图片的.offsetTop < 步骤1(可见视口 + 滚动的高度)
        // 不成立-不管
        // 成立-修改图片的src地址 改成真是的  
    
    
        // 1 每次获取最新的 可见视口 + 滚动的高度
        var temp1 = window.innerHeight || document.documentElement.clientHeight  // 兼容ie
        var temp2 = document.body.scrollTop || document.documentElement.scrollTop // 兼容doctype
        var maxShowHeight = temp1 + temp2
        // 2 获取所有图片
        var imgs = document.querySelectorAll('img')
        // 3 遍历
        imgs.forEach(function(item, index) { // item就是每一个图片标签对象
            // 4 判断:当前图片的.offsetTop < 步骤1(可见视口 + 滚动的高度)
            // 不成立-不管
            // 成立-修改图片的src地址 改成真是的  
            // console.log(item, item.offsetTop , maxShowHeight)
            if (item.offsetTop < maxShowHeight)
            {
                // item.src = item.src-real  切记非标签默认属性 不能直接点
                item.src = item.getAttribute('src-real')
            }
        })
    }
    
    // TODO: 待后续进一步优化
    // 首次
    lazyload() 
    // 后续
    // window.onscroll = lazyload()  错误 undefined
    window.onscroll = lazyload
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    💘 Week3

    🌛 谈谈你对事件流机制的理解

    术语:事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流

    学习:多个标签嵌套,事件触发-先检查当前标签,然后继续向上挨个检查祖先标签有没有事件 有就触发的现象就是事件流

    DOM事件流分为三个阶段,分别为:

    捕获阶段:事件从Document节点自上而下向目标节点传播的阶段;

    目标阶段:真正的目标节点正在处理事件的阶段;

    冒泡阶段:事件从目标节点自下而上向Document节点传播的阶段。

    🌛 谈谈你对事件委托的理解

    概念:利用事件冒泡机制处理指定一个事件处理程序,来管理某一类型的所有事件。

    事件委托的好处:

    • 利用冒泡的原理,将事件加到父级身上,这样只在内存中开辟一块空间,既节省资源又减少DOM操作,提高性能
    • 可以为动态添加的元素绑定事件

    🌛 正则

    匹配手机号:/^1\d{10}$/.test(数据)

    匹配邮箱:/^\w{2,20}@\w{2, 20}.(com|org|cn|edu)$/.test(数据)

    匹配中文:/1+$/.test(数据)

    去所有空格:str.replaceAll(’ ', ‘’) 或 str.replace(/\s/g, ‘’)

    购物车去非数字:str.replace(/\D/g, ‘’)

    🌟 es6新增语法

    https://github.com/tc39/proposals/blob/main/finished-proposals.md

    # 2015年 ES6
    
        修饰符:let、const
        解构赋值:let {键:变量名=默认值,...,键:变量名=默认值} = {键:值,....,键:值} !!!
        字符串相关扩展:模板字符串
        函数相关扩展:箭头函数!!!、函数形参默认值、rest参数 arguments
        对象相关扩展:对象简写!!!、链判断操作符 ?.  空判断操作符??
        数组相关扩展:find/findIndex/indexOf/includes
        新增原始类型:symbol、bigint  
        -----------
        //       重要      中等        中等       重要          重要
        其他新增:展开运算符、新增数据结构、循环forof、module模块化、class类等等
        
    # 2016年 ES7:Array.prototype.includes
    # 2017年 ES8:Async functions
    # 2018年 ES9:Promise.prototype.finally
    # 2019年 ES10
    # 2020年 ES11:String.prototype.matchAll、import()、BigInt、Promise.allSettled、
    # 2021年 ES12:String.prototype.replaceAll、Promise.any、
    # 2022年 ES13:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    🌟 es6常见问题汇总

    • 新增了哪些数据类型:symbol、bigInt

    • 新增的数据类型属于哪一类:原始类型

    • 数组如何去重:Set、filter+indexOf、forEach+indexOf、forEach+includes、对象

    • 新增数据类型有哪些分别有什么用

      Set数组去重
      Map对象的键不限于字符串

    🌟 let、const

    面试题1:let和const区别

    相同点-都是块级作用域/不能重复定义
    不同点-let修改/const不能修改
    
    • 1
    • 2

    面试题2:const真的不能修改吗

    原始类型:不可以
    对象类型:可以
    
    原理:const不可以修改栈里面的地址,但是可以修改堆里面的数据
    
    • 1
    • 2
    • 3
    • 4

    面试题3:暂时性死区

    let前面的区域就是暂时性死区,必须先定义再使用
    
    • 1

    面试题4:let和const如何选

    普遍用let、明确后期不改用const 例如Date、xhr、promise对象等
    
    const d = new Date() 
    
    • 1
    • 2
    • 3

    面试题5:var和let区别

    var 函数作用域   可以重复定义 可以修改
    let 块级作用域  不能重复定义 可以修改
    
    • 1
    • 2

    🌟 bind 和 call/apply 的区别

    fun.call(thisArg, param1, param2, ...)
    fun.apply(thisArg, [param1,param2,...])
    
    fun.bind(thisArg, param1, param2, ...)
    
    • 1
    • 2
    • 3
    • 4

    是否立刻执行

    • call/apply 改变了函数的 this 上下文后 马上 执行该函数。
    • bind 则是返回改变了上下文后的函数, 不执行该函数 。

    返回值的区别

    • call/apply 返回 fun 的执行结果。
    • bind 返回 fun 的拷贝,并指定了 fun 的 this 指向,保存了 fun 的参数。

    🌛 手写bind/call/apply 原理

    • call

    apply

    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    bind

    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    💘 Week4

    🌟 原型、原型链概念

    原型:js给每个函数分配的公共空间,减少内存占用

    原型链:多个原型的集合,当调用对象的属性或方法时,先自身找,找不到去原型链上找,一直找到Object构造函数得原型链

    🌟 构造函数new干了啥

    1 搞obj空对象

    2 给obj增加proto属性 并且指向 构造函数的.prototype

    3 将 构造函数this中的数据 全部放到obj上

    4 返回obj对象

    // let Sym = fn
    function Sym() {
      this.a = 1;
      this.b = 2;
      this.c = 3;
    }
    // 第一种使用方式:当变量赋值用
    let data1 = Sym;
    console.log(data1); // 打印:函数本身
    // 第二种使用方法:当函数用
    let data2 = Sym();
    console.log(data2); // 打印:undefined  但是window多了a、b、c三个属性
    // 第三种使用方法:new关键词
    let data3 = new Sym();
    console.log("new关键词:", data3); // 打印:对象
    
    /*
    栈                  堆
    data1: 地址1        地址1:function Sym() {  this.a = 1; this.b = 2;  this.c = 3; }
    data2:undefined    地址2:{a:1,b:2,c:3, __proto__:}
    data3:地址2
     */
    
    function _new(当前new的构造函数) {
      // let obj = {};
      // obj.__proto__ = 当前new的构造函数.prototype;
      
      let obj = Object.create(当前new的构造函数.prototype); // !!!!
      //   obj.a = 1;
      //   obj.b = 2;
      //   obj.c = 3;
      当前new的构造函数.call(obj);
      return obj;
    }
    let data4 = _new(Sym);
    // 需求:封装_new普通函数仿写new关键词效果
    // 分析:_new普通函数里面做哪些时
    // - 必须返回一个对象
    console.log("通过_new仿写new:", data4);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    🌛 箭头函数与普通函数区别?能不能作为构造函数

    1. 语法更加简洁、清晰
    2. 箭头函数不会创建自己的this
    3. 箭头函数继承而来的this指向永远不变
    4. .call()/.apply()/.bind()无法改变箭头函数中this的指向
    5. 箭头函数不能作为构造函数使用
    6. 箭头函数没有自己的arguments
    7. 箭头函数没有原型prototype
    8. 箭头函数不能用作Generator函数,不能使用yeild关键字

    https://juejin.cn/post/6844903805960585224##heading-2

    🌛 更精确判断数据类型

    // typeof 原始类型:除了null是object其他都是自身
    
    // console.log(typeof null); // object
    // console.log(typeof undefined);
    // console.log(typeof true);
    // console.log(typeof 123);
    // console.log(typeof "sdafadsf");
    // console.log(typeof Symbol());
    // console.log(typeof 1111n);
    
    // typeof 对象类型:除了function是function其他都是object
    
    // 问题:你就无法根据不同类型做不同逻辑处理
    // 比如:判断是数组  判断是null
    // 解决:Array.isArray()  等等单独处理
    // 然后:也可以统一处理
    
    // 语法:Object.prototype.toString.call(数据)
    
    // console.log(Object.prototype.toString.call(null));
    // console.log(Object.prototype.toString.call(undefined));
    // console.log(Object.prototype.toString.call(true));
    // console.log(Object.prototype.toString.call(123));
    // console.log(Object.prototype.toString.call("sdfdsf"));
    // console.log(Object.prototype.toString.call(Symbol()));
    // console.log(Object.prototype.toString.call(1111n));
    // console.log(Object.prototype.toString.call(function () {}));
    // console.log(Object.prototype.toString.call({}));
    // console.log(Object.prototype.toString.call([]));
    
    function getType(data) {
      let result = Object.prototype.toString.call(data);
      //   console.log(result.substr(8, result.length - 1 - 8));
      console.log(result.slice(8, -1));
    }
    
    getType(null);
    getType(undefined);
    getType(true);
    getType(123);
    getType("sdfdsf");
    getType(Symbol());
    getType(1111n);
    getType(function () {});
    getType({});
    getType([]);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    🌛 Object构造函数上有哪些语法

    重要

    Object.defineProperty() 三阶段才详细讲 现在【禁止】百度这个

    Object.keys() 获取对象的所有键 返回数组

    Object.values() 获取对象的所有值 返回数据

    Object.create() 创建对象(特色 基于指定原型造对象 场景1:new原理优化,场景2:三阶段vue )


    Object.assign() 合并对象

    Object.prototype.constructor 所属构造函数

    Object.prototype.toString() 转字符串

    💘 Week5 高频周

    • day1

    🌟 输入网址浏览器干哈了(简单版)

    打开浏览器输入网址回车 ->  去DNS服务器找网址对应的IP地址 -> 找不到【无法访问此网站】 找到了【根据ip地址去请求服务器】 -> 服务器返回数据 -> 【浏览器解析】
    
    脚下留心:浏览器其实返回的是index.html的数据,然后在解析的过程中,遇到link、script、img等 再次发送请求拿数据然后解析
    
    • 1
    • 2
    • 3

    🌟 谈谈你对HTTP理解

    面试:HTTP是超文本传输协议,规定了客户端和服务端如何通信,然后由两个部分组成分别是请求、响应
    
    学习:就是一个规则,你必须按照这个规则才可以和后端交互拿数据
    
    
    
    
    
    
    概念:超文本传输协议
    作用:规定客户端和服务端通信技术
    场景:网页、APP等
    请求组成:请求行(地址/状态吗/请求方式)、请求头(ua、content-type、token、cookie)、请求体(接口参数)
    响应组成:响应行(同上)、响应头(暂略)、响应体(接口数据调试错误)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    🌟 HTTP周边:HTTP动词

    🌟 HTTP周边:状态码

    🌟 HTTP周边:请求头参数

    • HTTP动词(请求方式 method)

      明确:form标签也就是w3c就是遵循http规则设计的 但是它的请求方式仅仅只有两种get、post 其他不支持
      但是:我们目前也用get、post 等到三阶段就用n多
      然后:面试就问你有哪些
      种类:常用的get查询、post增加数据、put修改数据、delete删除数据
      实际:java攻城狮就用get查询 增删改都用post

    • 状态码

      2xx 200 成功 201 成功并且服务器创建了新数据
      3xx 301 站内跳转 302 站外跳转 304 浏览器缓存
      4xx 400 你传递给后端的参数 401 密码错误 403 没有权限 404文件不存在 405 请求方式有误
      5xx 500 服务器有误

    • 请求头参数

      ua、content-type、token、cookie

    🌟 HTTP周边:强制缓存、协商缓存

    强制缓存:就是文件直接从本地缓存中获取,不需要发送请求。

    响应头 Cache-Control : 86400

    expires

    协商缓存/对比缓存

    在响应头部 Response Headers 中,有两种资源标识:

    • Last-Modified 资源的最后修改时间,对应请求头为 If-Modified-Since ;
    • Etag 资源的唯一标识,所谓唯一,可以想象成时人类的指纹,具有唯一性;但 Etag 的本质是一个字符串;对应请求头为 If-None-Match 。

    Last-Modified 和 Etag

    • 当响应头部 Response Headers 同时存在 Last-Modified 和 Etag 的值时,会优先使用 Etag ;
    • Last-Modified 只能精确到秒级;
    • 如果资源被重复生成,而内容不变,则 Etag 更精确。

    https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fupload-images.jianshu.io%2Fupload_images%2F5727550-fd8811d7defb8956.png&refer=http%3A%2F%2Fupload-images.jianshu.io&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1650391279&t=0419cce2bf932f3c0e83594c4d177742

    请求行/响应行:method、url、status
    
    请求头headers、cookie、content-type、ua、if-none-match、if-modified-since 
    请求体:请求参数
    
    响应头:content-type 告诉浏览器如何解析数 、etag、last-modified、 Cache-Control...
    响应体:响应的数据
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    🌟 get和post有什么区别

    安全角度:post相对比get安全    原因get会在地址栏 因为在地址栏就有访问历史记录  post请求体不会存在来留痕
    数据角度:post相对传输的数据比get多      get会受到不同浏览器地址栏长度限制,post服务器配置
    
    
    上传图片:2M 一般只能上传png、jpg  gif不允许
    
    • 1
    • 2
    • 3
    • 4
    • 5

    🌟 谈谈你对http、https的理解,有什么区别

    http超文本通讯协议	80
    https也是超文本通讯协议  相对http更加安全  443
    
    • 1
    • 2

    -day2

    🌟 谈谈你对骨架屏的理解

    骨架屏就是在页面数据尚未加载前先给用户展示出页面的大致结构,直到请求数据返回后再渲染页面,补充进需要显示的数据内容。常用于文章列表、动态列表页等相对比较规则的列表页面。 很多项目中都有应用:ex:饿了么h5版本,知乎,facebook等网站中都有应用。

    参考

    https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/10/15/16676db12e4232bb~tplv-t2oaga2asx-watermark.awebp

    🌟 谈谈你对节流防抖的理解

    回答:节流防抖都是用来进行项目优化,减少代码触发的频率,同时又不影响实际效果

    节流:一段时间内只执行一次

    防抖:一段时间内可重复执行,但是要把之前的取消掉

    思路:事件中代码用定时器包起来,然后再前面加判断
    
    问题:输入教主会执行 jiaozhu教主 这么多次
    标签对象.oninput = function() {
        console.log(1)
    }
    
    节流:一段时间内 1次
    let t
    标签对象.oninput = function() {
        if (t) return
        t = setTimeout(() => {
            console.log(1)
            t = null
        }, 3000)
    } 
    
    防抖:一段时间内可重复执行,但是要把之前的取消掉
    let t
    标签对象.oninput = function() {
        if (t) clearTimeout(t)
        t = setTimeout(() => {
            console.log(1)
            t = null
        }, 3000)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    🌟 谈谈你对高阶函数的理解

    简而言之,高阶函数是那些将其他函数作为参数或返回其他函数的函数。在高阶函数中作为参数传递的函数被称为回调。

    高阶函数的优势:

    • 它们可以帮助我们写出简洁的代码。
    • 由于是简洁的代码,调试工作会更加容易。

    现在 JavaScript 有一些内置的高阶函数,你可能已经在不知不觉中就使用它们了,例如 filter()、reduce()、sort() 和 forEach()。

    🌟 function+ajax+callback

    /**
     * 发送get异步请求
     * @param {stirng} url 请求地址
     * @param {object} params 请求参数,格式  {参数名:数据,....,参数名:数据}
     * @param {function} callback 回调函数
     * @param {object} headers 自定义请求头   {键:值, token: '数据', 'content-type': '数据'}
     */
    function get(url, params, callback, headers = {}) {
      // 一、创建xhr对象
      const xhr = new XMLHttpRequest();
      // 二、设置请求方式、请求地址
      let temp = [];
      for (let key in params) {
        temp.push(`${key}=${params[key]}`);
      }
      xhr.open("get", `${url}?${temp.join("&")}`);
      // 三、监听请求状态
      xhr.onreadystatechange = () => {
        // 判断返回
        if (xhr.readyState === 4) {
          // 判断状态
          if (xhr.status === 200) {
            // 获取数据
            let res = JSON.parse(xhr.responseText);
            // 逻辑处理
            // console.log(res);
            callback(res);
          } else {
            console.log(xhr.status);
          }
        }
      };
      // 四、发送
      for (let key in headers) {
        xhr.setRequestHeader(key, headers[key]);
      }
      xhr.send();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    🌟 function+ajax+promise

    /**
     * 发送get请求
     * @param {stirng} url 请求地址
     * @param {object} params 请求参数
     * @param {object} headers 自定义请求头
     * @returns 
     */
    function get(url, params, headers = {})
    {
        const p = new Promise((resolve, reject) => {
            // 一、创建xhr对象
            const xhr = new XMLHttpRequest
            // 二、设置请求方式、请求地址
            let temp = []
            for (let key in params) {
                temp.push(`${key}=${params[key]}`)
            }
            xhr.open('get', `${url}?${temp.join('&')}`)
            // 三、监控请求状态
            xhr.onreadystatechange = () => {
                // 返回
                if (xhr.readyState === 4)
                {
                    // 状态码
                    if (xhr.status === 200)
                    {
                        // 获取数据
                        let res = JSON.parse(xhr.responseText)
                        // 逻辑处理
                        // console.log(res)
                        resolve(res)
                    } else {
                        // console.log(xhr.status)
                        reject(xhr.status)
                    }
                }
            }
            // 四、发送请求
            for (let key in headers) {
                xhr.setRequestHeader(key, headers[key])
            }
            xhr.send()
        })
    
        return p  // 后期谁调用get就会拿到promise对象 通过then就可以获取数据 实现不同的业务逻辑
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    -day3

    🌟 谈谈你对promise的理解

    概念:ES6异步编程解决方案

    作用:常用于封装ajax异步请求

    🌟 说一下promise原理

    底层创建了Promise构造函数,并且给该构造函数绑定了then、catch、finally等原型方法,和reject、resolve、all、race等静态方法。

    🌟 说一下promise几个状态

    进行中、成功了、失败了

    const p = new Promise((resolve, reject) => {
    	// 发送异步请求
    	// 默认触发的  所以是进行中状态
    })
    
    • 1
    • 2
    • 3
    • 4

    追问:为什么状态不可逆

    回答:底层Promise构造函数中会判断当前是否是pending进行中状态,不是就会终止代码执行 所以不可逆

    // 明确:底层Promise源码大概是这么写的
    function Promise(callback) {
    
        this.PromiseState = 'pending'
        this.PromiseResult = undefined
        
        const resolve = data => {
            if (this.PromiseState != 'pending') return
            this.PromiseState = 'fulfilled'
            this.PromiseResult = data
        }
        const reject = error => {
            if (this.PromiseState != 'pending') return
            this.PromiseState = 'rejected'
            this.PromiseResult = error
        }
    
        try {
            // callback(参数1, 参数2)
            // callback(() => {}, () => {})
            callback(resolve, reject)
        } catch(error) {
            reject(error.toString())
        }
    }
    
    // 然后:你写
    const p = new Promise((resolve, reject) => {
    	resolve(数据1)
    	reject(数据2)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    追问:状态之间怎么转换?

    回答:通过promise的then机制,来实现状态切换

    const p = new Promise((resolve, reject) => {
    	resolve(数据1)
    })
    
    p
    .then(res => {
    	return Promise.resolve('失败的')
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    🌟 Promise.all、Promise.allSettled区别

    Promise.all( 数组里面是一个个Promise对象 ) 有一个失败就走失败

    Promise.allSettled( 数组里面是一个个Promise对象 ) 没有失败

    🌟 Promise.race、Promise.any区别

    Promise.race( 数组里面是一个个Promise对象 ) 根据第一个最快返回的决定状态

    Promise.any( 数组里面是一个个Promise对象 ) 有一个成功就是then 都失败 才是catch

    • day4

    🌟 跨域相关

    • 跨域导致原因

      概念:当请求一个url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
      原因:浏览器安全策略/同源策略
      后果:不能跨网站操作发送ajax请求、WEB存储等

    • 跨域解决方案

      前端
      前端代理 http-proxy-middleware
      谷歌插件
      谷歌命令

      jsonp

      websocket
      postMessage

      留心:上述不管哪种方式仅自己可以使用
      最终:开发就选上面其中一种,最终后端:cors法 原理响应头告诉浏览器任何人都可以使用;nginx 反向代理

    🌛 谈谈你对同步异步的理解

    会被加入到浏览器队列的代码称之为异步代码,例如 ajax、setTimeout/setInterval、Promise.then 等等,他们不按书写✍🏻顺序执行打印结果的代码

    按照书写顺序执行打印的代码称之为同步代码

    🌟谈谈你对async,await的理解

    async、await是generator的语法糖,通过async修饰function、await修饰promise,

    底层将await后面的表达式会先执行一遍,再将await下一行代码加入到微任务中。

    🌛 谈谈你generator的理解

    es6新增的语法,通过*号修饰函数,当调用函数的时候返回一个generator对象,通过next函数迭代获取函数内部的数据,当遇到yield就会暂停,再次写next才会继续

    🌟 说出浏览器运行机制

    浏览器主进程,负责创建和销毁tab进程、负责交互前进后退、负责网页文件下载等

    渲染进程:每个tab对应一个渲染进程,下面有GUI渲染线程、JS引擎线程、事件线程、定时器线程、异步请求线程

    GPU进程:负责3D图绘制

    第三方插件进程:负责第三方插件处理,例如跨域、广告拦截插件等

    🌟 说出浏览器输入网址干了啥

    浏览器输入网址回车
    去DNS服务器找网址对应的IP地址 
    根据IP地址加端口访问服务器软件 
    服务器返回数据
    浏览器通过renderer是渲染进程处理,
    其中GUI线程负责页面渲染、JS引擎线程负责解析JS代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    🌛 说出JS为什么是单线程

    先看一个比喻

    进程就是一个公司,每个公司都有自己的资源可以调度;公司之间是相互独立的;而线程就是公司中的每个员工(你,我,他),多个员工一起合作,完成任务,公司可以有一名员工或多个,员工之间共享公司的空间

    什么是进程?

    进程:是cpu分配资源的最小单位;(是能拥有资源和独立运行的最小单位)

    什么是线程?

    线程:是cpu调度的最小单位;(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程)

    浏览器是多进程的

    放在浏览器中,每打开一个tab页面,其实就是新开了一个进程,在这个进程中,还有ui渲染线程,js引擎线程,http请求线程等。 所以,浏览器是一个多进程的。

    大家都在说js是单线程的,但是为什么要设计成单线程?

    这主要和js的用途有关,js是作为浏览器的脚本语言,主要是实现用户与浏览器的交互,以及操作dom;这决定了它只能是单线程,否则会带来很复杂的同步问题。 举个例子:如果js被设计了多线程,如果有一个线程要修改一个dom元素,另一个线程要删除这个dom元素,此时浏览器就会一脸茫然,不知所措。所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变.

    为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

    🌛 说出JS是单线程 为什么不存在执行效率问题

    JS是单线程执行程序代码,形成一个执行栈,挨个处理;

    但是遇到特别耗费时间的代码 ,例如异步请求,事件等,

    不会堵塞等待执行,而是交给浏览器其他线程处理后,再丢到执行栈中处理,从而保证还行效率

    🌟 谈谈你对Event Loop的理解

    Event Loop即事件循环,

    是指浏览器或Node的一种确保javaScript单线程运行时不会阻塞的一种机制,

    也就是我们经常使用异步的原理。

    种类:浏览器的Event Loop、Node.js中的Event Loop

    🌟 谈谈你对浏览器的Event Loop理解

    浏览器输入网址服务器响应数据后,

    浏览器会通过render进程开始解析工作

    GUI线程负责页面渲染

    JS引擎线程负责执行JS代码

    遇到异步代码会交给其他线程处理,然后放到队列中,

    事件循环主要是从队列中取出代码放到执行栈中交给js引擎线程处理

    🌟 说出宏任务、微任务各有哪些

    单词含义:I input 输入、 O output 输出

    用户角度IO操作:鼠标键盘-是计算机输入信息,显示器-是输出设备

    电脑角度IO操作:CPU、内存与其他设备之间数据转移过程就是IO操作,例如数据从磁盘读到内存,或者内存写到磁盘

    编程角度IO操作:进程读取数据操作

    • 宏任务:

      整体代码(script)
      定时器(setTimeout、setInterval)
      I/O操作(DOM事件、AJAX异步请求)

      setImmediate(node环境)
      requestAnimationFrame(浏览器环境)

    • 微任务

      Promise.then catch finally
      async/await(底层还是promise)
      process.nextTick(node环境)
      MutationObserver(浏览器环境)

    🌟 说出先执行宏任务还是微任务

    算整体代码script:1宏n微

    不算整体代码script:先n微,再1宏 -> n微,再1宏 -> n微

    • day5

    🌛 前端存储有几种

    回答1:常用的2种,主要是cookie、h5存储;浏览器其实还有web sql、indexdb

    H5
    cookie
    web sql
    indexdb
    
    • 1
    • 2
    • 3
    • 4

    🌟cookie和h5的区别

    回答2:答案在下面

    性能角度:相对而言H5存储性能比COOKIE高

    存储空间:H5单条数据5M左右、COOKIE单条数据4KB

    生命周期:

    cookie 			       自己设置,如果不设置浏览器关闭销毁
    h5 localStorage    永久
    h5 sessionStorage  窗口 
    
    • 1
    • 2
    • 3

    🌟如何实现localStorage7天过期

    回答3:

    cookie.  1*1000*60*60*24*7
    
    
    login.html
    
    步骤1:存数据的时候 也额外存一个键叫 expires  记录时间
    	localStorage.setItem('uname', 'value')
    	localStorage.setItem('expires', (new Date).getTime() + 1*1000*60*60*24*7 )
    member.html
    步骤2:使用的时候增加判断
    	// 公式:当前使用时间 > 存储时间 (过期了)
    	// 举例:比如你是2月1号存 
    	// 然后:你加了7天  2月8号过期
    	// 最后: 2月5号 > 2月8号   不成立 没过期
    	// 最后: 2月11号 > 2月8号  成立  过期
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    🌟如何实现七天免登录

    1、登录的时候存一个时间 当前时间+7天时间戳

    localStorage.setItem('uname', 'value')
    localStorage.setItem('expires', (new Date).getTime() + 1*1000*60*60*24*7 )
    
    • 1
    • 2

    2、后期用的时候判断是否过期

    会员中心

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    🌟登录是如何实现的

    步骤1:登录按钮绑定点击事件

    步骤2:事件处理函数中 获取表单数据,请求接口

    步骤3:失败-弹框提示,成功-提示、存储、跳转

    💘 Week6 较为低频

    🌛 xhr、$ .get、$.ajax区别

    问题1:XMLHttprequest和JQ代码的区别
    回答1:
    相同点:都可以发送异步请求
    不同点:JQ是基于XMLHttprequest封装了  1 更简单、 2 解决兼容问题等
    
    问题2:$.get、$.ajax区别
    回答2:一样,唯一区别$.ajax比$.get语法上更强
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    🌛 jq你会吗,比如操作样式用什么属性…

    获取标签:CSS选择器、筛选选择器、过滤选择器等
    操作标签:样式css方法、类addClass、属性attr/prop、内容val/html、节点append/remove
    事件:$().事件类型()     $().on(事件类型,子,处理函数)
    异步请求:$.get、$.post、$.ajax
    动画:$.animate() 
    网页加载完毕:$(function(){})    (留心:和window.onload区别 
    对象相互转换:$()[索引]   或者  $(JS标签对象
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    💘 Week7 高频

    🌟 说出几个常用的git命令

    配置SSH  ssh-keygen
    用户配置  git config global user.name/email ''
    获取代码 
    git clone 仓库地址
    git init 
    git remote add origin 仓库地址
    git remote remove origin 仓库地址
    增删改:git add . / commit  / push
    
    周边(忽略文件) .gitignore
    周边(代码冲突) git pull git status 
    周边(日志回滚   git log 、 git reset 
    周边(分支)    git branch / git checkout ...
    周边(其他)    git stash、git tag、git pull、git fetc、git merge
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    🌟 说出git工作流,说一下你们日常开发工作流

    git flow
    
    功能分支 -> 合并到dev分支
    dev分支 -> 合并到release分支
    release分支 -> 合并到master分支
    
    • 1
    • 2
    • 3
    • 4
    • 5

    🌟 说下git如何解决代码冲突

    1 pull
    2 status、手动解决
    3 重新add/commit/push
    
    • 1
    • 2
    • 3

    🌟 说一下你在开发登陆时,线上出现bug了如何维护

    基于master创建hotfix分支,
    解决了再 push 并 merge 到 master、dev 上
    
    • 1
    • 2

    🌟 克隆获取的是默认分支代码,如何获取其他分支代码

    git checkout -b 分支名 分支名
    
    • 1

    🌟 用过哪些git图形化可是软件

    编辑器
    sourcetruee  
    等等
    
    • 1
    • 2
    • 3

    🌟 说下git和svn区别

    git是分布式、svn是集中式
    svn相对容易冲突
    等
    
    • 1
    • 2
    • 3

    1. \u4e00-\u9fa5 ↩︎

  • 相关阅读:
    基于骨骼的动作识别:PoseConv3D
    基于springboot实现校友社交平台管理系统项目【项目源码+论文说明】计算机毕业设计
    [译]为什么vim是程序员最喜欢的编辑器
    #微信小程序(按键控制)
    ssm+java+vue基于微信小程序的智能停车场管理系统#毕业设计
    已解决java.lang.ClassCircularityError: 类循环依赖错误的正确解决方法,亲测有效!!!
    神器 SpringDoc 横空出世!最适合 SpringBoot 的API文档工具来了
    有什么拍照识别植物的软件?建议收藏这几个软件
    设计模式之桥接模式、组合模式与享元模式
    前后端技术栈
  • 原文地址:https://blog.csdn.net/tangyu520lehua/article/details/127971601