ES6 基本语法2(class、Set和Map数据结构)

五、class的基本语法
1.类
(1)ES6通过class关键字,可定义类

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}

说明

  • 定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则为实例对象;
  • Point类除了构造方法,还定义了一个toString方法。

  • 定义“类”的方法的时候,前面不需加function这个关键字;
  • 方法之间不需逗号分隔

(2)ES6 的类,可看作构造函数的另一种写法

class Point {
  // ...
}
typeof Point // "function"
Point === Point.prototype.constructor // true

说明类的数据类型就是函数,类本身就指向构造函数

(3)使用时,直接对类使用new命令,跟构造函数的用法完全一致

class Ball {
  doSport() {
    console.log('soccer');
  }
}
var b = new Ball();
b.doSport() // "soccer"

(4)构造函数的prototype属性,在 ES6 的“类”上继续存在
事实上,类的所有方法都定义在类的prototype属性上

class Point {
  constructor() {
    // ...
  }
  toString() {
    // ...
  }
  toValue() {
    // ...
  }
}
// 等同于
Point.prototype = {
  constructor() {},
  toString() {},
  toValue() {},
};

(5)在类的实例上调用方法,其实就是调用原型上的方法

class B {}
let b = new B();
b.constructor === B.prototype.constructor // true

说明:b是B类的实例,它的constructor方法就是B类原型的constructor方法。

(6)类的方法都定义在prototype对象上,所以类的新方法可添加在prototype对象上。Object.assign方法可方便地一次向类添加多个方法

class Point {
  constructor(){
    // ...
  }
}
Object.assign(Point.prototype, {
  toString(){},
  toValue(){}
});

(7)prototype对象的constructor属性,直接指向“类”的本身
这与 ES5 的行为一致

Point.prototype.constructor === Point // true

(8)类的内部所有定义的方法,都是不可枚举的
这与 ES5 的行为不一致

class Point {
  constructor(x, y) {
    // ...
  }
  toString() {
    // ...
  }
}
Object.keys(Point.prototype)
// []
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]

2.constructor方法
(1)constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。
一个类必须有constructor方法,若无显式定义,一个空的constructor方法会被默认添加。

class Point {
}
// 等同于
class Point {
  constructor() {}
}

说明:定义了一个空的类Point,JavaScript 引擎自动为它添加空的constructor方法。

(2)constructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象

class Foo {
  constructor() {
    return Object.create(null);
  }
}
new Foo() instanceof Foo
// false

说明:constructor函数返回一个全新的对象,结果导致实例对象不是Foo类的实例。

(3)类必须使用new调用,否则会报错

(4)es6中属性的定义是在constructor里面,即给属性初始化默认值

3.类的实例
(1)生成类的实例,使用new命令

class Point {
  // ...
}
// 报错
var point = Point(2, 3);
// 正确
var point = new Point(2, 3);

(2)实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)

//定义类
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}
var point = new Point(2, 3);
point.toString() // (2, 3)
point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true

说明:x和y都是实例对象point自身的属性(因为定义在this变量上),所以hasOwnProperty返回true,而toString是原型对象的属性(因为定义在Point类上,类的所有方法都定义在类的prototype属性上),所以hasOwnProperty返回false。

hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中。这个方法只在给定属性存在于对象实例中,才会返回true

4.取值函数(getter)和存值函数(setter)
在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为

class MyClass {
  constructor() {
    // ...
  }
  get prop() {
    return 'getter';
  }
  //存值需带参
  set prop(value) { 
    console.log('setter: '+value);
  }
}
let inst = new MyClass();
//先设置再获取
inst.prop = 123;
// setter: 123

inst.prop
// 'getter'

说明:prop属性有对应的存值和取值函数,因此赋值和读取行为都被自定义了。

六、Set和Map数据结构
1.Set
基本用法
(1)类似于数组,但是成员的值都是唯一的,没有重复的值(可做数组去重)

let smap=new Set([1,2,3,1,2,3]);
console.log(smap);  //Set(3) {1, 2, 3}

(2)Set本身是一个构造函数,用来生成 Set 数据结构

let s=new Set();
let a=[1,2,5,2,6,4,6];
a.forEach(function(v){
     s.add(v);
});
console.log(s);  //Set(5) {1, 2, 5, 4, 6}

说明:通过add()方法向 Set 结构加入成员,结果表明 Set 结构不会添加重复的值

(3)去数组重复成员的方法

// 去除数组的重复成员
[...new Set(array)]

(4)去字符串里的重复字符

let a=[...new Set('ababbc')].join('');
console.log(a);  //abc

(5)两个对象总是不相等的

let set = new Set();
set.add({});
console.log(set.size); // 1
set.add({});
console.log(set.size); // 2

说明:由于两个空对象不相等,所以它们被视为两个值。

Set 实例的属性和方法
(1)属性

  • Set.prototype.constructor:构造函数,默认就是Set函数;
  • Set.prototype.size:返回Set实例的成员总数

(2)方法

  • add(value):添加某个值,返回 Set 结构本身;
  • delete(value):删除某个值,返回一个布尔值,表示删除是否成功;
  • has(value):返回一个布尔值,表示该值是否为Set的成员;
  • clear():清除所有成员,没有返回值

例:属性和方法的实例如下

s.add(1).add(2).add(2);
// 注意2被加入了两次

s.size // 2

s.has(1) // true
s.has(2) // true
s.has(3) // false

s.delete(2);
s.has(2) // false

(3)Array.from方法可以将 Set 结构转为数组

const items = new Set([1, 2, 3, 4, 5]);
const array = Array.from(items);

(4)去数组重复成员的另一种方法

function deput(array) {
  return Array.from(new Set(array));
}
deput([1, 1, 2, 3]) // [1, 2, 3]

遍历操作

  • keys():返回键名的遍历器
  • values():返回键值的遍历器
  • entries():返回键值对的遍历器
  • forEach():使用回调函数遍历每个成员

(1)keys(),values(),entries()

let set = new Set(['red', 'green', 'blue']);
for (let item of set.keys()) {
  console.log(item);
}
// red
// green
// blue
for (let item of set.values()) {
  console.log(item);
}
// red
// green
// blue
for (let item of set.entries()) {
  console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

说明:entries方法返回的遍历器,同时包括键名和键值,所以每次输出一个数组,它的两个成员完全相等。

可以省略values方法,直接用for…of循环遍历 Set:

let set = new Set(['red', 'green', 'blue']);
for (let x of set) {
  console.log(x);
}
// red
// green
// blue

(2) forEach()
Set 结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值。

let set = new Set([1, 4, 9]);
set.forEach((value, key) => console.log(key + ' : ' + value))
// 1 : 1
// 4 : 4
// 9 : 9

说明:该函数的参数与数组的forEach一致,依次为键值、键名、集合本身。
Set 结构的键名就是键值(两者是同一个值),因此第一个与第二个参数的值永远是一样的。

2.Map
基本用法
(1)类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键
例:类似于存值

let m=new Map();
let s={name:"张三",sex:"男"};
m.set('stu',s);
console.log(m.get('stu'));  //{name: "张三", sex: "男"}
console.log(m.has('stu'));  //true

例:如何向 Map 添加成员

const m=new Map();
const o={p: 'Hello World'};
m.set(o, 'content');
console.log(m.get(o)); // content
m.has(o);   // true
m.delete(o);   // true
m.has(o);   // false

说明:使用 Map 结构的set方法,将对象o当作m的一个键,然后又使用get方法读取这个键,接着使用delete方法删除了这个键。

(2)作为构造函数,Map 也可以接受一个数组作为参数
该数组的成员是一个个表示键值对的数组。

const map = new Map([
  ['name', '张三'],
  ['title', 'Author']
]);
map.size;   // 2
map.has('name');   // true
map.get('name');   // "张三"
map.has('title');   // true
map.get('title');   // "Author"

说明:在新建 Map 实例时,就指定了两个键name和title。

(3)Map构造函数接受数组作为参数
例:模式匹配器存值

const items = [
  ['name', '张三'],
  ['title', 'Author']
];
const map = new Map();
items.forEach(
  ([key, value]) => map.set(key, value)
);

实例的属性和操作方法
(1)size 属性
返回 Map 结构的成员总数

(2)set(key, value)
设置键名key对应的键值为value,然后返回整个 Map 结构。若key已有值,则键值会被更新,否则新生成该键。

(3)get(key)
读取key对应的键值,若找不到key,返回undefined。

(4)has(key)
返回一个布尔值,表示某个键是否在当前 Map 对象之中。

(5)delete(key)
删除某个键,返回true;若删除失败,返回false。

(6)clear()
清除所有成员,没有返回值。

猜你喜欢

转载自blog.csdn.net/weixin_43675447/article/details/88665613