web前端面试套路(完整的体系) 层层深入

一、变量、JS部分

一.JS的数据类型
  • 基本数据类型 (number, string, boolean, null[空指针], undefined) 存储的是值
  • 引用数据类型(object[[]], {},new Boolean()], function) 存储的是引用地址(指向同一个内存地址,一个变,另一个会随之改变)
  • es6 symobl [Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象]
注意: 基本数据类型用new关键字也会变成一个一个应用数据类型,是一个实例了
如何判断一个值是否是null
 function checkNull(val) {
      return  typeof val === 'object' && val === val;
 }
 checkNull()
复制代码
如何判断一个值是否是NaN
 function checkNaN(val) {
      return  val.toSring() === 'NaN';
 }
 checkNull() 
复制代码
二.如何检测数据类型
  • typeof typeof() 是一个一元运算符,可以不加括号,是等价的, 返回一个类型字符串 用法==>> typeof typeof()

    • 只能检测基本数据类型,不能区分引用数据类型,引用数据类型都返回'object'
    • 如何区分null和object类型
    • 如何区分function 和 symbol类型
    有六种结果==>: 'number', 'string', 'boolean', 'object'[null], 'function'[Symobl], 'undefined'
        typeof null = > 'object'
        typeof Symobl('es6') => 'function'
        typeof typeof typeof typeof [] => 'string'
    复制代码
  • instanceof 只要在原型链上即可, 用法==>> 值 instanceof 类

    • Object类是所有类的基类
    • Function类是所有函数的基类
  [] instanceof Array // true
  [] instanceof Object  // true
  null instanceof Object //false    null空对象使用
复制代码
  • constructor 利用函数原型上的constructor执行类本身去判断(原型链机制去查找)
  • 在原型继承的时候会打断了,需要手动设置construct的值 [子类的.prototyep.constrcutor = 子类]
 机制是:实例.__proto ===类的.prototype.constructr
     function fn() {}
     [].constrcutor === Array;  / false
     fn.constrcutor === Object  // false
     fn.constructor === Function //true
     
     function A() {}
     A.prototype.getX() {};
     
     function B() {}
     B.protype = new A();
     B.prototype.constructor = B; //====>>手动设置constructor的值,设置会执行父类A
复制代码
  • Object.prototype.toString.call(val) 返回'[object 类的本身]' 改变this,返回类本身,最好的
 1.封装检测数据类型和判断数据类型各个方法
     const tool = function(window, undefined) {
          let box = {
              checkTypeof(val) {
                  return Object.prototype.toString.call(val);  
              },
              isNumber(val) {
                  return Object.prototype.toString.call(val) === '[object Number]';
              },
              isString(val) {
                  return Object.prototype.toString.call(val) === '[object String]';
              },
              isBoolean(val) {
                  return Object.prototype.toString.call(val) === '[object Boolean]';
              },
              isNull(val) {
                  return Object.prototype.toString.call(val) === '[object Null]';
              },
              isUndefined(val) {
                  return Object.prototype.toString.call(val) === '[object Undefined]';
              },
              isFunction(val) {
                  return Object.prototype.toString.call(val) === '[object Function]';
              },
              isObject(val) {
                  return Object.prototype.toString.call(val) === '[object Object]';
              },
              isArray(val) {
                  return Object.prototype.toString.call(val) === '[object Array]';
              },
              isSymbol(val) {
                  return Object.prototype.toString.call(val) === '[object Symbol]';
              },
              isExpRep(val) {
                  return Object.prototype.toString.call(val) === '[object ExpRep]';
              },
          };
          return box;
    }();

2. 如何判断一个变量是否是数组
     - instanceof     val instanceof Array
     - constrcutor    val.constrcutor === Array
     - Array.isArray(val)
     - Object.prototype.toString.call(val)   ==> '[object Array]'   => 最靠谱,最安全
     
     注意:constrcutor和isArray在两个iframe,在哪个iframe中间判断,因为是俩个window对象,会有问题
复制代码
三、数组方法
  • es3
push => pop  
unshift => shift
splice(n, m, val) 截取  从n,删除m个元素,用val去替换
slice(n,[m])    筛选,从索引n,查找到索引m,不包含m
conact  合并数组
reverse  倒叙     判断回文数面试题
sort((a,b) => a-b);  排序, 原理是冒泡排序  手写冒泡排序
indexOf([n]) => lastIndexOf([n]) 原理是,遍历进行===进行比较,所以NaN是找不到的 NaN === NaN =>false   查找这个东西,返回索引值,没有返回-1,前,后查找  
join 手拉手 转为字符串 split劈开转为数组

复制代码
  • es5 都是callback进行处理,不会改变原来数组, 自己封装
forEach  遍历
filter   过滤,筛选出符合条件的数据
map      映射, 一组数据对应
reduce   计算
some     全部是否符合
every    任意一个符合


myForEach:
   Array.prototype.myForEach = function (callback) {
       if (typeof callback == 'function') {
           for (let i = 0; i < this.length; i++) {
               callback.call(this, this[i], i, this);
           }
       }
   };

myMap:
   Array.prototype.myMap = function (callback) {
       let ary = [];
       if (typeof callback == 'function') {
           for (let i = 0; i < this.length; i++) {
               ary.push(callback.call(this, this[i], i, this));
           }
       }
       return ary;
   };


myFilter:
   Array.prototype.myFilter = function (callback) {
       let ary = [];
       if (typeof callback == 'function') {
           for (let i = 0; i < this.length; i++) {
             if (callback.call(this, this[i], i, this)) {
                 ary.push(this[i]);
             }
           }
       }
       return ary;
   };

复制代码
  • es6
find => findIndex 数组实例的find方法,用于找出第一个符合条件的数组成员
fill(val) 快速填充数组,
includes =>原理Ojbect.is(),所以他可以处理数组里面的NaN值,查找某个元素在数组里面,找到返回true,反之false

复制代码
*** 1.哪些方法是改变原来的数组
push pop shift unshift  splice sort reverse

其他返回原数组,或者布尔值,索引
复制代码
*** 2.手写冒泡排序
Array.prototype.mySort = function() {
    for(let i=0;i<this.length-1;i++) {
        for(let k=0;k=this.length-1-i;k++) {
            if(this[k] > this[k+1]) {
                let templ = this[k];
                this[k] = this[k+1];
                this[k+1] = this[k];
            }
        }
    }
    return this;
};
复制代码
*** 3.在数组里面查找NaN
  • indexOf, lastIndexOf, 循环遍历,严格比较(===) 处理不了NaN
  • includes =>Object.is()原理 处理NaN的
*** 4.如何快速创建10000个值都是为1的数组
 let ary = new Array(1000).fill(1);
 console.log(ary);
复制代码
四、数组去重
*** 由于考虑NaN问题,比较会返回false问题,我们一律采用Object.is()方法,查找一律采用includes方法
  • 创建空数组,循环判断进行push, 注意,考虑到NaN最好用includes, 建议不用indexOf过滤不掉的,NaN ===NaN false
    Array.prototype.myUnique = function () {
            let ary = [];
            for (let i = 0; i < this.length; i++) {
                console.log(ary.includes(this[i]))
                if (!ary.includes(this[i])) {
                    ary.push(this[i]);
                }
            }
            return ary;
    }
    let s= ([1, 2, 2, 1, 3, 4, 1, 2, 3,NaN, null,NaN].myUnique())
复制代码
  • 原数组进行排序,相邻进行对比,重复,splice删除,i--
 Array.prototype.myUnique = function () {
           this.sort((a, b) => a-b);

           for(let i=0;i<this.length;i++) {
               if (this[i] === this[i+1]) {    ==>>Object.is(this[i], this[i+1])
                   this.splice(i ,1);
                   i--;
                   continue;
               }
           }
           return this;
        }
        var s= [1, 2, 2, 1, 3, 4, 1, 2, 3,NaN, null,NaN].myUnique();
        
        [null, 1, 2, 3, 4, NaN, NaN]; 去不掉NaN, 因为NaN === NaN;是不相等的,NaN除了数字其他东西,鬼知道呢
        
    ====>> 优化去掉NaN;
         this[i] === this[i+1]不可以排除,我们用Object.is(this[i], this[i+1])不就可以了嘛
复制代码
  • 对象去重复(对象的属性不能重复)
    Array.prototype.myUnique = function () {
        let obj = {};
        for (let i = 0; i < this.length; i++) {
            let cur = this[i];
            if (obj[cur] === cur) {  // ===>> Object.is(obj[cur] === cur)
                this.splice(i, 1);
                i--;
                continue;
            }
            obj[cur] = cur;
        }
        obj = null;  // ===>>释放内存,优化
        return this;  // ===>> 链式调用
    }
    var s = [1, 2, 2, 1, 3, 4, 1, 2, 3, NaN, null, NaN].myUnique();
    s => [1, 2, 3, 4, NaN, null, NaN]
    也是严格对NaN问题,Object.is(obj[cur] === cur)
复制代码
  • es6 [ ...new Set(val) ] set数据解构配合数组拓展符运算符
   Array.prototype.myUnique = function () {
        return [... new Set(this)]
    }
    var s = [1, 2, 2, 1, 3, 4, 1, 2, 3, NaN, null, NaN].myUnique();
    s ==> [1, 2, 3, 4, NaN, null]
复制代码
四、伪数组转为数组
1.伪数组:
  • DOM选择器选择出来的列表
  • 函数的arguments对象
  • jQ里面的选择出来的对象是
2.转换为数组
第一种方法,封装方法,遍历push
function toArray(likeAry) {
    if (likeAry && likeAry.length) {
        let ary = [];
        for (let i = 0; i < this.length; i++) {
            ary.push(this[i]);
        }
        return ary;
    }

    return [];
}
console.log(toArray(document.getElementsByTagName('*')) instanceof Array) // true
复制代码
第二种方法,借助数组原型上的方法slice,截取,改变this执行,上面是slice的封装
  • Array.prototype.slice.call(likeAry);
  • [].slice(likeAry); ==> [].proto..slice
 function fn() {
     arguments = Array.prototype.slice(arguments);
     arguments = Array.from(arguments);
 }
复制代码
第三种方法,es6 Array.from(likeAry);
  function toArray(likeAry) {
      return Array.from(likeAry);
  }
  
复制代码
五、遍历数组方法总结 (面试题)
=>说说for、 for-in、 forEach 、for -of 区别
  • for循环
    • 不会遍历出私有的属性
    • 编程式,知道原理
  • forEach循环
    • 不能return
    • 不能遍历出私有属性
    • 声明式编程, 不知道原理,用即可, vue就是
  • for - in 循环
    • 可以遍历出私有的属性,利用hasOwnproperty()进行过滤
  • for - of循环 ES6完美解决上面问你
    • 可以return
    • 不会遍历出私有的属性
    • 只能遍历数组
  • myForEach封装,就是回调函数(在原型上扩展)
Array.prototype.myForEach = function(callback) {
  if (typeof callback == 'function') {
      for (let i =0;i<this.length;i++) {
          callback.call(this,this[i], i, this);
      }
  }
};

  var ary  = ['vue', 'react', 'angular'];
  ary.myForEach(function(item, index, slef) {
      console.log(item, index, slef)
  });
复制代码
  1.for循环 // ==>> 不会遍历出私有的属性
     let ary = [1, 2, 3];
     ary.b = 100;
     for (let i=0,len=ary.length;i<len;i++) {
          console.log(ary);   
     }
     
  2. forEach // ==>> 不能return,不会遍历出私有的属性
     ary.forEach((item, index, self)=> {
      console.log(item);   
     });
     
  3.for - in   // ==>> key会变成字符串,并且会遍历出私有的属性,利用hasOwnproperty进行过滤
    for(let key in ary) { 
       if (!ary.hasOwnproperty(key)) {
            conosle.log(key)
       }
    }
    
  4.for - of  // ==>> 可以return, 但是必须是数组,不能遍历对象
   for(let key of ary) {  
       
   }
   实现想遍历对象:  Object.keys(); //====>>将一个对象的属性依次放到一个数组中,返回一个新的数组
      let obj = {school:'科师',age:9};
      for (let key of Ojbect.keys(obj) {
          console.log(obj[key]);
      }
复制代码
四、字符串方法
  • es3
chartAt(index) 返回子字符串,index为字符串下标,index取值范围[0,str.length-1]
chatCodeAt(index) 返回子字符串的unicode编码,index取值范围同上

查找方法: 
indexOf(searchString,startIndex)返回子字符串第一次出现的位置,从startIndex开始查找,找不到时返回-1
lastIndexOf(searchString,startIndex) 从由往左找子字符串,找不到时返回-1

截取方法 
substr(start,end) 两个参数都为正数,返回值:[start,end) 也就是说返回从start到end-1的字符
substring(start,end)  返回从 start 到 end(不包括)之间的字符,start、end均为 非负整数。若结束参数(end)省略,则表示从start位置一直截取到最后。
slice 两个参数可正可负,负值代表从右截取,返回值:[start,end)也就是说返回从start到end-1的字符

字符串分割成数组
str.split(separator,limit);  参数1指定字符串或正则,参照2指定数组的最大长度
  - str.split("");  每个字符都被分割  ['','','','']
  - str.split();    整个字符串放到数组里  ['']
  
str.replace(rgExp/substr,replaceText)   返回替换后的字符串

英文转换
toLowerCase() 转小写
toUpperCase() 转大写
复制代码

后续每天更新

一、CSS部分

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值