前端面试知识点(JS、CSS、Angular)

目录

前言

一、JS知识点

一、找出数组中的最大值

1.1 使用Math.max.apply

1.2 使用Math.max()和扩展运算符 

1.3 使用Math.max()和reduce()

1.4 使用sort()排序

1.5 使用数组的for循环方法

 二、排序算法

2.1 选择排序 

三、内存泄露

3.1 常见的内存泄漏

四、模块化导入导出

4.1 commonjs

五、entries()方法

六、如何判断两个对象是否相等

1.使用全等===判断是否相等

 2.使用JSON.stringfy()判断是否相等

 3.使用遍历属性判断是否相等

七、防抖和节流

1.防抖 

2.节流

八、ES6中Map和Set的区别和用法

1.Set

2.Map

九、数组去重的方式

 1.使用Array.from()和Set()

2. 使用indexOf方法

3.使用双层for循环+splice()

 4.使用includes()方法

5.使用Map去重

十、Promise函数相关知识点

 1.promise状态

 2.promise使用

 3.多次调用.then

十一、去掉字符串内的空格 

1.使用replace()

2.使用for循环

 十二、??运算符

二、CSS知识点

一、CSS盒子模型

二、CSS实现宽度自适应100%,宽高16:9的比例的矩形 

三、Angular知识点

四、面试问题 

4.1 在项目中遇到过的难点


前言

以下是针对我知识点薄弱的地方进行的总结,为面试的一些基础知识进行复习

一、JS知识点

一、找出数组中的最大值

1.1 使用Math.max.apply

Math.max用于找出传入参数的最大值,而apply可以将数组形式作为参数传入

math.max(a, b ,c, d,...)返回最大的那个数字,其中比较的参数可以任意个

 const arr = [1, 2, 45, 6];
 console.log(Math.max.apply(null, arr)); //45 apply接受两个参数,第一个用于指定上下文对象,第二个则是数组形式传入参数

1.2 使用Math.max()和扩展运算符 

 const arr = [1, 2, 45, 6];
 console.log(Math.max(...arr)); //45

1.3 使用Math.max()和reduce()

const arr = [1, 2, 45, 6];
const max = arr.reduce((a, b) => Math.max(a, b)); 
console.log(max);//45

1.4 使用sort()排序

sort方法默认按照字符的ASCII码进行升序排序,所以有时候顺序会不同于想要的结果此时可以将传参改为函数,利用函数返回来决定sort是升序还是降序

const arr = [1, 2, 45, 6];
        arr.sort((a, b) => {
            return a - b;
        });
        console.log(arr); //[1,2,6,45]
        const max = arr[arr.length - 1];
        console.log(max);//45

1.5 使用数组的for循环方法

const arr = [1, 2, 45, 6];
let max = arr[0];
        for (let i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        console.log(max);//45

 二、排序算法

2.1 选择排序 

 //选择排序
        const arr = [8, 7, 3, 9, 12, 5];
        //第一轮
        //假设最小值是索引值为0的值,如果发现有比当前数更小的数,就重新确定最小数,并得 
          到下标当遍历到数组的最后时,就得到本轮最小数的小标
        //首先i=0不满足条件,i变为1,此时arr[0]>arr[1]即8>7满足条件,此时minIndex=1,
        //i变为2,if语句arr[1]>arr[2]即7>3成立,minIndex=2,以此类推后面没有数比3小
        //所以第一轮找到的最小值索引为2,与初始值0所在的值交换
        let minIndex = 0;
        for (let i = 0; i < arr.length - 1; i++) {
            if (arr[minIndex] > arr[i]) {
                minIndex = i;
            }
        }
        //遍历结束找到当前最小值所在的索引值,让第0个和索引值minIndex的交换
        //第二轮则从索引值为i+1开始比较,往后以此类推
        var temp = arr[minIndex];
        arr[minIndex] = arr[0];
        arr[0] = temp;

        //结果
        // 外层循环表示总共需要排序几次才能找到最小值 第一轮是索引0-arr.length-1
        //第二轮是索引1到arr.length-1,....,需要排序的次数是arr.length-1次
        //内存循环则为
        for (let i = 0; i < arr.length - 1; i++) {
            let minIndex = i;
            let min = arr[minIndex];
            for (let j = i + 1; j < arr.length; j++) {
                if (min > arr[j]) {
                    minIndex = j;
                    min = arr[j];
                }
            }
            //结束循环后
            if (minIndex !== i) {
                arr[minIndex] = arr[i];
                arr[i] = min;
            }
        }

// 输出结果: [3, 5, 7, 8, 9, 12]

三、内存泄露

内存泄漏是指程序中不再使用的内存没有被释放,无法进行垃圾回收,从而导致系统内存的浪费,影响系统的性能和稳定性。

3.1 常见的内存泄漏

1、 意外的全局变量。未被声明的变量,会被挂在window对象下,不能及时的销毁。(不使用时将变量设为null)

2、启动循环定时器后不清理,会一直循环。导致计时器持续运行,占用内存空间,导致内存泄漏。(销毁生命周期函数时调用清除定时器的方法)

3、闭包,一个函数在作用域内可以访问另一个函数的变量,这个函数被引用着不会被销毁。(将函数设为null)

四、模块化导入导出

4.1 commonjs

导出分为module.exports和export,导入是require

1.module.exports导出

 //a.js导出
 module.exports = {a: 1};
 //导入
 const { a } = require('./a.js')

2.exports导出

nodejs为每个模块提供了一个exposrts变量,其指向module.exports,相当于再模块头部加了这句代码:var exports = module.exports;在对外输出时,可以给exports对象添加方法,但不能直接赋值,因为这样会切断exports与module.exports的联系。所以不能使用exports={}导出,而是如下

        exports.a = 1;
        exports.fa = function () {};

五、entries()方法

可以将数组转换成一个可迭代数组

        const arr = [1, 2, 3];
        console.log(arr.entries());
        for (let i of arr.entries()) {
            console.log(i);
        }
        //输出
         [0,1]
         [1,2]
         [2,3]   

六、如何判断两个对象是否相等

1.使用全等===判断是否相等

===比较的是引用地址,可以判断是否引用了同一个对象,也就是引用地址指向同一个时,可以判断全等。

        //使用全等===判断是否相等
        const obj1 = { a: 1, name: '张三', b: {} };
        const obj3 = { a: 1, name: '张三', b: {} };
        let obj4 = obj1;
        console.log(obj1 === obj3);//false
        console.log(obj1 === obj4);//true

 2.使用JSON.stringfy()判断是否相等

JSON.stringfy()比较的是对象中的属性,不比较引用地址

        const obj1 = { a: 1, name: '张三', b: { name: '1' } };
        const obj3 = { a: 1, name: '张三', b: { name: '1' } };
        let obj4 = obj1;
        console.log(JSON.stringify(obj1) === JSON.stringify(obj3));//true
        console.log(JSON.stringify(obj1) === JSON.stringify(obj4));//true

 3.使用遍历属性判断是否相等

Object.keys()遍历属性对判断是否一致,for循环判断属性值是否一致

getAttribute(a: any, b: any) {
        const obj1 = Object.keys(a);
        const obj2 = Object.keys(b);
        //属性不同则返回
        if (obj1.length !== obj2.length) {
            return false;
        }
        // 属性值不同
        for (let key of obj1) {
            if (a[key] !== b[key]) return false;
        }
        return true;
    }

 ngOnInit(): void {
        //使用全等===判断是否相等
        const obj1 = { a: 1, name: '张三', b: { name: '1' } };
        const obj3 = { a: 1, name: '李四', b: { name: '1' } };
        let obj4 = obj1;
        console.log(this.getAttribute(obj1, obj3)); //false
        console.log(this.getAttribute(obj1, obj4)); //true
    }

七、防抖和节流

作用:都是在高频事件中防止函数被多次调用,以此优化性能

区别:1.防抖函数只会在高频事件结束后n毫秒调用一次函数

           2.节流函数是在高频事件触发过程中每隔n毫秒调用一次函数

1.防抖 

高频事件结束后n毫秒内只会调用一次函数,如果再次触发,则重新计算时间

    //防抖(debounce)
    //input框的输入、scroll事件滚动出发、按钮提交事件
    //触发高频事件后n秒内函数只会执行一次,如果n秒内再次触发,则重新计算时间
    debounceTime(func, timeout) {
        let timer = null;
        return function debounce() {
            //清除定时器
            clearTimeout(timer);
            timer = setTimeout(() => {
                //使得每次传入的函数的this都指向调用该debounceTime的调用者
                func.apply(this, arguments);
            }, timeout);
        };
    }

2.节流

持续触发事件后,保证每隔一段时间就执行一次事件

    //节流(throttle)
    //搜索联想、DOM 元素的拖拽功能实现
    //频发触发事件,每隔一段时间执行一次函数,多次触发只会在间隔时间内执行一次
    throttleTime(func, timeout) {
        let timer = null;
        return function throttle() {
            //如果没有计时器 则执行
            if (!timer) {
                timer = setTimeout(() => {
                    func.apply(this, arguments);
                    //间隔时间结束 计时器清除 在规定的时间内只会触发一次
                    timer = null;
                }, timeout);
            }
        };
    }

八、ES6中Map和Set的区别和用法

1.Set

Set是一组key的集合,每个key都是唯一的不能重复所以可以用Set进行数组去重

        //数组去重
        const arr = [...new Set([1, 2, 3, 4, 4, 6, 7, 7])];
        console.log(arr);//[1,2,3,4,6,7]
        //Set的方法使用
        //1.add() 添加元素
        const newSet = new Set();
        newSet.add('hello');
        newSet.add('world');
        newSet.add('!');
        //2.delete() 删除元素
        newSet.delete('!');
        //3.has() 是否存在某个值
        console.log(newSet.has('hello')); //true
        //4.size Set中元素的数量
        console.log(newSet.size); //2
        //5.clear()  清除Set中所有元素
        newSet.clear();
        const set = new Set([1, 23, 4]);
        //6.keys() Set中的所有元素的键名
        console.log(set.keys()); //SetIterator {1, 23, 4}
        //7.values() Set中所有元素的键值
        console.log(set.values()); //SetIterator {1, 23, 4}
        //8.entries() Set中所有键值对
        console.log(set.entries()); //SetIterator {1 => 1, 23 => 23, 4 => 4}
     

2.Map

Map是一组键值对的结构,初始化Map需要一个二维数组,或者直接初始化一个空Map

        const map = new Map([
            ['name', 'zhangsan'],
            ['age', '18'],
            ['sex', 'male'],
        ]);
        const newMap = new Map();
        console.log(map); //Map(3) {'name' => 'zhangsan', 'age' => '18', 'sex' => 'male'}
        //1.set(key,value) 新增
        map.set('address', 'earth');
        //2.get(key) 通过key查到对应的value
        console.log(map.get('age')); //18
        //3.has(key) 是否存在某个key
        console.log(map.has('name')); //true
        //4.delete(key) 删除某个key
        map.delete('sex');
        //5.clear() 清空Map里所有的键值对
        map.clear();
        newMap.set('data', 10);
        newMap.set('total', 20);
        //6.keys()  返回Map中所有的键
        console.log(newMap.keys()); //MapIterator {'data', 'total'}
        //7.values() 返回Map所有的键值
        console.log(newMap.values()); //MapIterator {10, 20}
        //8.entries() 返回Map中所有键值对
        console.log(newMap.entries()); //MapIterator {'data' => 10, 'total' => 20}
        //9.forEach() 遍历Map中所有键值对
        newMap.forEach((value: any, key: any) => {
            console.log(value, key);
            //10 'data'
            //20 'total'
        });

九、数组去重的方式

 1.使用Array.from()和Set()

        const arr = [1, 5, 7, 2, 5, 7, 8, 8, null, null, undefined, undefined, NaN, NaN]; 
//Array.from从可迭代(Set Map)或类数组(存在length属性和索引元素的对象)对象创建数组
        const newArr = Array.from(new Set(arr));
        console.log(newArr);//[1, 5, 7, 2, 8, null, undefined, NaN]

2. 使用indexOf方法

indexOf无法区分NaN

        const arr = [1, 5, 7, 2, 5, 7, 8, 8, null, null, undefined, undefined, NaN, NaN];
        //无法区分NaN 因为NaN!==NaN NaN不等于本身
        //利用数组的indexOf判断如果不存在则加入新数组
        const newArr = [];
        arr.forEach((item: any) => {
            //判断新数组中是否存在某个值
            if (newArr.indexOf(item) === -1) {
                newArr.push(item);
            }
        });
        console.log(newArr); //[1, 5, 7, 2, 8, null, undefined, NaN, NaN]

3.使用双层for循环+splice()

注意:undefined在数组中相当于数组空位即没有值,所以在使用数组方法filter、map、forEach时会直接跳过

以下例子中a[19],a[11],a[12],a[13]具有null或undefined值 索引不存在,所以无法使用for循环

         const arr = [1, 5, 7, 2, 5, 7, 8, 8, null, null, NaN, NaN, undefined, undefined];
        //使用两层循环+splice()
        for (let i = 0; i < arr.length; i++) {
            for (let j = i + 1; j < arr.length; j++) {
                if (arr[i] === arr[j]) {
                    //去除序号较大的元素,数组长度-1,序号为j的被删除序号j后的元素顶上
                    arr.splice(j, 1);
                    arr.length--;
                    j--;
                }
            }
        }
        console.log(arr);//[1, 5, 7, 2, 8, null]

 4.使用includes()方法

        const arr = [1, 5, 7, 2, 5, 7, 8, 8, null, null, undefined, undefined, NaN, NaN];
        //使用数组的includes()方法来检测是否存在某个值
        const newArr = [];
        arr.forEach((item: any) => {
            //如果不存在数组中,则新增至数组
            if (!newArr.includes(item)) {
                newArr.push(item);
            }
        });
        console.log(newArr);//[1, 5, 7, 2, 8, null, undefined, NaN]

5.使用Map去重

        const arr = [1, 5, 7, 2, 5, 7, 8, 8, null, null, undefined, undefined, NaN, NaN];
        //使用Map去重
        const newArr = new Map();
        arr.forEach((item: any) => {
            //如果不存在数组中,则新增至数组
            if (!newArr.has(item)) {
                newArr.set(item, item);
            }
        });
        const data = [...newArr.keys()];
        console.log(data);// [1, 5, 7, 2, 8, null, undefined, NaN]

十、Promise函数相关知识点

 1.promise状态

Promise状态有三种:pending(等待)、fulfilled(成功)、rejected(失败)

 2.promise使用

注意:.catch()的作用是捕获Promise的错误,与then()的rejected回调作用几乎一致,catch()也能够捕获then()中抛出的错误

        //成功状态
        new Promise((resolve, reject) => {
            resolve(2);
        }).then(
            resolved => {
                console.log(resolved); //2
            },
            (error: any) => {
                console.log(error);
            }
        );

        //失败状态
        new Promise((resolve, reject) => {
            reject(444);
        }).then(
            resolved => {
                console.log(resolved); //2
            },
            (error: any) => {
                console.log(error);//444
            }
        );
        //在.then中如果没有第二个失败的回调
        //存在.catch(可以更清晰定义错误处理逻辑)会执行
        new Promise((resolve, reject) => {
            reject(444);
        })
            .then(
                resolved => {
                    console.log(resolved); //2
                }
                // (error: any) => {
                //     console.log('rejected', error);
                // }
            )
            .catch(error => {
                console.log('catch', error);//444
            });

 3.多次调用.then

           new Promise((resolve, reject) => {
            resolve(444);
            })
            .then(value => {
                console.log(value); //2
                return 888;
            })
            .then(value => {
                //这里的值是上一个.then的返回值
                console.log(value); //888
            })
            .then(value => {
                //上一个.then没有传值 则为undefined
                console.log(value); //undefined
            });

十一、去掉字符串内的空格 

1.使用replace()

        const str = ` a a a a `;
        //replace方法返回一个新字符串,不会更改字符串
        //全局匹配所有空格
        const newStr = str.replace(/\s/g, '');
        console.log(newStr); //aaaa

2.使用for循环

        const str = ` a a  a a `;
        let newStr = '';
        for (let i = 0; i < str.length; i++) {
            if (str[i] !== ' ') {
                newStr += str[i];
            }
        }
        console.log(newStr);//aaaa

 十二、??运算符

??的作用是用来判断一个变脸是否为null或者undefined,JavaScript两个问号运算符会检查一个变量的值是否为null或undefined。它只有在变量值为null或undefined时才会返回默认值,否则返回变量的实际值

示例: 

  //只有当值为undefined/null时输出默认值??后的值,否则都输出??之前的值
        let name = '';
        console.log(name ?? 'hahah'); //输出空字符串
        let key = undefined;
        console.log(key ?? 'hahah'); //输出hahah

二、CSS知识点

一、CSS盒子模型

浏览器默认的盒子模型为box-sizing:content-box(默认)

CSS盒子模型包含标准盒子模型IE盒子模型。

盒模型都是由四个部分组成的,分别是 margin、border、padding 和 content。

box-sizing: border-box;  /*IE盒子模型*/ 
box-sizing: content-box; /*标准盒子模型*/

 示例图:

22222
IE盒子模型
标准盒子模型

//IE盒子模型
// 盒子的width和height分别为content、padding、border的宽高度相加
.box {
    box-sizing: border-box;
    width: 200px;
    height: 200px;
    border: 10px solid black;
    margin: 10px;
    padding: 10px;
    background-color: aqua;
}

//W3c 标准盒子模型 盒子的width和height为content
.content {
    box-sizing: content-box;
    width: 200px;
    height: 200px;
    padding: 10px;
    border: 10px solid black;
    margin: 10px;
    background-color: rgb(238, 185, 70);
}

二、CSS实现宽度自适应100%,宽高16:9的比例的矩形 

假设宽度为100%,那么高度则为h= 9/16 = 56.25%

<div class="content">
    <div class="box">这是一个16:9的盒子</div>
</div>
.content {
    width: 50%;
    .box {
        width: 100%;
        height: 0; /*防止矩形被里面的内容撑出多余的高度 且父元素未设置高度 
 此时如果使用百分比则是0的基础上设置 那么子元素也会没有高度 所以不能使用百分比*/
 /*撑起盒子高度 如果为padding-top也会是16:9 但此时盒子内的内容则会在盒子下方*/
        padding-bottom: 56.25%; 
        background: pink;
        position: relative;
        .box p {
            width: 100%;
            height: 100%;
            position: absolute;
        }
    }
}

三、实现三角形

 

把需要隐藏的border设置为transparent即可

.content {
    height: 0;
    width: 0;
    border-top: 100px solid pink;
    /*  border-bottom: 10px solid transparent; */
    border-bottom: 100px solid yellow;
    border-right: 100px solid greenyellow;
    /*  border-right: 10px solid transparent; */
    border-left: 100px solid skyblue;
}

三、Angular知识点

四、面试问题 

4.1 在项目中遇到过的难点

1.性能优化 如浏览器缓存问题、路由的懒加载问题、比如通过angular自带的debounceTime防抖来对一些搜索功能的api进行结合,减少调用的次数优化性能


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值