ES6学习笔记

这篇博客详细介绍了ES6的关键特性,包括let和const的声明方式,防止变量提升和作用域污染;解构赋值和集合Set的使用;for of循环遍历字符串和数据结构;深拷贝的实现,探讨了JSON.stringify()的限制;defineProperty用于对象属性的动态定义;Proxy代理实现对象操作拦截;Reflect对象提供与Proxy相似的功能;Symbol作为唯一标识的常量;以及class类的介绍,探讨了原型链和构造函数。同时提到了JavaScript中的微任务和宏任务概念。
摘要由CSDN通过智能技术生成

1、let const(新增)

es6 -> es5 babel

  1. 声明的变量默认声明到全局上,全局作用域  函数作用域  {} 作用域+ let  实现一个作用域
  2.  用var 声明的变量会导致变量提升 var function import。用let声明的变量会绑定到当前作用域  暂存死区
  3. var a = 1 var a = 2; 使用let 可以保证我的代码命名不重复
  4. var 声明的变量可以更改 var a = 1 a =100。
  5. 自执行函数可以解决作用域问题
  6. js 事件 不要用var
for (let i = 0; i < 10; i++) {
    setTimeout(()=>{
        console.log(i)   
    }); // 4ms 
};

2、解构赋值 ...   集合 Set

解构的方式都是根据key来实现

// 解构的方式都是根据key来实现
let [,age] = ['姓名','年龄'];
console.log(age);


// 用:号来重新命名  = 可以用来赋值默认值
let {name,age:age1,address="CN"} = {name:'xx',age:10};
console.log(name,age1,address);


// 剩余运算符  只能用在最后一项
let [,...args] = ['xx',10,'CN']; // slice
console.log(args);

// 对象的剩余运算符
let {name,...args} = {name:'珠峰',age:10};
console.log(args);
// (set + map) set 和map 是es6中新的数据类型 不能放重复的
let set = new Set([1,2,3,3,2,1]);
console.log(set); // 没有key属性

set.add(4);
// set.clear()// 清除
// set.delete(); // 删除某一项
console.log(set.entries()) // Object.entries Object.keys   Object.values

// Symbol.iterator
set.forEach(item=>{
    console.log(item);
})
console.log(set.has(1))


// union
let a1 = [1,2,3];
let a2 = [4,5,6,1,2,3];
// let s1 = new Set([...a1,...a2]);
// console.log([...s1]);

// 数组的交集  和 差集 has来实现  set方法只有forEach方法
let s1 = new Set([...a1]); // [1,2,3]
let s2 = new Set([...a2]); // [1,2,3]
let a3 = [...s2].filter((item=>{ // 返回的是一个新的数组
   return  !s1.has(item); // map是映射一个新的数组 但是不会比以前的项少 
}));
console.log(a3);
// map 和set 用法基本一致

3、for of 字符串遍历

    let str = "hello";
    //1.for遍历
    for (let i = 0; i < str.length; i++) {
        console.log(i, str[i]);     //i 索引    数值类型
    }
    
    //2.数组->for->for in
    let arr = [1, 2, 3];
    for (let i in arr) {
        console.log(i, arr[i]);     //i 索引    字符串类型
    }
    
    //3.for... of
    for(let i of str){
        console.log(i);     //数据
    }
    
    //4.解构
    let [a, b, c, d ,e] = str;
    console.log(a, b, c, d ,e);

4、深拷贝

Q:怎么判断数据的类型?

        typeof object Array

        Object.prototype.toString.call()

        instanceof 可以判断类型 判断是谁的实例

        constructor 构造函数

 递归实现深拷贝

let school = {
  name: "珠峰",
  age: 10,
  a: { b: 2 },
  fn: () => {},
  c: undefined,
  reg: /\d+/
};
const deepClone = (value ,hash = new WeakMap) => {
    if(value == null) return value; // 排除掉null 和undefine 的情况
    if(typeof value !== 'object') return value; // 这里包含了函数类型
    if(value instanceof RegExp) return new RegExp(value);
    if(value instanceof Date) return new Date(value);
    // .....
    // 拷贝的人可能是一个对象 或者是一个数组 (循环)  for in 
    let instance = new value.constructor; // 根据当前属性构造一个新的实例
    if(hash.has(value)){ // 先去hash中查看一下是否存在过 ,如果存在就把以前拷贝的返回去 
        return hash.get(value); // 返回已经拷贝的结果
    }
    hash.set(value,instance);// 没放过就放进去
    // 用一个对象来记忆
    for(let key in value){ // 一层
        if(value.hasOwnProperty(key)){ // 将hash 继续向下传递 保证这次拷贝能拿到以前拷贝的结果
            instance[key] = deepClone(value[key],hash); // 产生的就是一个新的拷贝后的结果
        }// 过滤掉原型链上的属性
    }
    return instance
};
let obj = {a:1};
obj.b = obj; // 如果obj 已经被拷贝了一次 那下次 在用到obj的时候 直接返回就好了 不需要再次拷贝了
console.log(deepClone(obj));

JSON.parse(JSON.stringify(a)) 转换也可以实现深拷贝,但是数据中有数值类型可能会有精度缺失的问题。不能拷贝正则,Date,方法函数等。

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

5、defineProperty

用在对象上设新属性,在ES6中,由于 Symbol类型的特殊性,用Symbol类型的值来做对象的key与常规的定义或修改不同,而Object.defineProperty 是定义key为Symbol的属性的方法之一。

let obj = {}
let val = '';
Object.defineProperty(obj,'a',{
    configurable:true, // 是否可删除
    // writable:true, // 是否可写,
    enumerable:true, // for in 原型上的方法
    get(){
        return val
    },
    set(value){
        val = value;
    }
    // 默认设置的值是不可枚举的
})
delete obj.a
console.log(obj);

6、Proxy代理

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

// 代理 我们可以创造一个代理 帮我们干某些事
let obj = {
    a:{a:2}
}
let handler = { // 只能代理当前这个对象 1层
    get(target,key){ // 有13中属性 symbol 11种
        // return target[key]
        if(typeof target[key] === 'object'){
            return new Proxy(target[key],handler); // 如果是对象 就返回这个对象的代理
        }
       return Reflect.get(target,key);
    },
    set(target,key,value){ // 反射属性
        // target[key] = value;
        if(key === 'length') return true;
        console.log('update');
        return  Reflect.set(target,key,value);
    }
}
let proxy = new Proxy(obj,handler)
proxy.a.a = 100
console.log(obj.a.a);
// 支持数组 可以直接更改数组 达到拦截的目的

7、Reflect

Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与proxy handlers 的方法相同。Reflect不是一个函数对象,因此它是不可构造的。

  1. get/set
  2. has
  3. defineProperty
  4. getOwnPropertyDescriptor
  5. ownKeys
  6. setPrototypeOf, getPrototypeOf
  7. 函数的apply方法

        Q:  bind、apply、call区别

        bind传参“~”,call、apply传参是数组形式。第一个是改变this指向。

// 2) has
// 老的写法
console.log('a' in {a:1});
// 新的写法
console.log(Reflect.has({a:1},'a'));

// 3)defineProperty
const obj = {a:1}
// Object.freeze(obj); // 这个属性就能不能配置了   冻结freeze
let flag = Reflect.defineProperty(obj,'a',{
    value:100
})
console.log(flag);

8、Symbol

        独一无二,用作常量

        hasInstance、 toPrimitive、 toStringTag、 species、 unscopables、 isConcatSpreadable

9、class类

         es5中没有类 用构造函数来模拟类
       

 原型链 

 __proto__ 指向所属类的原型

 prototype 所有类都有一个prototype属性

constructor prototype.constructor 每个类的原型上都有这个属性

微任务: promise.then ,MutationObserver,

宏任务:script ,ajax , 事件,requestFrameAnimation, setTimeout ,setInterval ,setImmediate (ie下),MessageChannel ,UI rendering。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值