前端知识点

1、JS基本数据类型有哪些?引用数据类型有哪些?

在 JS 中,存在着 8 种原始值,分别是: boolean null undefined number string symbol 、Bigint(ES2020新增)
引用数据类型:
对象Object(包含普通对象-Object,数组对象-Array,正则对象-RegExp,日期对象-Date,数学函数-Math,函数对象-Function)

null和undefined 有什么区别?

(1)null是一个表示”无”的对象,转我数值是为0,undefined是一个表示”无”的原始值,转为数值时为NaN。当声明的变量还未被初始化时,能量的默认值为undefined
(2)Null用来表示尚未存在的对象,常用来表示函数企图返回一个不存在的对象
(3)Undefined表示”缺少值”,就是此处应该有一个值,但是还没有定义。
典型用法是:
a、变量被声明了,但没有赋值时,就等于undefined
b、调用函数时,应该提供的参数没有提供,该参数等于undefined
c、对象没有赋值属性,该属性的值为undefined
d、函数没有返回值时,默认返回undefined
(4)null表示”没有对象”,即该处不应该有值。典型用法是: a、作为函数的参数,表示该函数的参数不是对象 b、作为对象原型链的终点

 

 

2、CSS中 link 和@import 的区别是?

link属于HTML标签,而@import是CSS提供的;页面被加载的时link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;link方式的样式的权重 高于@import的权重.

3、position的absolute与fixed共同点与不同点

相同:改变行内元素的呈现方式,display被置为block;让元素脱离普通流,不占据空间;默认会覆盖到非定位元素上
不同点:absolute的”根元素“是可以设置的,而fixed的”根元素“固定为浏览器窗口。当你滚动网页,元素与浏览器窗口之间的距离是不变的。  


4、什么是闭包?

   我的理解是,闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

5、谈谈你对原型链的理解

在JavaScript中,每当定义一个函数数据类型(普通函数、类)时候,都会天生自带一个prototype属性,这个属性指向函数的原型对象。
   当函数经过new调用时,这个函数就成为了构造函数,返回一个全新的实例对象,这个实例对象有一个__proto__属性,指向构造函数的原型对象。
   JavaScript对象通过__proto__ 指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条, 即原型链。

实现一个instanceof

function myInstanceof(left,right) {
    if(typeof left !== 'object' || left === null) return false
    //获取原型
    let proto = Object.getPrototypeOf(left)
    while(true){
        //如果原型为null,则已经到了原型链顶端,判断结束
        if(proto === null) return false
        //左边的原型等于右边的原型,则返回结果
        if(proto === right.prototype) return true
        //否则就继续向上获取原型
        proto = Object.getPrototypeOf(proto)
    }
}

 

6、关于setTimeout的一些冷知识

  • 由于消息队列的机制,不一定能按照自己设置的时间执行

  • settimeout嵌套settimeout时,系统会设置最短时间间隔为4ms

  • 未激活的页面,settimeout最小时间间隔为1000ms

  • 延时执行时间最大值为2147483647(32bit),溢出这个值会导致定时器立即执行

7、常见兼容性问题


浏览器默认的margin和padding不同。解决方案是加一个全局的*{margin:0;padding:0;}来统一。
IE下,可以使用获取常规属性的方法来获取自定义属性,
   也可以使用getAttribute()获取自定义属性;
   Firefox下,只能使用getAttribute()获取自定义属性. 
   解决方法:统一通过getAttribute()获取自定义属性.
IE下,event对象有x,y属性,但是没有pageX,pageY属性; 
  Firefox下,event对象有pageX,pageY属性,但是没有x,y属性
解决方法:(条件注释)缺点是在IE浏览器下可能会增加额外的HTTP请求数。
Chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示, 
  可通过加入 CSS 属性 -webkit-text-size-adjust: none; 解决.

超链接访问过后hover样式就不出现了 被点击访问过的超链接样式不在具有hover和active了解决方法是改变CSS属性的排列顺序:
L-V-H-A :  a:link {} a:visited {} a:hover {} a:active {}

上下margin重合问题
ie和ff都存在,相邻的两个div的margin-left和margin-right不会重合,但是margin-top和margin-bottom却会发生重合。
解决方法,养成良好的代码编写习惯,同时采用margin-top或者同时采用margin-bottom。


8、节流

比如说事件触发可以让它在每一秒内只触发一次,可以提高性能。
function throttle(fn, wait) {
    let prev = +new Date()
    return function() {
        let now = +new Date()
        /*当下一次事件触发的时间和初始事件触发的时间的差值大于
			等待时间时才触发新事件 */
        if(now - prev > wait) {
            fn.apply(this, arguments)
        }
        //重置初始触发时间
        prev = +new Date()
    }
}

 

9、防抖

防抖就是可以限制事件在一定时间内不能多次触发,比如说你疯狂按点击按钮,一顿操作猛如虎,不加防抖的话它也会跟着你疯起来,疯狂执行触发的方法。但是一旦加了防抖,无论你点击多少次,他都只会在你最后一次点击的时候才执行。 防抖常用于搜索框或滚动条等的监听事件处理,可以提高性能。

function debounce(fn, wait = 50) {
    //初始化一个定时器
    let timer
    return function() {
        //如果timer存在就将其清除
        if(timer) {
            clearTimeout(timer)
        }
        //重置timer
        timer = setTimeout(() => {
            //将入参绑定给调用对象
            fn.apply(this, arguments)
        }, wait)
    }
}

深拷贝和浅拷贝

浅拷贝: 顾名思义,所谓浅拷贝就是对对象进行浅层次的复制,只复制一层对象的属性,并不包括对象里面的引用类型数据 , 当遇到有子对象的情况时,子对象就会互相影响 ,修改拷贝出来的子对象也会影响原有的子对象

深拷贝: 深拷贝是对对象以及对象的所有子对象进行拷贝,也就是说新拷贝对象的子对象里的属性也不会影响到原来的对象

let obj = { a: 1, b: 2, c: { d: 3, e: 4 } }

实现浅拷贝

使用Object.assign()

let obj2 = Object.assign({}, obj)
obj2.a = 111
obj2.c.e = 555
console.log(obj)
console.log(obj2)

 

使用展开运算符

let obj2 = {...obj}

obj2.a = 111

obj2.c.e = 555

console.log(obj)

console.log(obj2) 

 

实现深拷贝

最简单的深拷贝方式

let target = JSON.parse(JSON.stringify(source))

但是这种方法的话只支持objectarraystringnumbertruefalsenull这几种数据或者值,其他的比如函数、undefined、Date、RegExp等数据类型都不支持。对于它不支持的数据都会直接忽略该属性。

 

完整版

function deepCopy(source, cache = new Map()) {
  if (cache.has(source)) {
    //如果缓存中已经有值则直接返回,解决循环调用的问题
    return cache.get(source)
  }
  //当入参属于Object复杂数据类型就开始做子类检测-> Function Array RegExp Date 都属于Object类型
  if (source instanceof Object) {
    let target
    if (source instanceof Array) {
      //判断数组的情况
      target = []
    } else if (source instanceof Function) {
      //判断函数的情况
      target = function () {
        return source.apply(this, arguments)
      }
    } else if (source instanceof RegExp) {
      //判断正则表达式的情况
      target = source
    } else if (source instanceof Date) {
      target = new Date(source)
    } else {
      //普通对象
      target = {}
    }
    // 将属性和拷贝后的值进行缓存
    cache.set(source, target)
    //开始做遍历递归调用
    for (let key in source) {
      if (source.hasOwnProperty(key)) {
        target[key] = deepCopy(source[key], cache)
      }
    }
    return target
  } else {
    //如果不是复杂数据类型的话就直接返回
    return source
  }
}

 

posted on 2022-04-11 14:59  助金  阅读(35)  评论(0编辑  收藏  举报