Symbol
es6引入了一种新的原始数据类型Symbol,表示独一无二的值。
js语言的第七种数据类型,是一种类似于字符串的数据类型。
特点:
- Symbol的值是唯一的,用来解决命名冲突。
- Symbol的值不能与其他数据类型进行运算。
- Symbol定义的对象属性不能使用for…in循环遍历,但是可以用Reflect.ownkeys来获取对象的所有键名。
应用:向对象中添加属性或方法
var s1 = Symbol('lyz');
var s2 = Symbol('lyz');
console.log(s1 === s2); // false
//Symbol.for()通过描述字符串(括号中的值)创建唯一的值
var s3 = Symbol.for('lyz');
var s4 = Symbol.for('lyz');
console.log(s3 === s4); // true
//向game中添加up和down方法(不确定game中是否有这两种命名的属性值)
var game = {
up: '向上',
down: '向下',
name: '超级马里奥'
}
var op = {
up: Symbol(),
down: Symbol()
}
game[op.up] = function () {
console.log('up');
}
game[op.down] = function () {
console.log('down');
}
game[op.up]();
var say = Symbol('say');
var close = Symbol('close');
// var youxi = {
// name: '狼人杀',
// [Symbol('say')]: function () {
// console.log('say');
// },
// [Symbol('close')]: function () {
// console.log('close eyes');
// }
// }
var youxi = {
name: '狼人杀',
say: function () {
console.log('say');
},
close: function () {
console.log('close eyes');
}
}
console.log(youxi);
youxi.say();
迭代器Iterator
迭代器是一种接口,为各种不同的数据结构提供访问机制。
任何数据结构只需要部署Iterator接口(对象中的一个属性,属性名为Symbol.iterator),就可以完成遍历。
es6创建的新遍for…of循环,Iterator接口主要为for…of消费
let arr = ['lyz', 'lyj', 'my'];
//使用for...of遍历数组
/*
for...in 保存键名 仅仅是对对象遍历有用
for...of 保存键值
*/
for (let v of arr) {
console.log(v); //lyz lyj my
}
工作原理:
- 创建一个指针对象,指向当前数据结构的起始位置。
- 第一次调用对象的next方法,指针自动指向数据结构的第一个成员。
- 接下来不断调用next方法,指针一直往后移动,直到指向成员的最后一个成员。
- 每调用next方法,返回一个包含value和done属性对象。(done为false时,说明)
let iterator = arr[Symbol.iterator]();
console.log(iterator);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
自定义遍历数据:
const obj = {
name: 'lyz',
like: ['my', 'lyj', 'glnz'],
[Symbol.iterator]() {
let index = 0;
let _this = this;
return {
next(){
if (index < _this.like.length) {
const result = {value: _this.like[index],done: false};
index++;
return result;
}else {
const result = {value: undefined,done: true};
return result;
}
}
}
}
}
for(let v of obj) {
console.log(v);
}
Promise
Promise是es6引入的异步编程的新解决方案,语法上Promise是构造函数,用来封装异步操作,并且可以获取其成功或错误的结果。
主要作用是用来解决JS异步机制里,回调机制产生的“回调地狱”。
/*
resolve() 正确信息
reject() 错误信息
*/
const p = new Promise(function (resolve, reject) {
let data = '数据';
resolve(data);
})
p.then(function(res){
console.log(res);
}, function () {
})
例子:promise读取文件
const fs = require('fs');
const p = new Promise(function (resolve, reject) {
fs.readFile('01.htmla', (err, data) => {
//如果失败
if (err) reject(err);
//如果成功
resolve(data);
});
});
p.then(function (data) {
console.log(data.toString());
}, function (err) {
console.log('读取失败');
})
promise封装ajax
const p = new Promise((resolve, reject) => {
//创建对象
const ajax = new XMLHttpRequest();
//初始化
ajax.open('get', 'https://api.apiopen.top/getJoke');
//发送
ajax.send();
//绑定事件 处理响应结果
ajax.onreadystatechange = function () {
if (ajax.readyState == 4) {
if (ajax.status == 200) {
resolve(ajax.response);
}else {
reject(ajax.status);
}
}
}
});
//指定回调
const result = p.then(function (res) {
console.log(res);
}, function (err) {
console.log(err);
})
console.log(result);
then方法返回的是Promise对象,对象的状态是由回调函数的执行结果决定。
- 返回的是非promise类型的属性,状态为成功,返回值为对象的成功值。
- 返回的值为promise类型,返回的状态决定then方法的返回值状态。
- 可以链式
promise读取多个文件
const fs = require('fs');
const p = new Promise((resolve, reject) =>{
fs.readFile('01.html', (err, data) =>{
resolve(data);
})
});
p.then(res => {
return new Promise((resolve, reject) => {
fs.readFile('02_箭头函数.html', (err, data) => {
resolve([res, data]);
})
});
}).then(res =>{
return new Promise((resolve, reject) =>{
fs.readFile('03_reset参数.html', (err, data) =>{
res.push(data);
resolve(res);
})
})
}).then(res =>{
console.log(res.join());
})
集合Set
es6提供了新的数据结构set(集合),类似于数组。但成员的值都是唯一的,集合实现了Iterator接口,所以可以使用扩展运算符和for…of进行遍历。
let s = new Set();
console.log(typeof s); //object
let s2 = new Set(['lyz', 'my', 'lyj', 'lyz', 'my', 'glnz']);
console.log(s2);
//添加
s2.add('lyf');
console.log(s2);
//删除
s2.delete('my');
console.log(s2);
//检测
console.log(s2.has('glnz'));
//遍历
for (let v of s2) {
console.log(v);
}
s2.clear();
console.log(s2);
let arr = [1, 2, 4, 6, 2, 5];
let arr2 = [7, 6, 3, 7, 4, 2];
//去重
let newArr = [...new Set(arr)];
console.log(newArr);
//交集
// let intersection = [...new Set(arr)].filter(item =>{
// let new_arr = new Set(arr2);
// if (new_arr.has(item)) return true;
// else return false;
// })
let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
console.log(result);
//并集
let union = [...new Set([...new Set(arr), ...new Set(arr2)])];
console.log(union);
//差集
let result1 = [...new Set(arr2)].filter(item => !(new Set(arr).has(item)));
console.log(result1);
Map
es6提供了Map数据结构,它类似与对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值都可以(包括对象)都可以作为键。Map也实现了Iterator接口,所以可以使用扩展运算符和for…of进行遍历。
let m = new Map();
//添加
m.set('name', 'lyz');
m.set('age', 21);
m.set({
name: 'my',
age: 22
}, ['99, 100']);
console.log(m);
//删除
m.delete('name');
console.log(m);
//清空
console.log(m.clear());
let m = new Map();
m.set('name', 'lyz');
m.set('age', 21);
m.set({
name: 'my',
age: 22
}, ['99, 100']);
for (let v of m) {
console.log(v);
} //遍历结果是数组
for (let v of m.keys()) {
console.log(v);
} //遍历结果是属性
for (let v of m.values()) {
console.log(v);
} //遍历结果是属性值
Class类
es6提供了更接近传统语言(Java/C++)的写法,引入了class(类)这个概念,作为对象的模版,通过class关键字,可以定义类。ea6的class可以看作是语法糖,他绝大部分功能是在ea5中可以实现的。新的class写法只是让对象原型的写法更加清晰,更加面向对象编程的语言而已。
class Phone {
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
call() {
console.log('call');
}
}
var p = new Phone('华为', 1999);
console.log(p); //Phone {brand: "华为", price: 1999}
console.log(p.brand); //华为
p.call(); //call
静态(static)成员,只能被类调用(只属于类),不能被类的实例对象调用。
class Phone {
//静态属性 只能用类调用 (只属于类 不属于实例对象)
static name = 'lyz';
static change(){
console.log('change');
}
}
console.log(Phone.name); //lyz
Phone.change(); //change
var p = new Phone();
console.log(p.name); //undefined(谷歌浏览器)
// p.change() //报错
继承
- es5
function Phone(brand, price) {
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function () {
console.log('call');
}
function SmartPhone(brand, price, color, size) {
//用call方法改变this指向
Phone.call(this, brand, price);
this.color = color;
this.size = size;
}
//建立子级构造函数的原型
SmartPhone.prototype = new Phone();
SmartPhone.prototype.photo = function () {
console.log('photo');
}
let sp = new SmartPhone('iphone', '10000', 'white', '5inch');
sp.call(); //call
sp.photo(); //photo
console.log(sp);
- es6
class Phone1 {
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
call() {
console.log('call');
}
}
class SmartPhone1 extends Phone1 {
constructor(brand, price, color, size) {
super(brand, price);
this.color = color;
this.size = size;
}
photo() {
console.log('photo');
}
}
let smart = new SmartPhone1('huawei', '1699', 'white', '5inch');
console.log(smart);
smart.call();//call;
smart.photo(); //photo;
子类对父类方法的重写
//es6继承
class Phone1 {
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
call() {
console.log('call');
}
}
class SmartPhone1 extends Phone1 {
constructor(brand, price, color, size) {
super(brand, price);
this.color = color;
this.size = size;
}
call() {
//子类成员方法中不能调用父类的重名方法
console.log('smart_call');
}
photo() {
console.log('photo');
}
}
let smart = new SmartPhone1('huawei', '1699', 'white', '5inch');
console.log(smart);
smart.call();//call;
SmartPhone1.photo(); //photo;
getter/setter的设置 对对象属性进行方法的绑定
getter: 对某一属性进行获取时,执行get对应的函数。只要读取该属性时,就会执行函数里的代码,函数的返回值就是属性的值。(对对象的动态属性进行封装 eg:总数/平均值等)
setter:对某一属性进行设置时,执行set对应对函数,必须传值。(eg:判断/修改等)
class Per {
get like() {
console.log('eat');
}
set like(newVal) {
console.log('修改like');
}
}
let per = new Per();
per.like = 'happy';
console.log(per.like);
对象方法扩展
- Object.is() 判断两个值是否完全相等,与===类似,但是对NaN的比较有偏差。
console.log(Object.is(123, 432));; //false
console.log(Object.is(NaN, NaN));//true
console.log(NaN === NaN); //false
- Object.assign() 对象的合并。后面的对象会覆盖前面的,没有相同的属性则按原来的输出。
const config1 = {
host: 'localhost',
port: 3306,
name: 'root',
pwd: 'root',
test: 'lyz'
}
const config2 = {
host: 'localhost:8080',
port: 3308,
name: 'root',
pwd: '123456',
test2: 'my'
}
//适合配置合并
console.log(Object.assign(config1, config2));
- Object.setPrototypeOf()设置原型对象/Object.getPrototypeOf()获取原型对象
let school = {name: 'lyz'};
let cities = {
like: ['eat', 'drink']
}
Object.setPrototypeOf(school, cities);//{host: "localhost:8080", port: 3308, name: "root", pwd: "123456", test: "lyz", …}
console.log(Object.getPrototypeOf(school)); //{like: Array(2)}
console.log(school);//{name: "lyz"}