迭代器
一种接口,为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署 inerator 接口,就可以完成遍历操作。
工作原理
a)创建一个指针对象,指向当前数据结构的起始位置。
b)第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员。
c)接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员。
d)每调用 next 方法返回一个包含 value和done 属性的对象。
声明一个数组
const xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];
使用 for...of 遍历数组
for(let v of xiyou){
console.log(v);
}
使用 for...in遍历数组
for(var i in xiyou){
console.log(i)
}
使用 symbol.iterator 创建对象
let iterator = xiyou[Symbol.iterator]();
调用对象的next方法
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
自定义遍历数据
//声明一个对象
const banji = {
name: "终极一班",
stus: [
'xiaoming',
'xiaoning',
'xiaotian',
'knight'
],
//增加迭代器,返回对象
[Symbol.iterator]() {
//索引变量,进行判断,决定返回结果
let index = 0;
//保存this
let _this = this;
//创建一个指针对象
return {
//next方法
next: function () {
if (index < _this.stus.length) {
const result = {
//返回一个包含value和done属性的对象
value: _this.stus[index], done: false
};
//下标自增
index++;
//返回结果
return result;
}else{
return {
value: undefined,
done: true
};
}
}
};
}
}
//遍历这个对象
for (let v of banji) {
console.log(v);
}
生成器
异步编程解决方案
//定义函数
function * gen(){
console.log(111);
yield '一只没有耳朵';
console.log(111);
yield '一只没有尾巴';
console.log(111);
return '真奇怪';
console.log(111);
}
//调用函数
let iterator = gen();
//执行函数
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
//遍历
for(let v of gen()){
console.log(v);
}
生成器函数参数
yield 关键字
- 生成器函数执行暂停,yield关键字后面的表达式的值返回给生成器的调用者。
- 返回一个iteratorreault(迭代器)对象,有两个属性(value,done),分别代表返回值和是否完成。
- 配合生成器工作的,如next。
function * gen(arg){
console.log(arg);
let one = yield 111;
console.log(one);//BBB
let two = yield 222;
console.log(two);//CCC
let three = yield 333;
console.log(three);//DDD
}
//执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());
//next方法可以传入实参
//传入BBB值,返回yield后的222
console.log(iterator.next('BBB'));
//传入CCC值,返回yield后的333
console.log(iterator.next('CCC'));
//传入DDD值,返回undefined
console.log(iterator.next('DDD'));
实例
1s 后控制台输出 111 2s后输出 222 3s后输出 333
function one(){
setTimeout(()=>{
console.log(111);
iterator.next();
},1000)
}
function two(){
setTimeout(()=>{
console.log(222);
iterator.next();
},2000)
}
function three(){
setTimeout(()=>{
console.log(333);
iterator.next();
},3000)
}
function * gen(){
yield one();
yield two();
yield three();
}
//调用生成器函数
let iterator = gen();
iterator.next();
Promise
实例化Promise对象
const p = new Promise(function(resolve, reject){
setTimeout(function(){
//成功
let data = '数据库中的用户数据';
resolve(data);
//失败
let err = '数据读取失败';
reject(err);
}, 1000);
});
//调用 promise 对象的 then 方法
//resolve成功
p.then(function(value){
console.log(value);
//reject失败
}, function(reason){
console.error(reason);
})
Promise读取文件
使用node
- 引入 fs 模块
const fs = require('fs');
- 调用方法读取文件(正常读取)
fs.readFile('./resources/为学.md', (err, data)=>{//箭头函数 使用fs模块下readFile函数,回调
//如果失败, 则抛出错误
if(err) throw err;
//如果没有出错, 则输出内容
console.log(data.toString());
});
- 使用 Promise 封装
//实例化Promise对象
const p = new Promise(function(resolve, reject){
fs.readFile("./resources/为学.mda", (err, data)=>{
//判断如果失败
if(err) reject(err);
//如果成功
resolve(data);
});
});
p.then(function(value){
console.log(value.toString());
}, function(reason){
console.log("读取失败!!");
});
Promise封装Ajax请求
// 接口地址: https://api.apiopen.top/getJoke
const p = new Promise((resolve, reject) => {
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化
xhr.open("GET",
"https://api.apiopen.top/getJ");
//3. 发送
xhr.send();
//4. 绑定事件, 处理响应结果
xhr.onreadystatechange = function () {
//判断
if (xhr.readyState === 4) {
//判断响应状态码 200-299
if (xhr.status >= 200 && xhr.status < 300) {
//表示成功
resolve(xhr.response);
} else {
//如果失败
reject(xhr.status);
}
}
}
})
//指定回调
p.then(function(value){
console.log(value);
}, function(reason){
console.error(reason);
});
then 方法
调用 then 方法 then方法的返回结果是 Promise 对象
对象状态由回调函数的执行结果决定
- 如果回调函数中返回的结果是 非 promise 类型的属性, 状态为成功, 返回值为对象的成功的值
- 是 promise 对象
- 抛出错误
- 链式调用
p.then(value=>{
}).then(value=>{
});
读取多个文件
引入 fs 模块
const fs = require("fs");
正常方法
fs.readFile('./resources/为学.md', (err, data1)=>{
fs.readFile('./resources/插秧诗.md', (err, data2)=>{
fs.readFile('./resources/观书有感.md', (err, data3)=>{
let result = data1 + '\r\n' +data2 +'\r\n'+ data3;
console.log(result);
});
});
});
使用 promise 实现
const p = new Promise((resolve, reject) => {
fs.readFile("./resources/为学.md", (err, data) => {
resolve(data);
});
});
p.then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./resources/插秧诗.md", (err, data) => {
resolve([value, data]);
});
});
}).then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./resources/观书有感.md", (err, data) => {
//压入
value.push(data);
resolve(value);
});
})
}).then(value => {
console.log(value.join('\r\n'));
});
set (集合)
新的数据结构,类似于数组,成员值唯一,实现了iterator接口,可以使用【扩展运算符】,【for...of...】遍历。
属性和方法
1) size 返回集合的元素个数
2) add 增加一个新元素,返回当前集合
3) delete 删除元素,返回 boolean 值
4) has 检测集合中是否包含某个元素,返回 boolean 值
5) clear 清空集合,返回 undefined
声明一个 set
let s = new Set();let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);
输出
- 元素个数
console.log(s2.size);
- 添加新的元素
s2.add('喜事儿');
- 删除元素
s2.delete('坏事儿');
- 检测
console.log(s2.has('糟心事'));
- 清空
s2.clear(); console.log(s2);
- 遍历
for(let v of s2){ console.log(v); }
实践
let arr = [1,2,3,4,5,4,3,2,1];
- 数组去重
let result = [...new Set(arr)]; console.log(result);
- 交集
//常规
let arr2 = [4,5,6,5,6];
let result = [...new Set(arr)].filter(item => {
let s2 = new Set(arr2);// 4 5 6
if(s2.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([...arr, ...arr2])]; console.log(union);
- 差集
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item))); console.log(diff);
Map
类似于对象,也是键值对的集合。
但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了iterator接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。
属性和方法:
1) size 返回 Map 的元素个数
2) set 增加一个新元素,返回当前 Map
3) get 返回键名对象的键值
4) has 检测 Map 中是否包含某个元素,返回 boolean 值
5) clear 清空集合,返回 undefined
声明 Map
let m = new Map();
添加元素
方式一:
m.set('name','尚硅谷'); m.set('change', function(){ console.log("我们可以改变你!!"); });
方式二:
let key = { school : 'ATGUIGU' }; m.set(key, ['北京','上海','深圳']);
数量
console.log(m.size);
删除
m.delete('name');
获取
console.log(m.get('change')); console.log(m.get(key));
清空
m.clear();
遍历
for(let v of m){ console.log(v); //v=[键:值] }
class
通过 class 关键字,可以定义类。
ES5 中 类
//手机
function Phone(brand, price){
this.brand = brand;
this.price = price;
}
//添加方法
Phone.prototype.call = function(){
console.log("我可以打电话!!");
}
//实例化对象
let Huawei = new Phone('华为', 5999);
Huawei.call();
console.log(Huawei);
class 定义
constructor 不能修改 当使用 new+类名时自动执行
//class
class Shouji{
//构造方法 名字不能修改
constructor(brand, price){
this.brand = brand;
this.price = price;
}
//方法必须使用该语法, 不能使用 ES5 的对象完整形式
call(){
console.log("我可以打电话!!");
}
}
let onePlus = new Shouji("1+", 1999);
console.log(onePlus);1) class 声明类
1) class 声明类
2) constructor 定义构造函数初始化
3) extends 继承父类
4) super 调用父级构造方法
5) static 定义静态方法和属性
6) 父类方法可以重写
静态成员
使用static声明的属性,属于类而不属于类的实例化对象
class Phone{
//静态属性
static name = '手机';
static change(){
console.log("我可以改变世界");
}
}
let nokia = new Phone();
console.log(nokia.name);
console.log(Phone.name);
继承
ES5
重点
Phone.call(this, brand, price);
SmartPhone.prototype = new Phone; SmartPhone.prototype.constructor = SmartPhone;
//手机
function Phone(brand, price) {
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function() {
console.log("我可以打电话");
}
//智能手机
function SmartPhone(brand, price, color, size) {
Phone.call(this, brand, price);
this.color = color;
this.size = size;
}
//设置子级构造函数的原型
SmartPhone.prototype = new Phone;
SmartPhone.prototype.constructor = SmartPhone;
//声明子类的方法
SmartPhone.prototype.photo = function() {
console.log("我可以拍照")
}
SmartPhone.prototype.playGame = function() {
console.log("我可以玩游戏");
}
const chuizi = new SmartPhone('锤子', 2499, '黑色', '5.5inch');
console.log(chuizi);
class 继承
extends 关键字
重点
super(brand, price);
class Phone {
//构造方法
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
//父类的成员属性
call() {
console.log("我可以打电话!!");
}
}
class SmartPhone extends Phone {
//构造方法
constructor(brand, price, color, size) {
super(brand, price); // Phone.call(this, brand, price)
this.color = color;
this.size = size;
}
photo() {
console.log("拍照");
}
playGame() {
console.log("玩游戏");
}
//子类对父类的重写
call() {
console.log('我可以进行视频通话');
}
}
const xiaomi = new SmartPhone('小米', 799, '黑色', '4.7inch');
// console.log(xiaomi);
xiaomi.call();
xiaomi.photo();
xiaomi.playGame();
set get
// get 和 set
class Phone {
get price() {
console.log("价格属性被读取了");
return 'iloveyou';
}
set price(newVal) {
console.log('价格属性被修改了');
}
}
//实例化对象
let s = new Phone();
// console.log(s.price);
s.price = 'free';
数值扩展
- Number.EPSILON 是 JavaScript 表示的最小精度EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16
//判断两个数是否相等
function equal(a, b) {
if (Math.abs(a - b) < Number.EPSILON) {
return true;
} else {
return false;
}
}
console.log(0.1 + 0.2 === 0.3); console.log(equal(0.1 + 0.2, 0.3))
- 二进制和八进制let b = 0b1010; let o = 0o777; let d = 100; let x = 0xff; console.log(x);
- Number.isFinite 检测一个数值是否为有限数console.log(Number.isFinite(100)); console.log(Number.isFinite(100 / 0)); console.log(Number.isFinite(Infinity));
- Number.isNaN 检测一个数值是否为 NaNconsole.log(Number.isNaN(123));
- Number.parseInt Number.parseFloat字符串转整数console.log(Number.parseInt('5211314love')); console.log(Number.parseFloat('3.1415926神奇'));
- Number.isInteger 判断一个数是否为整数console.log(Number.isInteger(5)); console.log(Number.isInteger(2.5));
- Math.trunc将数字的小数部分抹掉console.log(Math.trunc(3.5));
- Math.sign 判断一个数到底为正数 负数 还是零console.log(Math.sign(100)); console.log(Math.sign(0)); console.log(Math.sign(-20000));
对象方法扩展
- Object.is 判断两个值是否完全相等console.log(Object.is(120, 120));// === console.log(Object.is(NaN, NaN));// === console.log(NaN === NaN); // ===
- Object.assign 对象的合并
const config1 = {
host: 'localhost',
port: 3306,
name: 'root',
pass: 'root',
test: 'test'
};
const config2 = {
host: 'http://atguigu.com',
port: 33060,
name: 'atguigu.com',
pass: 'iloveyou',
test2: 'test2'
}
console.log(Object.assign(config1, config2));
- Object.setPrototypeOf设置原型对象
Object.getPrototypeof
const school = {
name: '尚硅谷'
}
const cities = {
xiaoqu: ['北京', '上海', '深圳']
}
Object.setPrototypeOf(school, cities);
console.log(Object.getPrototypeOf(school));
console.log(school);
模块化
一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来
模块化的好处
模块化的优势有以下几点:
1) 防止命名冲突
2) 代码复用
3) 高维护性
模块化规范产品
ES6 之前的模块化规范有:
1) CommonJS => NodeJS、Browserify
2) AMD => requireJS
3) CMD => seaJS
ES6 模块化语法
模块功能主要由两个命令构成:export 和 import。
? export 命令用于规定模块的对外接口
//分别暴露 m1.js
export let school = '尚硅谷';
export function teach() {
console.log("我们可以教给你开发技能");
}
//统一暴露 m2.js
let school = '尚硅谷';
function findJob(){
console.log("我们可以帮助你找工作!!");
}
export {school, findJob};
//默认暴露 m3.js
export default {
school: 'ATGUIGU',
change: function(){
console.log("我们可以改变你!!");
}
}
? import 命令用于输入其他模块提供的功能
- 通用的导入方式
import * as m1 from "./src/js/m1.js";
import * as m2 from "./src/js/m2.js";
import * as m3 from "./src/js/m3.js";
- 将js文件中的内容赋值到前面的变量中
console.log(m1);
console.log(m2);
console.log(m3);
- 解构赋值形式
import {school, teach} from "./src/js/m1.js";
import {school as guigu, findJob} from "./src/js/m2.js";
import {default as m3} from "./src/js/m3.js";
- 将js文件中的内容进行对应赋值
- 简便形式 针对默认暴露
import m3 from "./src/js/m3.js";
js引入文件模块
引入jquery文件模块
const $ = require("jquery");
等同于
import $ from 'jquery';
使用
$('body').css('background','pink');
babel对ES6模块化代码转换
步骤
- 安装工具 npm i babel-cli babel-preset-env browserify(webpack) -D
- -D(开发依赖)
- 编译 npx babel src/js -d dist/js --presets=babel-preset-env
- 打包 npx browserify dist/js/app.js -o dist/bundle.js
ECMASript 7新特性
Array.prototype.includes
Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值
const mingzhu = ['西游记','红楼梦','三国演义','水浒传'];
判断
console.log(mingzhu.includes('西游记'));
指数操作符
ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同
console.log(2 ** 10);
等同
console.log(Math.pow(2, 10));
本文暂时没有评论,来添加一个吧(●'◡'●)