ECMAScript 相关介绍
ECMA : (European Computer Manufacturers Association) 欧洲计算机制造协会
ECMAScript : 是由ECMA国际通过 ECMA-262 标准化的脚本程序设计语言
学习ES6
变量
ES6新添加的两个定义变量的关键字 let const
let
// 声明变量let a;let b, c;let e = 100;let f = 123, g = 'yellowsea', h = [];
let特性
- 变量不能重复的声明
- 块级作用域 全局, 函数, eval
- 不存在变量提升
- 不影响作用域链
// let 特性//1. 变量不能重复的声明let star = 'yellowsea';let star = 'test1'; //err 重复声明//2. 块级作用域 全局, 函数, eval// if else while for{let girl = 'newTest';}console.log(girl); // err : girl is not defined//3. 不存在变量提升console.log(song);let song = 'test1'; // err: Cannot access 'song' before initialization//4. 不影响作用域链{let school = 'test';function test1() {console.log(school);}test1(); // test}
实例
const items = document.getElementsByClassName('item');// 使用 var 定义变量时for (var i = 0; i < items.length; i++) {items[i].onclick = function() {// 修改点击item 的颜色// this.style.backgroundColor = 'pink'; // 可以修改items[i].style.backgroundColor = 'pink'; // Cannot read properties of undefined (reading 'style')}}console.log(window.i); // 3/*** 因为使用了var, var i 进行3次循环, i变成了3;* var 是全局作用域的, 会将var i = 3 绑定到 window 上;* 点击 item 时,执行 回调函数,回调函数中的items[i], i 是没有在函数中定义的,所以它会去window 上去找i* 此时的window.i = 3 ; items[3]没有; 所以会报错*/
// 使用 let 时 , 没有发生报错, 因为let 具有块级作用域。声明的i是 互不影响的for (let i = 0; i < items.length; i++) {items[i].onclick = function() {// 修改点击item 的颜色// this.style.backgroundColor = 'pink'; // 可以修改items[i].style.backgroundColor = 'pink';}}
const
const 常量 : 值不能修改的量 叫常量
// 常量 : 值不能修改的量 叫常量const NAME = 'yellowsea'; // 定义常量一般要大写
const 特性
//1. 声明常量 一定要赋值const A; // 报错//2. 一般定义常量使用大写 (潜规则)const a = 100 ; // 可以不用也不会报错, 书写标准//3. 常量的值不能修改NAME = 'YELLOWSEA'; // 报错//4. const 具有块级作用域{const PLAYER_NAME = 'UZI';}console.log(PLAYER_NAME); // 报错//5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错const TEAM = ['UZI', 'MLXG', 'Ming','Letme'];// TEAM.push('Meiko'); // 没有报错, 因为这个常量所指向的地址没有发生改变,所以不会报错// TEAM = 100; // 报错 , 常量所指向的地址值发生了改变const PERSON = {Id: 123,Name: 'yellowsea',}PERSON.Name = 'Hidie'; // 修改对象数据console.log(PERSON); // {Id: 123, Name: 'Hidie'}
对象的简化写法
ES6 允许在大括号里面,直接写入变量和函数, 作为对象的属性方法 , 这样书写更加简洁
// 同名在定义对象中可以简化
let name = 'Yellowsea';let change = function() {console.log('change 方法');}const school = {// name: name, 可以简化// 同名可以简化name,change,// 写在对象中额方法 简化// improve: function() {}improve() {console.log('这是简化后的方法');}}console.log(school);school.improve();
模板字符串
`` ES6 引入新的声明字符串方法
//1 声明let str = `这是一个字符串`;console.log(str, typeof str);//2. 内容中可以直接出现换行符let str = `<ul><li>test1</li><li>test2</li><li>test3</li></ul>`// 3. 变量拼接 ${}let test = 'Yellowsea';let out = `Name is ${test}`;console.log(out);
解构赋值
ES6 允许按照一定模式从数组和对象中提取值, 对变量进行赋值, 称为解构赋值
// 数组的解构赋值const F4 = ['001', '002', '003'];let [a,b,c] = F4; // 解构console.log(a);console.log(b);console.log(c);
//2. 对象的解构const zhao = {name: '赵本山',age: '不详',xiaopin: function () {console.log('演小品');}};// 对象单独解构 解构时 变量名必须相同let {xiaopin} = zhao;xiaopin();//let {name, age, xiaopin} = zhao;console.log(name);console.log(age);console.log(xiaopin);xiaopin(); // 演小品
箭头函数
ES6 允许使用 箭头 => 定义函数
// 声明函数let fn = function () { // 普通定义函数}// 使用箭头函数let Fn = (a, b) => {return a + b;}Fn(1,2); // 3
箭头函数的特性
- 箭头函数没有自己的this, 使用时, this是它的上一级(this指向它的上一级)
- 不能作为构造函数实例化对象
- 不能使用 arguments 变量
- 箭头函数的简写
// 1. this 是静态的, this 始终指向函数声明时在作用域下的this的值function getName() {console.log(this.name);}let getName2 = () =>{console.log(this.name);}// 设置window 对象的 name 属性window.name = 'yellowsea';const hidie = {name: 'YELLOWSEA'}// 直接调用 , 全局,window下的name// getName();// getName2();//call 方法调用getName.call(hidie); // YELLOWSEAgetName2.call(hidie); // yellowsea , 因为this没有改变,指向的全局作用域的window
//2. 不能作为构造函数实例化对象let Person = (name,age) => {this.name = name;this.age = age;}let me = new Person('hidie', 123);console.log(me); // 报错 : TypeError: Person is not a constructor
//3. 不能使用 arguments 变量let newTest = () => {console.log(arguments);}newTest(1,2,3); // ReferenceError: arguments is not defined at newTest
// 4. 箭头函数的简写// 1) 省略小括号, 当形参有且只有一个的时候// let add = (n) => {// return n + n;// }let add = n => {return n + n;}console.log(add(9));// 2) 省略花括号, 当代码体只有一条语句的时候,省略花括号,此时 return 也必须要省略// 而且语句的执行结果就是函数的返回值// let pow = n => {// return n * n;// }let pow = n => n*n;console.log(pow(9));
// 实例
// 需求-1 点击div 2s 后颜色变为pink// 获取元素const ad = document.getElementById('ad');// 绑定事件ad.addEventListener('click', function() {setTimeout(() => {// 箭头函数没有自己的this,会向外一层边找, 知道找到 window 下为止// 或者可以这样理解箭头函数下的this , this永远都是定义函数下作用域的 this (谁调用this就是谁)this.style.backgroundColor = 'pink';},2000)})
// 需求2 从数组中返回偶数的元素const arr = [1,6,12,45,100];const result = arr.filter(value => value % 2 === 0 );console.log(result);// 箭头函数适合于 this 无关的回调 , 定时器, 数组的方法回调// 箭头函数不适合与 this 有关的回调 , DOM事件的回调, 对象的方法{name: 'Yellowsea';// getName: function() {// this.name; // this.name 指向的是 该作用域的name// }getName: () => {this.name; // 此时的this.name 指向的是window 下的name}}
函数参数设置默认值
ES6 允许给函数参数赋初始值
//1. 形参初始值 具有默认值的参数, 一般位置靠后(潜规则)function add (a,b,c=10) { // 给c 设置默认值, 如果没有设置默认值,则为 undefined ;return a + b + c;}console.log(add(1,2,));//2. 与解构赋值结合function connect({host, username, password, port}) {// let {host, username, password,port} = options;console.log(host);console.log(username, password);console.log(port);}connect({host: '',username: 'root',password: 'root',port: 3306,})
rest参数
ES6 引入 rest 参数, 用于获取函数的实参, 用来代替 arguments(用来获取函数在调用时的实参)
function data() {console.log(arguments); //此时的arguments 是一个对象}data('test1','test2','test3');
// rest 参数function data(...args) {console.log(args); // rest参数 返回的是一个数组,可以使用数组中的一系列方法// 例如使用 数组返回的 forEach方法args.forEach(value => console.log(value));}data('test1','test2','test3');// 注意 ,如果你的参数由多个, rest 参数必须要放到最后function fn(a,b, ...args) {console.log(a,b,args);}fn(1,2,3,4,1);
扩展运算符
… 扩展运算符 , 能够将 数组 转换为逗号分隔的 参数序列
const Arr = ['test1', 'test2', 'test3']; // => test1, test2, test3function Test() {console.log(arguments);}Test(...Arr); // 相当于 Test('test1','test2','test3'); // 扩展运算符// 扩展运算符 和 rest 参数 相比// 扩展运算符 用来 调用函数的 实参里 进行对 数组 | 对象的 解构// rest 用在调用函数的形参里, 用于对参数设置默认值
扩展运算符的应用
// 1. 数组的合并let strArr1 = ['1','2','3','4'];let strArr2 = ['a','b','c','d','e'];// 默认方法const result = strArr1.concat(strArr2);// 使用扩展运算符 ... 方法const newArr = [...strArr1, ...strArr2];console.log(newArr);//2. 数组的克隆const kelongArr = ['A','B','C','D'];const kelongNewArr = [...kelongArr];console.log(kelongNewArr);// 3. 将伪数组转为真正的数组const divs = document.querySelectorAll('div'); // divs : NodeList 类型const div = [...divs]; // div Array 类型console.log(div);
Symbol
ES6 引入了一种新的原始类型 Symbol , 表示独一无二的值, 是JS语言的第七种类型
Symbol特点
/*** 1. Symbol的值是唯一的,用来解决命名冲突问题* 2. Symbol值不能与其他类型进行运算* 3. Symbol定义的对象属性不能使用for...in 循环遍历,但是可以使用 Reflect.ownKeys来获取对象的所有键名* @type {symbol}*/
// 创建Symbollet s = Symbol();console.log(s, typeof s);let s2 = Symbol('Yellowsea');let s3 = Symbol('Yellowsea');console.log(s2 === s3); // false// 使用 Symbol.for 创建let s4 = Symbol.for('yellowsea');let s5 = Symbol.for('yellowsea');console.log(s4 === s5); // true// 不能与其他数据进行运算// let result1 = s + s2;
// Symbol 内置属性
// 1. Symbol.hasInstance 检测类型 与 instanceof 配合使用class Person {static [Symbol.hasInstance](param) { // 自己去控制类型的检测console.log(param); // param 表示正在检测的数据类型console.log('被用来检测类型了')// return false;// return true;}}let o = {};console.log(o instanceof Person); // false//2. Symbol.isConcatSpreadable 给一个布尔值// 表示该对象使用 concat()时,是否可以展开const arr1 = [1,2,3];const arr2 = [4,5,6];arr2[Symbol.isConcatSpreadable] = false; // arr2 不允许被展开console.log(arr1.concat(arr2)); // [1, 2, 3, Array(3)]
// Symbol 创建对象属性
// Symbol 给对象添加一个独一无二的值let game = {name: "game1",up: function() {},down(){},};// 声明一个对象let methods = {up: Symbol(),down: Symbol()}// 给game 中添加方法 (安全添加方法 )game[methods.up] = function() {console.log('这是up 方法')}game[methods.down] = function() {console.log('这是down 方法')}console.log(game);// 方法二let youxi = {name: '三国杀',[Symbol('sha')]() {console.log('杀')},[Symbol('shan')]() {console.log('闪')}}console.log(youxi);
迭代器
迭代器(iterator)是一种接口,任何数据只要有了 iterator 接口, 就可以完成遍历操作
ES6 创造了一种新的遍历命令 for..of 循环, iterator 接口主要供for…of 消费 (for…of 直接遍历出值, 而for…in遍历得到的是下标)
原生就局具备 iterator 接口的数据 (可以使用for…of 遍历)
例如 : Array Arguments Set Map String TypedArray NodeList
* 工作原理* 1. 创建一个指针对象,指向当前数据结构的起始位置* 2. 第一次调用对象的next方法, 指针自动指向数据结构的第一个成员* 3. 接下来不断调用 next() 方法, 指针一直往后移动, 知道指向最后一个成员* 4. 每调用next方法返回一个包含 value 和 done 属性对象
迭代器的作用 : 需要自定义遍历数据的时候,要想到迭代器
// 例子 声明数组let lizi = ['yellowsea','世利', 'Hidie'];console.log(lizi);// 在它的原型上具有 Symbol(Symbol.iterator): ƒ values() 方法// 所以可以使用 for...of 进行遍历直接获取值for ( let v of lizi) {console.log(v);}//分析原理//1. 创建对象let iterator = lizi[Symbol.iterator](); //Symbol.iterator 是一个方法// 查看console.log(iterator); // 身上具有next() 方法//2. 调用 next() 方法console.log(iterator.next()); // 指针自动指向 数据结构的下一个成员console.log(iterator.next());console.log(iterator.next()); // {value: 'Hidie', done: false}console.log(iterator.next());//每次返回都包含value | done 属性, {value: undefined, done: true}
// 迭代器运用
迭代器自定义遍历数据
// 声明一个对象const obj = {name: '001',arr: ['test1','test2','test3','test4'],// 实现能够循环遍历 (根据原理实现)// 定义 iterator 接口[Symbol.iterator]() {// 控制对 arr 的数据获取let index = 0; // 设置索引值let _this = this;// 返回一个指针对象return {// 指针对象中具有一个next() 方法next() {// 返回一个具有 value 和 done 的属性对象// 控制下标,返回结果if ( index < _this.arr.length ) {//返回数据const result = {value: _this.arr[index], done: false}index++; // 下标自增return result; // 返回结果}else {return {value: undefined, done: true} // 遍历完成}}}}}// 需求,使用for...of 遍历, 每次循环返回arr数组中的属性值// 使用for...of 遍历// for (let v of obj) {// console.log(v); // Uncaught TypeError: obj is not iterable// // obj 没有 iterator 接口类型// }// 完成自定义遍历 , 完全按照我们的意愿进行遍历, 这就是迭代器的作用for (let v of obj) console.log(v);// 'test1','test2','test3','test4'
生成器
生成器函数 Es6 提供的一种异步编程的解决方案
// 生成器, 其实就是一个特殊的函数// 异步编程 纯回调函数// 定义函数function * gen() { // 使用 function * 函数名 的语法定义生成器// console.log('Hello generator');// 里面可以定义 yield 语句/* yield 算是函数代码分隔符 */// console.log(111);yield 'test1';// console.log(222);yield 'test2';// console.log(333);yield 'test3';// console.log(444);}// 执行let iterator = gen();console.log(iterator); //输出的其实是一个 迭代器对象,原型中具有一个next() 方法//运行// iterator.next(); // Hello generator// iterator.next();// iterator.next();// iterator.next();// iterator.next();// 循环输入for (let v of gen()) {console.log(v); // test1 test2 test3// 所以循环遍历生成器, 输出(执行)的是 yield 语句的代码块}
生成器函数参数
function * gen(args) {console.log(args); // 可以进行传参let one = yield 111;console.log(one); // BBB, 第二个next的参数let tow = yield 222;console.log(tow) // CCC , 第三个next 的参数let three = yield 333;console.log(three) // DDD, 第四个 next方法 的参数}//执行获取迭代器对象// 传参let iterator = gen('AAA');console.log(iterator.next());// next 方法 可以传入实参console.log(iterator.next("BBB")); // 第二次调用的next方法传入的参数, 会作为第一个yield语句返回的结果;console.log(iterator.next("CCC")); // 第三次调用的next方法传入的参数, 会作为第二个yield语句返回的结果;console.log(iterator.next("DDD"));
生成器实例
// 异步编程 文件操作 网络操作 ajax request// 需求 1s 后 输出 111 2s 后输出 222 3s 后输出 333// 回调地狱// setTimeout(() => {// console.log(111)// setTimeout(()=> {// console.log(222)// setTimeout(()=> {// console.log(333)// }, 3000)// }, 2000)// },1000)// 使用生成器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(); // 首次执行 next()
// 实例2
//模拟获取 用户数据 订单数据 商品数据 获取数据,进行操作//异步获取function getUsers () {setTimeout(() => {let data = "用户数据"iterator.next(data); // 调用 next()方法时, 传入 data 数据, yield 接收到数据 ,进而操作数据}, 1000)}function getOrders () {setTimeout(() => {let data = "订单数据"iterator.next(data);}, 1000)}function getGoods () {setTimeout(() => {let data = "商品数据"iterator.next(data);}, 1000)}// 定义生成器function * gen() {let users = yield getUsers();console.log(users);let orders = yield getOrders();console.log(orders);let goods = yield getGoods();console.log(goods);}// 执行生成器let iterator = gen();iterator.next();// 异步处理数据
Promise
Promise 是 ES6 引入的异步编程的新解决方案 , 语法上 Promise 是一个构造函数用来封装异步函并可以获取其成功或或者失败的结果
// 创建 Promise
// 实例化 Promise 对象const p = new Promise(function(resolve,reject){setTimeout(() => {let data = '用户数据'// 如果成功, 调用 resolve// resolve(data);//如果失败, 调用 rejectlet err = '获取数据失败';reject(err);}, 1000)});// 调用 promise 对象的 then 方法// p.then() 回调方法 , 给出两个参数, 一个是成功的函数, 一个是失败的函数p.then(function(value){// 第一个参数; 成功的回调 , value 异步请求成功后,获取的数据console.log(value)}, function(reason) {// 第二个参数; 失败的回调console.log(reason)})
promise封装读取文件
// Promise封装读取文件//1. 引入 fs 模块const fs = require('fs');//2. 使用 fs模块 调用方法 读取文件// fs.readFile('./result/test.md', (err,data) => {// // 如果失败, 抛出错误// if (err) throw err;//// // 成功状态, 输入内容// console.log(data.toString()); //<Buffer, 使用 toString() 方法进行转化// });//3. 使用 Promise 调用 fs 读取文件内容, 封装 (读取文件内容-> 异步操作)const p = new Promise(function (resolve, reject) {fs.readFile('./result/test.md', (err, data) => {// 如果失败, 调用 reject 改变 p 的返回值if (err) reject(err);// 如果成功resolve(data);})})// 调用 Promise, 通过 p.then() 回调处理结果p.then((value) => {console.log(value.toString())}, (reason) => {console.log('读取失败')})
Promise封装Ajax请求
// https://api.oick.cn/dutang/api.php// 默认的 Ajax 发起请求// //1. 创建对象// const xhr = new XMLHttpRequest();//// //2 初始化// xhr.open('GET', 'https://api.oick.cn/dutang/api.php');//// //3, 发送// xhr.send();//// //4, 绑定事件,处理响应结果// xhr.onreadystatechange = function () {// // 判断// if (xhr.readyState === 4) {// // 判断响应码 200 ~ 299// if ( xhr.status >= 200 && xhr.status < 300) {// // 表示成功// console.log(xhr.response);// }else {// console.log(xhr.status);// }// }// }// 使用 Promise 发起请求const p = new Promise((resolve, reject) => {//1. 创建对象const xhr = new XMLHttpRequest();//2 初始化xhr.open('GET', 'https://api.oick.cn/dutang/api.php');//3, 发送xhr.send();//4, 绑定事件,处理响应结果xhr.onreadystatechange = function () {// 判断if (xhr.readyState === 4) {// 判断响应码 200 ~ 299if ( xhr.status >= 200 && xhr.status < 300) {// 表示成功// console.log(xhr.response);resolve(xhr.response); // 返回给实例化对象p}else {// 表示失败// console.log(xhr.status);reject(xhr.status);}}}});// 实例化对象p 处理响应结果// 指定回调p.then((value)=>{console.log(value);}, (reason)=> {console.log('获取数据失败',reason)});
promise.prototype.then方法
// 创建 Promise 对象const p = new Promise((resolve, reject) => {setTimeout(() => {// resolve('这是用户数据');reject("出错了")}, 1000)});// 调用 then 方法// 查看 then 的返回结果/*** 调用then 方法 then 方法的返回结果是 Promise 对象, 对象状态由回调函数的执行结果决定** 1. 如果回调函数中返沪的结果是 非 promise 类型的属性 , 状态为 成功**/const result = p.then(value => {console.log(value)// 1. 非 promise 类型属性// return 213; // 状态是成功的// 2. 是promise 对象// return new Promise((resolve, reject) => {// resolve('ok');// })//3. 抛出错误throw new Error('出错了')}, reason => {console.warn(reason)})// 所以可以利用 then 的返回值 可以 进行链式调用// 链式调用// p.then(value => {//// }).then(value => {//// })console.log(result)
Promise对象catch方法
const p = new Promise((resolve, reject) => {// 设置 p 对象的状态为失败, 并设置失败的值reject('出错了')})// 通常使用 p.then 方法 指定失败的回调// p.then(value => {}, reason => {// console.log(reason);// })// 使用 catch 方法// 只获取出错的回调p.catch(reason => {console.log(reason)})
总要:Promise的链式调用
(套娃)实例
// 这种场景使用在 读取用户数据 之后 才能读取用户的订单 用户商品管理 等等操作
// 遇到时候 可以想到使用 Promise
// Promise实践-读取多个文件内容const fs = require('fs')// 默认一个文件内容fs.readFile('./result/test.md', (err, data) => {console.log(data.toString())})// 使用 Promise 读取多个内容const p = new Promise((resolve, reject) => {// 读取第一个文件fs.readFile('./result/test.md', (err, data) => {resolve(data)})})p.then(value => { // value 是第一个文件内容// 使用 p.then 的返回可以是一个 Promise 的特性可以读取第二个文件内容return new Promise((resolve, reject) => {fs.readFile('./result/test2.md', (err, data) => {// 返回 第一个文件内容 和 第二个文件内容resolve([value, data]);})})}).then(value => { //链式调用, 此时的value 是 [value, data]return new Promise((resolve, reject) => {// 读取第三个文件内容fs.readFile('./result/test3.md', (err, data) => {// 压入操作value.push(data);resolve(value);})})}).then(value => { // 这里就是3个文件的内容了console.log(value.join('\r\n')) // 打印输出})
Set 和 Map
Set 方法
Set ES6 提供的新的数据结构 Set 集合 , 类似数组, 但集合中的成员值都是唯一的
Set实现了 iterator 接口, 所以可以使用 … | for…of 进行遍历
* Set 的属性和方法* size : 返回集合元素的个数* add : 增加一个新的元素, 返回当前集合* delete : 删除元素, 返回 boolean值* has : 检测集合中是否包含某个元素, 返回 boolean值* clear : 清空集合元素
// 声明一个 Set 集合let s = new Set();// console.log(s, typeof s); // Set(0) {size: 0} 'object'// 使用 Set 的属性方法let s2 = new Set(['test1', 'test2','test3']);// 个数console.log(s2.size);// 添加s2.add('test4');// 删除s2.delete('test2');// 检测console.log(s2.has('test3')); // 返回一个boolean 值// 清空集合// s2.clear();//使用 for...of 遍历for (let v of s2) console.log(v);// 使用 扩展运算符 展开集合console.log(...s2);console.log(s2);
// set实践
let arr = [1,23,1,21,21,3,31,23,1,1,2,3];//1. 数组去重let result = [...new Set(arr)];// Set特性,在Set集合中元素只能出现一次. | 使用 ... 展开Set集合,保存为数组console.log(result);//2. 交集let arr2 = [1,2,3,2,1,2];let result = [...new Set(arr)].filter(item => { // arr 去重然后循环过滤let s2 = new Set(arr2); // arr2 去重// s2.has(item) 判断s2中是否由 item , 可以获取交集的元素return s2.has(item)})console.log(result);//简化let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));console.log(result);//3. 并集// 使用 [...new Set(arr)] 转为一个数组let union = [...new Set([...arr, ...arr2])];console.log(union);//4. 差集 (交集取反 )let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));console.log(diff);
Map 方法
Map ES6提供的Map数据结构。 它类似于对象, 也是键值对的集合。
但是“键”的范围不限于字符串, 各种类型的值(包括对象)都可以当作键。
Map具有 iterator 接口, 可以使用 … | for…of 进行遍历
* Map 具有的属性方法* size : 返回Map的个数* set : 增加一个元素, 返回当前的Map* get : 返回键名对象的键值* has : 检测Map中是否含有某个元素, 返回 boolean 值* clear : 清空Map集合, 返回 undefined* keys() : 获取所有的key名
// 声明 Maplet m = new Map();console.log(m, typeof m); // Map(0) {size: 0} 'object'// Map 属性方法//1. 添加属性 set(key, value ) 形式m.set('name', "yellowsea");m.set('change', function() {console.log('这是change方法')}); // key 和 value 不仅仅是字符串,let key = {school: 'HIdie'};m.set(key, ['test1', 'test2', 'test3']);// 删除 键// m.delete('name');// 检测console.log(m.has(key)); // true// 获取 键值valueconsole.log(m.get('name')); // 通过 key 获取 value 的值console.log(m.get(key));// 遍历console.log(...m); // 展开for (let v of m.keys()) console.log(v);// 清空// m.clear();console.log(m);
Class 类
ES6 引入了Class类这个概念,作为对象的模板 。 通过class关键字可以定义类。
基本上ES6的class可以看作只是一个语法糖,它的绝大多数功能ES5都可以做到 。 新的class 写法只是让对象原型的写法更加清晰,更像面向编程的语法而已
* 知识点* class 声明类* constructor 定义构造函数初始化* extends 继承父类* super 调用 父级构造方法* static 定义静态方法和属性* 父类方法可以重写
ES5通过构造函数 实现的类方法
//手机function Phone (brand, price) {this.brand = brand;this.price = price;}// 添加方法 (在原型上)Phone.prototype.call = function () {console.log('这是call 方法 ');}// 实例化对象const Huawei = new Phone('华为',2000);Huawei.call();console.log(Huawei);
ES6使用class 构造类
// 使用 ES6 的 class 构造类class Phone {// 构造方法, 必须使用 constructor()方法,不能修改,自动执行(在new Phone的时候执行)constructor(brand, price) {this.brand = brand;this.price = price;}// 定义方法call(a) { // 必须使用该语法在class中定义方法,不能使用 ES5的对象完整形式console.log('这是call 方法 ', a);}}const onePlus = new Phone('1+手机', 1000);onePlus.call('test');console.log(onePlus);
class类静态属性
/// Class静态成员// ES5 的静态成员function Phone() {}// 这样在写属性在 构造函数 对象 上的属性, 实例化对是无法查看到的// 这种属性叫做静态属性Phone.name = 'test';Phone.change = function () {console.log('这是change 方法');}// 如果在构造函数原型上 添加的属性 就可以看到Phone.prototype.size = '123';// console.log(Phone.name);Phone.change();// 实例化对象let nokia = new Phone();console.log(nokia.name); // undefined , 实例化对象出来的, 是无法获取到构造函数中的静态属性console.log(nokia.size);// ES6// Class 定义静态属性class Shouji {static mingzi = "手机";static change() {console.log('静态属性方法')}}// 实例化对象const sj = new Shouji();console.log(sj.mingzi); // undefined , 实例化对象出来的, 是无法获取到Class中的静态属性
class构造函数继承
ES5构造函数继承
// 回顾 ES5 构造函数 的继承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值 ; 实现子类调用父类方法 进行初始化Phone.call(this, brand,price); // this 是指向 SmartPhone//子类属性初始化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 sj = new SmartPhone("这是手机",12312, 'back', '5.5');console.log(sj);sj.call();sj.playGame();sj.photo();
ES6 class 继承
// Class 的继承class Phone {// 构造方法constructor(brand, price) {this.brand = brand;this.price = price;}//父类的方法call() {console.log('我可以大点话 ');}}// 子类, extendsclass SmartPhone extends Phone { // 子类必须使用 extends 指向父类// 子类的构造方法constructor (brand,price,color,size) {// 注意点super(brand,price) // 必须通过 super 指向父类的constructor 方法,进行父类的属性的初始化// super(brand,price) 相等于 ES5 中的 Phone.call(this,brand, price)this.color = color;this.size = size;}// 子类方法photo() {console.log('我可以拍照');}playGame() {console.log('我可以打游戏');}}//实例化对象const Xiaomi = new SmartPhone('小米手机', 2000, 'write', '5.5inch');console.log(Xiaomi);Xiaomi.call();
Class中Getter和Setter方法
class Phone {// get 方法get price() { // 只要实例化对象 读取了 price属性, 就睡调用 get price 这个方法// 返回值就是 price 这个属性的值return 'price的值'}// set//只要price属性被修改了,就会调用set 方法set price(value) {// price 必须接收一个参数,为修改的值console.log('price 被修改了 ');return value}}const s = new Phone();console.log(s.price)s.price = 'free';console.log(s)
ES6数值的扩展
// Number 数值的扩展//1. 二进制和八进制let b = 0b1010; // 二进制let o = 0o777; // 0o 表示八进制let d = 100; // 十进制let x = 0xff; // 十六进制console.log(b,o,d,x); // 10 511 100 255//2. Number.isFinite 检测一个数值是否为有限数console.log(Number.isFinite(100))console.log(Number.isFinite(100/0))//3. Number.isNaN 检测一个数值是否为NaNconsole.log(Number.isNaN(3));//4. Number.parseInt Number.parseFloat 字符串转为整数console.log(Number.parseInt('123123aaa'));console.log(Number.parseFloat('3.12生')); // float// 5. Number.isInteger 判断一个数是否为 整数console.log(Number.isInteger(123));console.log(Number.isInteger(12.3));//6. Math.trunc 将数字的小数部分抹掉console.log(Math.trunc(3.14));//7. Math.sign 判断一个数是否是 正数 零 负数console.log(Math.sign(100)) //1console.log(Math.sign(0)) // 0console.log(Math.sign(-100)) //-1
ES6对象的扩展
// 对象扩展方法//1. Object.is 判断两个值是否完全相等console.log(Object.is(123,123));console.log(Object.is(NaN,NaN));//2. Object.assign 对象的合并const obj1 = {username: 'yellowsea',password: 'test1'}const obj2 = {username: null,password: null,}// Object.assign(参数1, 参数2); 参数2会覆盖参数1, 后面的会覆盖前面的// console.log(Object.assign(obj1, obj2));Object.assign(obj1,{a:1,b:2,c:3}); // 合并console.log(obj1);//3. Object.setPrototypeOf 设置原型对象// Object.getPrototypeOf 获取原型对象const school = {name: "Yellowsea"}const className = {name: ['test1', 'test2', 'test3']}// 设置原型对象 , Object.setPrototypeOf(对象原型, 设置原型对象上的数据);Object.setPrototypeOf(school, className);console.log(Object.getPrototypeOf(school)); // 获取原型 信息console.log(school);
