前端实战技巧(一)

61 阅读3分钟

1.对象如何判断属性是否存在

定义如下obj对象

// 自有属性
const obj = {
    a: undefined
}

//原型上的属性
obj.__proto__.b = undefined

// 定义不可枚举的属性
Object.defineProperties(obj,{'c':{
    value:1 ,
    enumerable:false,
    }
})
//获取属性描述
Object.getOwnPropertyDescriptors(obj,"a")

if ("a" in obj) {
    console.log("a 存在")
}

if ("b" in obj) {
    console.log("b 存在")
}

if ("c" in obj) {
    console.log("c 存在")
}
  1. 通过Object.keys(obj).includes("c") 判断,只能判断自有属性,无法判断原型上的属性不可枚举的属性
  2. 通过obj.hasOwnProperty("c"),可以判断自有属性不可枚举的属性,不能判断原型上的属性
  3. 通过if ("a" in obj),是es6语法,三种都可以判断

2.数据类型和typeOf

截屏2023-11-30 16.11.38.png

js中是否存在精确的计时?

不存在,从以下4个方面

  1. 硬件: 没有绝对的精确,只有相对精确(计算机使用cpu寄存器计时)
  2. 系统: 浏览器调用操作系统计时间
  3. 标准: w3c,如果settimeout 嵌套层级>=5 ,最小耗时4ms时间
  4. 事件循环: 回调函数必须等待执行栈清空

判断是否是数组

有3种方式如下

// 方式1

function isArrayOne(list){

    const data = Object.prototype.toString.call(list)

    console.log("data",data);

    if(data === '[object Array]'){
        return true;

    }
    return false;
}

const arr = [1,2,3,4]

//缺点,可以通过Symbol修改字符串
const obj = {
    [Symbol.toStringTag] : 'Array'
}
console.log("obj",isArrayOne(obj))


//方式2

function isArrayTwo(list){

if(arr instanceof Array){
    return true

}
    return false
}

// 当前window Array
const Array1 = window.Array;
const iframe = document.querySelector('iframe');
const Array2 = iframe.contentWindow.Array;

// 方式2的缺点
// 如果是iframe下面的Array ,方式2的判断会有问题

console.log("方式2:",Array1 === Array2);

//最佳方式3

// 方式3 精确的判断

function isArrayThree(list){

if(Array.isArray(arr)){

    return true;

}

   return false

}


如何打破谷歌浏览器最小字体限制

谷歌浏览器默认的最小字体大小为12,即使我们把字体变为<12,也无法改变,这给时候我们可以使用缩放

.font-scale{

    font-size: 20px;

    transform: scale(0.5);

    display: inline-block;

    transform-origin: left center;

}

判断一个指是否是Promise Like

// 根据promise A+ 规范

function isPromiseLike(value){

// 1.是对象或者函数

// 2.并且 then 方法是函数

    return (value !== null &&

            (typeof value === 'object' || typeof value === 'function') &&

            (typeof value.then === 'function'))

}

Proxy 和defineProperty到底哪个好

  1. defineProperty 需要深度遍历每一个对象, 通过在get 和set方法做一些处理

如果后续需要增加和删除属性则无法接听

  1. proxy直接监听整个对象

前端实现滚动元素到可视区域

常用的有2种方式如下

使用浏览器的锚点来实现

<!-- 给目标元素设置一个唯一的id -->

<div class="targetIdName">

</div>

<!-- 通过a元素创建一个带有锚点的链接 -->

<a href="#targetIdName"></a>
  • 优点:使用方便,可以分享后带链接跳转

  • 缺点:1. 无法滚动到精确位置

  • 缺点: 使用vue和react框架开发使用hash路由的时候会造成冲突

使用Js实现

通过scrollIntoView({behavior:'smooth',block:'start'}) 来实现

el:当前元素 behavior: 滑动行为 block:垂直方向的对齐 (start、center、end)

实现并发请求

需求如下:

  • 封装一个函数,传入参数1:需要并非的请求地址,参数2:同时并发的最大数量
  • 所有数据请求完成后,有序的返回各个借口的数据

直接上代码

function concurReq(urlList,maxNum){
    // 如果数组为空,直接返回空数组
    if(urlList.length == 0) return Promise.resolve([]);
    //指向下一次请求url的下表
    let index = 0;
    let count = 0; //当前完成的请求数量
    // 保存请求的结果
    const result = [];
    return new Promise((resolve)=>{
        // 单个接口请求
        async function _request(){
            const i = index;
            const url = urlList[index];
            index++;
        try {
                const resp = await fetch(url);
                result[i] = resp
            } catch (error) {
                result[i] = error
           }
           
        finally{
            count++;
            if(count === urlList.length){
            resolve(result)
        }
        
        if(index < urlList.length){
            _request();
        }

    }
}
    // 并发请求的最大数量
    for(let i = 0;i<Math.min(maxNum,urlList.length);i++){
          _request();
    }
})

}