JavaScript基础知识

目录

1. JS的数据类型

2. 判断数据类型的方法

3. JS的内置对象

4. var、let和const的区别,变量提升

5. new函数的具体实现

6. apply、call、bind的实现

7. arguments和rest参数的区别

8. this指向的改变

   this是指:包含它的函数,作为方法被调用时,所指向的对象;  

9. 箭头函数和普通函数的区别

10. 防抖和节流

11. 遍历方法 for in 、for of 、Object.keys()的区别

12. 新增的Map、Set数据



1. JS的数据类型

基础类型:Number、String、Boolean、Undefined、Null、BigInt、Symbol(独一无二的值);

复杂数据类型:Object;

2. 判断数据类型的方法

(1)typeof 

(2)instanceof

(3)Object.prototype.toString.call() 

(4)constructor

3. JS的内置对象

(1)数据封装类对象:Object、Array、Boolean、Number、String;

(2)其他对象:Function、Math、Date、RegExp、Error;

4. var、let和const的区别,变量提升

(1) var声明的变量会挂载到window上,而let和const声明的变量不会;

var a=100;
console.log(a,window.a);  //100 100

let b=10;
console.log(b,window.b);  //10 undefined

let c=1;
console.log(c,window.c);  //1 undefined

(2) var变量存在变量提升,而let和const没有;

(3) let和const声明形成块作用域;

if(1){
    var a=100;
    let b=10;
    const c=1;
}

console.log(a,b,c) //100 报错:b is not defined  报错:c is not defined

(4) 同一作用域内,let和const不可重复声明;

(5)暂存死区

var a = 100;
if(1){
    a = 10;
    //在当前块作用域中存在a使用let/const声明的情况下,给a赋值10时,只会在当前作用域找变量a,
    // 而这时,还未到声明时候,所以控制台Error:a is not defined
    let a = 1;
}

(6)const一旦声明变量,必须复制,且声明后不可修改其值;

5. new函数的具体实现

function _new(constructor,...args){
        let obj = {};//新建一个空对象
        obj._proto_ = constructor.prototype;//原型链连接
        let res = constructor.apply(obj,...args);//改变this指向
        return res instanceof Object ? res:obj;
}

6. apply、call、bind的实现

(1)apply:数组传参,返回函数执行结果;

apply实现

Function.prototype.myApply = function(context,args){
    if(typeof this !== 'Function'){
       throw new Error('this is not a function');
    }
    
    context = context || window;
    context.fn = this;
    let res;
    if(!args){
       res = context.fn();
    }else{
       res = context.fn(...args);
    }
    delete context.fn; //删除属性,避免副作用
    return res;

}

(2)call:逐个传参,也会返回函数执行结果;

call实现

Function.prototype.myCall = function(context,...rest){
   context = context || window;
   context.fn = this;
   let res = context.fn(...rest);
   delete context.fn;
   return res;
}

(3)bind:不执行,返回一个函数;

bind实现

Function.prototype.myBind = function(context,...rest){
    let self = this;
    return function(){
       return self.apply(context,rest);
    }
}

7. arguments和rest参数的区别

     arguments不是数组,而是一个类数组对象,包含length属性,包含所有可用参数;利用 arguments ,可以获得调用者传入的所有参数;

     arguments转换为数组的方法:Array.prototype.slice.call(argumen);

     而rest数组,是非定义的多余变量数组;

8. this指向的改变

   this是指:包含它的函数,作为方法被调用时,所指向的对象;  

优先级:箭头函数 > new > 显式 > 隐式 > 默认绑定

(1)默认绑定:非严格模式下,指向window对象;严格模式下,为undefined;

(2)隐式绑定:obj.fn;

(3)显式绑定:apply,call,bind方式;

(4)new绑定

9. 箭头函数和普通函数的区别

1. this:箭头函数没有自己的this;

2. arguments:不能使用arguments,改用rest代替;

3. 原型:没有prototype,无法作为构造函数;

4. yeild:箭头函数不能使用yeild;

10. 防抖和节流

(1)防抖:触发高频事件后,N秒内函数只会执行一次,若N秒内再次触发高频事件,则重新计时;

防抖

function debounce(fn,delay){
   let timer =null;
   return function(){
       if(timer)clearTimeout(timer);
       timer = setTimeout(fn,delay);
   }
}

应用场景:

  1. 搜索框输入查询;
  2. 提交按钮;
  3. 浏览器窗口缩放;
  4. 表单验证;

(2)节流:高频事件多次触发,但在N秒内只会执行一次,稀释函数的执行频率;

节流

function throttle(fn,delay){
    let timer = null;
    return function(){
       if(timer)return false;
       timer = setTimeout(()=>{
           fn();
           timer = null;
       },delay);
    }
}

应用场景:

  1. 滚动加载onScroll;
  2. 拖拽事件;
  3. 高频表单提交;

11. 遍历方法 for in 、for of 、Object.keys()的区别

return 语句只能在函数体中,否则会报错

(1) for in:可遍历数组或对象的属性(随机遍历)

遍历数组:除了会遍历数组元素,还会遍历自定义可枚举的属性,以及原型链上可枚举的属性;

Array.prototype.sayLength = function(){
        console.log(this.length);
}//原型链上

let arr = ['a','b','c','d'];
arr.name = '数组'; //自定义属性

Object.defineProperties(arr,{
     type:{
         value:true,
         writable:true,
         enumerable:true
     }
});

for(let i in arr){
     console.log(i); //0,1,2,3,name,type,sayLength
}

(2) Object.keys():遍历对象属性

和 for in 的区别在于:不能遍历原型链上的属性;

(3) for of(ES6新语法):可遍历拥有iterator迭代器对象的集合;

支持遍历数组、类对象、字符串、Set对象、Map对象;

let arr = [0,1,2,3];
for(let i of arr){

}

let person={
    name:'1',
    age:12
}
for(let key of Object.keys(person)){

}
或者
for(let [key,value] of Object.entries(person)){

}

12. 新增的Map、Set数据

(1)Map:一组键值对的结构,具有极快的查找速度;

let _map = new Map([['li',20],['zhao',40]]);

//新增元素
_map.set('zhu',21);

//检测key对应的值是否存在
_map.has('zhu');

//获取key对应的值
_map.get('zhu');

//删除元素
_map.delete('zhu');  //返回true或false

//计算map的长度
Object.getOwnPropertyNames(_map).length;

(2) Set:类似数组,一组key的组合,由于key不重复,故Set成员的值是唯一的,没有重复的值;

注意:在Set中,NaN等于自身;

NaN==NaN    ====> false

let _set = new Set([1,2,3]);

//添加元素
_set.add('li');

//检测是否包含元素
_set.has(1);

//删除元素
_set.delete(1);

//计算set的长度
_set.size;

Set的用法:可用于去除数组重复元素

  1.  [... new Set(arr)];
  2.  Array.from(new Set(arr)); 

(3)WeakSet:类似Set结构,但WeakSet成员只能是对象,且不可遍历,没有size属性;

     WeakSet不能遍历的原因:因为WeakSet的成员都是弱引用,成员不稳定,随时可能消失;

     WeakSet的用处由于垃圾回收机制只在乎强引用,合理使用WeakSet可避免内存泄漏;

    (1)使用WeakSet存储节点,避免节点从文档移除时,导致内存泄漏(即在被移除的节点上绑定的事件等);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值