ECMAScript 新特性(es6)的学习二

Proxy代理对象
如果想要监视某个对象中的属性的变化可以使用es5中的Object.defineProperty,在es6中增加了Proxy,专门用来为对象设置访问代理器。

const person = {
    name: 'qsn',
    age: 20
};

const personProxy = new Proxy(person, {
    get(target, property) {
        return property in target ? target[property] : 'default';
    },
    set(target, property, value) {
        if (property == 'age') {
            if (!Number.isInteger(value)) {
                throw new TypeError(`${value} is not an int`);
            }
        }
        target[property] = value;
    }
});
personProxy.age = 18;
console.log(personProxy);
console.log(personProxy.xxx);

在这里插入图片描述

Set的三个入参:代理目标对象,要写入的名称,要写入的属性值

Proxy对比defineProperty
defineProperty只能监视对象属性的读写,Proxy能够监视到更多对象操作,如delete操作

const person = {
    name: 'qsn',
    age: 20
};

const personProxy = new Proxy(person, {
    deleteProperty(target, property) {
        console.log('delete', property);
        delete target[property];
    }
});
delete personProxy.name;
console.log(personProxy);

在这里插入图片描述
Proxy更好的支持数组对象的监视,以住通过Object. defineProperty监视数组的操作最常见的就是重写数组的操作方法,也是vue.js中使用的方式,大体的思路是通过自定义的方法覆盖掉原型对象上的Push,shift等方法,以此来劫持这个方法调用的过程。
使用Proxy对象监视数组

const list = []

const listProxy = new Proxy(list, {
    set(target, property, value) {
        console.log("set", property, value);
        target[property] = value;
        return true; //表示添加成功
    }
});

listProxy.push(100);
console.log(listProxy);

在这里插入图片描述
Proxy是以非侵入的方式监管了对象的读写,意思是已经定义好的对象,不需要对对象进行任何的操作,就可以监视到内部成员的读写 ,而Object.defineProperty必须要通过特定的方式单独去设定属性去监听不同的操作

Reflect 统一的对象操作API
Reflect属于一个静态类,不能通过new的方式建一个实例对象,只能通过这个静态类去调用静态方式。和js中的Math对象类似,Reflect内部封装了一系列对对象的底层操作(14个方法,其中一个废弃)。
Reflect成员方法就是Proxy处理对象的默认实现

const obj = {
    name: "qsn",
    age: 18
};

const objProxy = new Proxy(obj, {
    get(target, property) {
        console.log("watch logic");
        return Reflect.get(target, property);
    }
});
console.log(objProxy.name);

在这里插入图片描述
Reflect最大的作用就是统一提供一套用于操作对象的API

const obj = {
    name: "qsn",
    age: 18
};

// console.log('name' in obj);
// console.log(delete obj['age']);
// console.log(Object.keys(obj));

console.log(Reflect.has(obj, 'name'));
console.log(Reflect.deleteProperty(obj, 'age'));
console.log(Reflect.ownKeys(obj));

在这里插入图片描述
Promise
一种更优的异步编程解决文案,解决了传统异步编程中回调函数嵌套过深的问题.
具体可以查看我之前发布的文章
js异步编程二:promise链式调用,异常处理,静态方法,并行和执行时序

Class类

//原始方法
// function Person(name) {
//     this.name = name;
// }

// Person.prototype.say = function() {
//     console.log(`hi,my name is ${this.name}`);
// }
// new Person("qsn").say();

class Person {
    constructor(name) {
        this.name = name;
    }
    say() {
        console.log(`hi,my name is ${this.name}`);
    }
}

const p = new Person("qsn1");
p.say();

静态方法static
方法分为实例方法和静态方法,实例方法通过这个类型构造的实例对象去调用,而静态方法则是直接通过类型本身去调用,
以前实现静态方法直接在构造函数对象上挂载方法来实现,因为在js中函数也是对象,也可以增加一些方法成员。
Es6中新增添加静态成员的static着关键词

class Person {
    constructor(name) {
        this.name = name;
    }
    say() {
        console.log(`hi,my name is ${this.name}`);
    }
    static create(name) {
        return new Person(name);
    }
}

const p = Person.create("qsn");
p.say();

在这里插入图片描述
类的继承extends

class Person {
    constructor(name) {
        this.name = name;
    }
    say() {
        console.log(`hi,my name is ${this.name}`);
    }
}

class Status extends Person {
    constructor(name, number) {
        super(name);
        this.number = number;
    }
    hello() {
        super.say();
        console.log(`my school number is ${this.number}`);
    }
}

const p = new Status("qsn", 12);
p.hello();

Super是访问父成员

Set数据结构
Set集合和数组非常类似,不过set内部的成员是不允许重复的

const s = new Set();
s.add(1).add(2).add(3).add(2);
console.log(s);

在这里插入图片描述
因为返回的值是这个对象的本身,所以可以链式的去调用,当添加了重复的值后会被忽略

const s = new Set();
s.add(1).add(2).add(3).add(2);

// s.forEach(i => console.log(i));
for (let i of s) {
    console.log(i);
}
console.log(s.size);

在这里插入图片描述
可以用of去遍历set,size是长度

s.has(100);
s.delete(3);
s.clear();

Has方法是判断是否存在某个值
删除,返回的是true或false,clear清空所有数据
Set最常见的场景就是用来给数组去重,去重再转成数组

const arr = [1, 2, 3, 2, 2, 5];
const newarr = [...new Set(arr)];
console.log(newarr)

在这里插入图片描述
Map数据结构
和对象比较像,但是对象的键只能是字符串类型、map可以是任意类型.
普通的对象:

const obj = {};
obj[true] = 1;
obj[123] = 2;
obj[{ "a": 1 }] = 3;
console.log(Object.keys(obj));

在这里插入图片描述
都被传成了字符串,map可以是任意的类型

const obj = new Map();

const tom = {
    "a": 1
};
obj.set(tom, 1);
obj.forEach((value, key) => console.log(key, value));

在这里插入图片描述
Symbol一种全新的原始数据类型
表示一个独一无二的值,避免对象属性名重复,传入字符串表示描述文本

console.log(
    Symbol() === Symbol()
);
console.log(Symbol('foo'));
console.log(Symbol('bar'));
console.log(Symbol('baz'));

const obj = {};
obj[Symbol()] = '123';
obj[Symbol()] = '456';
console.log(obj);

const obj1 = {
    [Symbol()]: 123
};
console.log(obj1);

在这里插入图片描述
也可以借助这个类型的特点模拟实现对象的私有成员

const name = Symbol();
const person = {
    [name]: 'zce',
    say() {
        console.log(this[name]);
    }
}
person.say();

在这里插入图片描述
因为没办法得到一样的symbol值,所以name只能在内部被访问到,
最主要的作用就是为对象添加独一无二的属性名。

const s1 = Symbol.for('foo');
const s2 = Symbol.for('foo');
console.log(s1 === s2);

在这里插入图片描述
Symbol.for传入的值是一样的,返回的symbol值也是一样的,这个方法内部维护了一个全局的注册表,为字符串和值提供了一一对应的关系,需要注意的是在这个方法内部维护的是字符串和symbol之间的对应关系,如果传的不是字符串会自动转换成字符串

const obj = {
    [Symbol()]: 'symbol value',
    foo: 'normal value'
};
console.log(Object.getOwnPropertySymbols(obj));

在这里插入图片描述
For…of循环
作为遍历所有数据结构的统一方式

const arr = [100, 200, 300, 400];
for (const item of arr) {
    console.log(item);
    if (item > 100) {
        break;
    }
}

在这里插入图片描述

const m = new Map();
m.set('foo', 123);
m.set('bar', '345');
for (const [key, value] of m) {
    console.log(key, value);
}

在这里插入图片描述
可迭代接口
Es中能够表示有结构的数据类型越来越多,为了给各种各样的数据结构提供统一遍历方式,es2015提供了Iterable接口,实现Ierable接口就是for…of的前提

// 迭代器(Iterator)

const set = new Set(['foo', 'bar', 'baz'])

const iterator = set[Symbol.iterator]()

// console.log(iterator.next())
// console.log(iterator.next())
// console.log(iterator.next())
// console.log(iterator.next())
// console.log(iterator.next())

while (true) {
  const current = iterator.next()
  if (current.done) {
    break // 迭代已经结束了,没必要继续了
  }
  console.log(current.value)
}

在这里插入图片描述
实现可迭代接口

const obj = {
    store: ['foo', 'bar', 'baz'],

    [Symbol.iterator]: function() {
        let index = 0
        const self = this

        return {
            next: function() {
                const result = {
                    value: self.store[index],
                    done: index >= self.store.length
                }
                index++
                return result
            }
        }
    }
}

for (const item of obj) {
    console.log('循环体', item)
}

在这里插入图片描述
迭代器模式

// 迭代器设计模式

// 场景:你我协同开发一个任务清单应用

// 我的代码 ===============================

const todos = {
    life: ['吃饭', '睡觉', '打豆豆'],
    learn: ['语文', '数学', '外语'],
    work: ['喝茶'],

    // 提供统一遍历访问接口
    each: function(callback) {
        const all = [].concat(this.life, this.learn, this.work)
        for (const item of all) {
            callback(item)
        }
    },

    // 提供迭代器(ES2015 统一遍历访问接口)
    [Symbol.iterator]: function() {
        const all = [...this.life, ...this.learn, ...this.work]
        let index = 0
        return {
            next: function() {
                return {
                    value: all[index],
                    done: index++ >= all.length
                }
            }
        }
    }
}

// 你的代码 ===============================

// for (const item of todos.life) {
//   console.log(item)
// }
// for (const item of todos.learn) {
//   console.log(item)
// }
// for (const item of todos.work) {
//   console.log(item)
// }

todos.each(function(item) {
    console.log(item)
})

console.log('-------------------------------')

for (const item of todos) {
    console.log(item)
}

在这里插入图片描述
当你知道当前的数据结构时可以这样去遍历,在todos里再增加一个数据时,遍历又要增加
对外提供统一的遍历接口
生成器Generator
避免在异步编程中回调嵌套过深,提供更好的异步编程解决方案

// Generator 函数

// function * foo () {
//   console.log('zce')
//   return 100
// }

// const result = foo()
// console.log(result.next())

function* foo() {
    console.log('1111')
    yield 100
    console.log('2222')
    yield 200
    console.log('3333')
    yield 300
}

const generator = foo()

console.log(generator.next()) // 第一次调用,函数体开始执行,遇到第一个 yield 暂停
console.log(generator.next()) // 第二次调用,从暂停位置继续,直到遇到下一个 yield 再次暂停
console.log(generator.next()) // 。。。
console.log(generator.next()) // 第四次调用,已经没有需要执行的内容了,所以直接得到 undefined

在这里插入图片描述
最大的特点是惰性执行,执行一次next执行到yield停一下。
生成器应用

// Generator 应用

// 案例1:发号器

function * createIdMaker () {
  let id = 1
  while (true) {
    yield id++
  }
}

const idMaker = createIdMaker()

console.log(idMaker.next().value)
console.log(idMaker.next().value)
console.log(idMaker.next().value)
console.log(idMaker.next().value)

// 案例2:使用 Generator 函数实现 iterator 方法

const todos = {
  life: ['吃饭', '睡觉', '打豆豆'],
  learn: ['语文', '数学', '外语'],
  work: ['喝茶'],
  [Symbol.iterator]: function * () {
    const all = [...this.life, ...this.learn, ...this.work]
    for (const item of all) {
      yield item
    }
  }
}

for (const item of todos) {
  console.log(item)
}

在这里插入图片描述
Es2016概述,增加了includes和pow

// ECMAScript 2016

// Array.prototype.includes -----------------------------------

// const arr = ['foo', 1, NaN, false]

// 找到返回元素下标
// console.log(arr.indexOf('foo'))
// 找不到返回 -1
// console.log(arr.indexOf('bar'))
// 无法找到数组中的 NaN
// console.log(arr.indexOf(NaN))

// 直接返回是否存在指定元素
console.log(arr.includes('foo'))
    // 能够查找 NaN
console.log(arr.includes(NaN))

// 指数运算符 ---------------------------------------------------

console.log(Math.pow(2, 10))//2的10次方

Es2017概述
增加了values,entries,等方法

// ECMAScript 2017

const obj = {
    foo: 'value1',
    bar: 'value2'
}

// Object.values -----------------------------------------------------------

console.log(Object.values(obj))

// Object.entries ----------------------------------------------------------

console.log(Object.entries(obj))

for (const [key, value] of Object.entries(obj)) {
    console.log(key, value)
}

console.log(new Map(Object.entries(obj)))

// Object.getOwnPropertyDescriptors ----------------------------------------

const p1 = {
    firstName: 'Lei',
    lastName: 'Wang',
    get fullName() {
        return this.firstName + ' ' + this.lastName
    }
}

// console.log(p1.fullName)

// const p2 = Object.assign({}, p1)
// p2.firstName = 'zce'
// console.log(p2)

const descriptors = Object.getOwnPropertyDescriptors(p1)
    // console.log(descriptors)
const p2 = Object.defineProperties({}, descriptors)
p2.firstName = 'zce'
console.log(p2.fullName)

// String.prototype.padStart / String.prototype.padEnd  --------------------

const books = {
    html: 5,
    css: 16,
    javascript: 128
}

// for (const [name, count] of Object.entries(books)) {
//   console.log(name, count)
// }

for (const [name, count] of Object.entries(books)) {
    console.log(`${name.padEnd(16, '-')}|${count.toString().padStart(3, '0')}`)
}

// 在函数参数中添加尾逗号  -----------------------------------------------------

function foo(
    bar,
    baz,
) {

}

const arr = [
    100,
    200,
    300,
]
const arr = [
    100,
    200,
    300,
    400,
]
const arr = [
    100,
    200,
    300
]
const arr = [
    100,
    200,
    300,
    400
]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值