目录
接口调用
转下方promise 请求调用
this关键字
this
是 JavaScript 语言的一个关键字。
它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用。
function test() {
this.x = 1;
}
上面代码中,函数test
运行时,内部会自动有一个this
对象可以使用。
那么,this
的值是什么呢?
函数的不同使用场合,this
有不同的值。总的来说,this
就是函数运行时所在的环境对象。
下面分四种情况,详细讨论this
的用法。
情况一:纯粹的函数调用
这是函数的最通常用法,属于全局性调用,因此this
就代表全局对象。请看下面这段代码,它的运行结果是1。
var x = 1;
function test() {
console.log(this.x);
}
test(); // 1
情况二:作为对象方法的调用
函数还可以作为某个对象的方法调用,这时this
就指这个上级对象。
function test() {
console.log(this.x);
}
var obj = {};
obj.x = 1;
obj.m = test;
obj.m(); // 1
情况三 作为构造函数调用
所谓构造函数,就是通过这个函数,可以生成一个新对象。这时,this
就指这个新对象。
function test() {
this.x = 1;
}
var obj = new test();
obj.x // 1
运行结果为1。为了表明这时this不是全局对象,我们对代码做一些改变:
var x = 2;
function test() {
this.x = 1;
}
var obj = new test();
x // 2
运行结果为2,表明全局变量x
的值根本没变。
情况四 apply 调用
apply()
是函数的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象。因此,这时this
指的就是这第一个参数。
var x = 0;
function test() {
console.log(this.x);
}
var obj = {};
obj.x = 1;
obj.m = test;
obj.m.apply() // 0
apply()
的参数为空时,默认调用全局对象。因此,这时的运行结果为0
,证明this
指的是全局对象。
如果把最后一行代码修改为
obj.m.apply(obj); //1
运行结果就变成了1
,证明了这时this
代表的是对象obj
。
----------------------------------以上this的说明来自阮一峰的博客----------------------------
https://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html
https://es6.ruanyifeng.com/#docs/intro 此网站是阮一峰ES6文档,可以当做字典使用
接下来的笔记来自尚硅谷ES6教程,本人为后端开发,前端还没摸着皮毛,笔记仅供
参考,详细教程建议学习阮一峰的ES6文档~
-----------------------------------------------------------------------------------------------------------
变量声明
let 关键字
let 关键字用来声明变量,使用 let 声明的变量有几个特点:
不允许重复声明
块儿级作用域
不存在变量提升
不影响作用域链
应用场景:以后声明变量使用 let 就对了
//声明变量
let a;
let b,c,d;
let e = 100;
let f = 521, g = 'iloveyou', h = [];
//1. 变量不能重复声明
// let star = '罗志祥';
// let star = '小猪';--报错
//2. 块儿级作用域 全局, 函数, eval
// if else while for
// {
// let girl = '周扬青';
// }
// console.log(girl);
//3. 不存在变量提升----变量提升指的是你没声明就用了 var是可以的 会给默认undefined值
// console.log(song);
// let song = '恋爱达人';
//4. 不影响作用域链
{
let school = 'ES';
function fn(){
console.log(school);
}
fn();
}
const 关键字
const 关键字用来声明常量,const 声明有以下特点
声明必须赋初始值 标识符一般为大写
不允许重复声明
值不允许修改
块儿级作用域
//声明常量
const SCHOOL = '东北大学';
//1. 一定要赋初始值
// const A;
//2. 一般常量使用大写(潜规则)
// const a = 100;
//3. 常量的值不能修改
// SCHOOL = 'ATGUIGU';
//4. 块儿级作用域
// {
// const PLAYER = 'UZI';
// }
// console.log(PLAYER);
//5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
const TEAM = ['UZI','MXLG','Ming','Letme'];
// TEAM.push('Meiko');
注意: 对象属性修改和数组元素变化不会出发 const 错误
应用场景:声明对象类型使用 const,非对象类型声明选择 let
解构表达式
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值,
这被称为解构赋值。
1. 数组的结构
const F4 = ['小沈阳','刘能','赵四','宋小宝'];
let [xiao, liu, zhao, song] = F4;
console.log(xiao);
console.log(liu);
console.log(zhao);
console.log(song);
2. 对象的解构
const zhao = {
name: '赵本山',
age: '不详',
xiaopin: function(){
console.log("我可以演小品");
}
};
let {name, age, xiaopin} = zhao;
console.log(name);
console.log(age);
console.log(xiaopin);
xiaopin();
let {xiaopin} = zhao;
xiaopin();
模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:
字符串中可以出现换行符
可以使用 ${xxx} 形式输出变量
ES6 引入新的声明字符串的方式 『``』 '' ""
1. 声明
let str = `我也是一个字符串哦!`;
console.log(str, typeof str);
2. 内容中可以直接出现换行符
let str = `<ul>
<li>沈腾</li>
<li>玛丽</li>
<li>魏翔</li>
<li>艾伦</li>
</ul>`;
3. 变量拼接
let lovest = '魏翔';
let out = `${lovest}是我心目中最搞笑的演员!!`;
console.log(out);
注意:当遇到字符串与变量拼接的情况使用模板字符串
简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
let name = '老王';
let change = function(){
console.log('我们可以改变你!!');
}
const school = {
name,
change,
// 用这种新的方法声明方法更加简单
improve(){
console.log("我们可以提高你的技能");
}
}
console.log(school);
注意:对象简写形式简化了代码,所以以后用简写就对了
箭头函数
ES6 允许使用「箭头」(=>)定义函数。
ES6 允许使用「箭头」(=>)定义函数。
声明一个函数
let fn = function(){
}
let fn = (a,b) => {
return a + b;
}
调用函数
let result = fn(1, 2);
console.log(result);
1. this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值
function getName(){
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
设置 window 对象的 name 属性
window.name = '尚硅谷';
const school = {
name: "ATGUIGU"
}
直接调用
getName();
getName2();
call 方法调用
getName.call(school);
getName2.call(school);
2. 不能作为构造实例化对象
let Person = (name, age) => {
this.name = name;
this.age = age;
}
let me = new Person('xiao',30);
console.log(me);
3. 不能使用 arguments 变量
let fn = () => {
console.log(arguments);
}
fn(1,2,3);
4. 箭头函数的简写
1) 省略小括号, 当形参有且只有一个的时候
let add = n => {
return n + n;
}
console.log(add(9));
2) 省略花括号, 当代码体只有一条语句的时候, 此时 return 必须省略
而且语句的执行结果就是函数的返回值
let pow = n => n * n;
console.log(pow(8));
箭头函数的注意点:
如果形参只有一个,则小括号可以省略
函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
箭头函数 this 指向声明时所在作用域下 this 的值
箭头函数不能作为构造函数实例化
不能使用 arguments
注意:箭头函数不会更改 this 指向,用来指定回调函数会非常合适
<div id="ad"></div>
<script>
需求-1 点击 div 2s 后颜色变成『粉色』
获取元素
let ad = document.getElementById('ad');
绑定事件
ad.addEventListener("click", function(){
保存 this 的值
let _this = this;
定时器
setTimeout(() => {
修改背景颜色 this
console.log(this);
_this.style.background = 'pink';
this.style.background = 'pink';
}, 2000);
});
需求-2 从数组中返回偶数的元素
const arr = [1,6,9,10,100,25];
const result = arr.filter(function(item){
if(item % 2 === 0){
return true;
}else{
return false;
}
});
const result = arr.filter(item => item % 2 === 0);
console.log(result);
箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法
</script>
函数参数默认值
ES6 允许给函数参数赋值初始值
1. 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
function add(a,c=10,b) {
return a + b + c;
}
let result = add(1,2);
console.log(result);
2. 与解构赋值结合
function connect({host="127.0.0.1", username,password, port}){
console.log(host)
console.log(username)
console.log(password)
console.log(port)
}
connect({
host: 'atguigu.com',
username: 'root',
password: 'root',
port: 3306
})
rest 参数
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
arguments可以获取函数调用时候的所有实参
作用与arguments相似
function date(){
console.log(arguments);
}
date('白芷','阿娇','思慧');
rest 参数
function date(...args){
console.log(args);// filter some every map
}
date('阿娇','柏芝','思慧');
rest 参数必须要放到参数最后
function fn(a,b,...args){
console.log(a);
console.log(b);
console.log(args);
}
fn(1,2,3,4,5,6);
注意:rest 参数非常适合不定个数参数函数的场景
spread 扩展运算符
扩展运算符(spread)也是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。
『...』 扩展运算符能将『数组』转换为逗号分隔的『参数序列』
声明一个数组 ...
const tfboys = ['易烊千玺','王源','王俊凯'];
=> '易烊千玺','王源','王俊凯'
声明一个函数
function chunwan(){
console.log(arguments);
}
chunwan(...tfboys);// chunwan('易烊千玺','王源','王俊凯')
应用
1. 数组的合并 情圣 误杀 唐探
const kuaizi = ['王太利','肖央'];
const fenghuang = ['曾毅','玲花'];
// const zuixuanxiaopingguo = kuaizi.concat(fenghuang);
const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
console.log(zuixuanxiaopingguo);
2. 数组的克隆
const sanzhihua = ['E','G','M'];
const sanyecao = [...sanzhihua];// ['E','G','M']
console.log(sanyecao);
3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);// arguments
Symbol
ES6 引入了一种新的原始数据类型 Symbol, 表示独一无二的值。它是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol 特点 :
1. Symbol 的值是唯一的,用来解决命名冲突的问题
2. Symbol 值不能与其他数据进行运算
3. Symbol 定义的对象属性不能使用 for…in 循环遍历, 但是可以使用Reflect.ownKeys 来获取对象的所有键名
创建Symbol
let s = Symbol();
console.log(s, typeof s);
let s2 = Symbol('尚硅谷');
let s3 = Symbol('尚硅谷'); s3 ===s2 为false
Symbol.for 创建
let s4 = Symbol.for('尚硅谷');
let s5 = Symbol.for('尚硅谷'); s4=s5 为true
不能与其他数据进行运算
let result = s + 100;
let result = s > 100;
let result = s + s;
USONB you are so niubility
u undefined
s string symbol
o object
n null number
b boolean
注: 遇到唯一性的场景时要想到 Symbol
symbol 创建对象属性
向对象中添加方法 up down
let game = {
name:'俄罗斯方块',
up: function(){},
down: function(){}
};
声明一个对象
let methods = {
up: Symbol(),
down: Symbol()
};
game[methods.up] = function(){
console.log("我可以改变形状");
}
game[methods.down] = function(){
console.log("我可以快速下降!!");
}
console.log(game);
let youxi = {
name:"狼人杀",
[Symbol('say')]: function(){
console.log("我可以发言")
},
[Symbol('zibao')]: function(){
console.log('我可以自爆');
}
}
console.log(youxi)
symbol内置属性
除了定义自己使用的 Symbol 值以外,ES6 还提供了11 个内置的Symbol 值, 指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。
Symbol.hasInstance
--> 当其他对象使用 instanceof 运算符,判断是否为该对 象的实例时,会调用这个方法
Symbol.isConcatSpreadable
--> 对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat()时, 是否可以展开。
Symbol.species
--> 创建衍生对象时,会使用该属性
Symbol.match
--> 当执行 str.match(myObject) 时,如果该属性存在,会 调用它,返回该方法的返回值。
Symbol.replace
--> 当该对象被 str.replace(myObject)方法调用时,会返回 该方法的返回值。
Symbol.search
--> 当该对象被 str. search (myObject)方法调用时,会返回 该方法的返回值。
Symbol.split
--> 当该对象被 str. split (myObject)方法调用时,会返回该 方法的返回值。
Symbol.iterator
--> 对象进行 for...of 循环时,会调用 Symbol.iterator 方法, 返回该对象的默认遍历器
Symbol.toPrimitive
--> 该对象被转为原始类型的值时,会调用这个方法,返 回该对象对应的原始类型值。
Symbol. toStringTag
--> 在该对象上面调用 toString 方法时,返回该方法的返 回值
Symbol. unscopables
--> 该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除。
class Person{
static [Symbol.hasInstance](param){
console.log(param);
console.log("我被用来检测类型了");
return false;
}
}
let o = {};
console.log(o instanceof Person);
const arr = [1,2,3];
const arr2 = [4,5,6];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr.concat(arr2));
迭代器
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。
任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费
原生具备 iterator 接口的数据(可用 for of 遍历)
Array
Arguments
Set
Map
String
TypedArray
NodeList
工作原理:
a.创建一个指针对象,指向当前数据结构的起始位置
b.第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
c.接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
d.每调用 next 方法返回一个包含 value 和done 属性的对象
注: 需要自定义遍历数据的时候,要想到迭代器。
声明一个数组
const xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];
使用 for...of 遍历数组
for(let v of xiyou){
console.log(v);
}
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());
生成器函数声明与调用
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
代码说明:
* 的位置没有限制
生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到
yield 语句后的值 yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码
next 方法可以传递实参,作为 yield 语句的返回值
//生成器其实就是一个特殊的函数
//异步编程 纯回调函数 node fs ajax mongodb
//yield 语句函数代码的分隔符
//生成器函数不能直接调用,使用举例
function * gee(){
console.log("输出");
}
// gee().next();
let itt = gee();
itt.next();
function * gen(){
// console.log(111);
yield '一只没有耳朵';
// console.log(222);
yield '一只没有尾部';
// console.log(333);
yield '真奇怪';
// console.log(444);
}
let iterator = gen();
iterator.next();
iterator.next();
iterator.next();
iterator.next();//每一次会执行一个log
console.log(iterator.next()); //每一次会输出返回的结果 "一只没有耳朵" done :false(遍历是否完成)
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next()); //undefined done:true
//遍历
// for(let v of gen()){ //会输出所有结果 111 一只没有耳朵 ....
// console.log(v);
// }
生成器函数参数
function * gen(arg){
console.log(arg);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
//执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());
//next方法可以传入实参
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
整体打印结果为:
AAA
111 done :false
BBB 第二个next的参数将作为 第一个 yield 的返回值
222 done :false
。。。
异步功能
异步编程 文件操作 网络操作(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();
//模拟获取 用户数据 订单数据 商品数据
function getUsers(){
setTimeout(()=>{
let data = '用户数据';
//调用 next 方法, 并且将数据传入
iterator.next(data);
}, 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();
let orders = yield getOrders();
let goods = yield getGoods();
}
//调用生成器函数
let iterator = gen();
iterator.next();
Promise
Promise 是ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数, 用来封装异步操作并可以获取其成功或失败的结果。
Promise 构造函数: Promise (excutor) {}
Promise.prototype.then 方法
Promise.prototype.catch 方法
//实例化 Promise 对象
const p = new Promise(function(resolve, reject){
setTimeout(function(){
//
// let data = '数据库中的用户数据';
// resolve
// resolve(data); 调用成功
let err = '数据读取失败';
reject(err);
}, 1000);
});
//调用 promise 对象的 then 方法
p.then(function(value){
console.log(value);//成功调用
}, function(reason){
console.error(reason);//失败调用
})
读取文件
使用 node + 文件全名调用js文件
//需要node环境
//1. 引入 fs 模块
const fs = require('fs');
-----------------------------普通方法---------------------------
//2. 调用方法读取文件
fs.readFile('./resources/为学.md', (err, data)=>{//(err,data)=> 这是一个回调函数
//如果失败, 则抛出错误
if(err) throw err;
//如果没有出错, 则输出内容
console.log(data.toString());
});
----------------------使用promise-------------------------------
//3. 使用 Promise 封装
const p = new Promise(function(resolve, reject){
fs.readFile("./resources/为学.mda", (err, data)=>{
//判断如果失败 改变promise对象p的状态 调用reject可以改变它的状态为失败,设置失败的值是err
if(err) reject(err);
//如果成功 改变状态为成功,设置成功的值为data
resolve(data);
});
});
//由于promise是异步进行的,所以调用两个回调函数 看看promise的执行结果
// p.then 两个回调函数为参数, 回调函数中的参数 潜规则:建议写value和reason,成功调用第一个回调函数,失败调用第二个回调函数
p.then(function(value){
console.log(value.toString());
}, function(reason){
console.log("读取失败!!");
});
// 为什么使用promise 因为可以让代码不持续缩进,单个任务使用promise 没什么优势,但是多个异步任务可以不缩进代码
promise封装AJAX请求/接口调用
通过promise 将普通的Ajax请求封装起来,再通过回调函数判断成功或者失败,不会造成回调地狱~结构清晰~ 不会在拿到数据的地方做数据处理,也就是普通AJAX成功或者失败的地方
处理数据 可以在回调函数处理数据,这样每个方法就有了明确的作用~
<script>
// 接口地址: https://api.apiopen.top/getJoke
const p = new Promise((resolve, reject) => {
//1. 创建对象 //整个就是用promise 将AJAX请求包起来,然后改变resolve和reject的状态判断成功或者失败
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); //改造之前 console.log(xhr.response)
} else {
//如果失败
reject(xhr.status); //改造之前 console.error(xhr.status)
}
}
}
})
//指定回调
p.then(function(value){
console.log(value);//处理数据的地方
}, function(reason){
console.error(reason);
});
</script>
then方法-回调
<script>
//创建 promise 对象
const p = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('用户数据');
// reject('出错啦');
}, 1000)
});
调用 then 方法 then方法的返回结果是 Promise 对象, 对象状态(属性状态)由回调函数的执行结果决定
1. 如果回调函数中返回的结果是 非 promise 类型的属性, 状态为成功, 返回值value为对象的成功的值,没有return 返回值为undefined
const result = p.then(value => {
console.log(value);
//1. 非 promise 类型的属性
// return 'iloveyou';
//2. 是 promise 对象 ---成功或失败的状态由返回的promise对象 决定 与返回的promise对象相同
// return new Promise((resolve, reject)=>{
// // resolve('ok'); //同样可以写同步任务
// reject('error');
// });
//3. 抛出错误
// throw new Error('出错啦!'); 状态 为reject 值为 出错啦!
throw '出错啦!'; 和上面相同
}, reason=>{
console.warn(reason);
});
链式调用 ----由于then返回的是一个 promise对象 所以返回的对象同样可以调用then方法,
then的回调可以只写成功的回调方法,失败的回调方法可以不写
p.then(value=>{
}).then(value=>{
});
</script>
promise 异步任务 回避回调地狱演示
//引入 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'));
});
catch
只有then 没有catch也可以~,也可以then只写成功的回调,catch写失败的回调,看着好看一点点~
<script>
const p = new Promise((resolve, reject)=>{
setTimeout(()=>{
//设置 p 对象的状态为失败, 并设置失败的值
reject("出错啦!");
}, 1000)
});
// p.then(function(value){}, function(reason){
// console.error(reason);
// });
p.catch(function(reason){
console.warn(reason);
});
</script>
Set 集合
和Java一样,不可重复,自动去重~
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:
size 返回集合的元素个数
add 增加一个新元素,返回当前集合
delete 删除元素,返回 boolean 值
has 检测集合中是否包含某个元素,返回 boolean 值
clear 清空集合,返回 undefined
<script>
//声明一个 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);
}
</script>
集合使用案例
<script>
let arr = [1,2,3,4,5,4,3,2,1];
//1. 数组去重
// let result = [...new Set(arr)];
// console.log(result);
//2. 交集
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);
//3. 并集
// 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);
</script>
Map
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键” 的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。Map 的属性和方法:
size 返回 Map 的元素个数
set 增加一个新元素,返回当前 Map
get 返回键名对象的键值
has 检测 Map 中是否包含某个元素,返回 boolean 值
clear 清空集合,返回 undefined
<script>
//声明 Map
let m = new Map();
//添加元素
m.set('name','哔哩哔哩~');
m.set('change', function(){
console.log("我们可以改变你!!");
});
let key = {
school : '哔哩哔哩ST'
};
m.set(key, ['北京','上海','深圳']);
//size
// 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);
}
// console.log(m);
</script>
Class类 对象
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
知识点:
class 声明类
constructor 定义构造函数初始化(没有构造函数也是合法的,可以没有属性)
extends 继承父类
super 调用父级构造方法
static 定义静态方法和属性
父类方法可以重写
两种不同的类模板生成方式
<script>
----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);
-----------------------------------------ES6--------------------------------
//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);
</script>
静态成员
<script>
// function Phone(){
// }
// Phone.name = '手机';
// Phone.change = function(){
// console.log("我可以改变世界");
// }
// Phone.prototype.size = '5.5inch';
// let nokia = new Phone();
// console.log(nokia.name); //undefined
// // nokia.change();
// console.log(nokia.size);
-------------------------------------------------ES6------------------------
class Phone{
//静态属性
static name = '手机';
static change(){
console.log("我可以改变世界");
}
}
let nokia = new Phone();
console.log(nokia.name);//undefined
console.log(Phone.name);
</script>
不管是ES5 还是6 静态属性都属于类调用,不属于具体的对象
类的继承
和Java类似
<script>
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);// 调用父类的构造方法~和Java类似
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();
</script>
get 和 set 对属性赋值
注意这里的price 是属性!
<script>
// get 和 set
class Phone{
get price(){
console.log("价格属性被读取了");
return 'iloveyou';
}//当price属性被调用了,这个price函数就会调用,return的值,就是price的值
set price(newVal){
console.log('价格属性被修改了');
}//同理,当price被设置值,会调用set方法,主要用于判断给price设置的值是否合法~
}
//实例化对象
let s = new Phone();
// console.log(s.price);
s.price = 'free';
</script>
数值扩展
<script>
0. 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))
1. 二进制和八进制
let b = 0b1010;
let o = 0o777;
let d = 100;
let x = 0xff;
console.log(x);
2. Number.isFinite 检测一个数值是否为有限数
console.log(Number.isFinite(100));
console.log(Number.isFinite(100/0));
console.log(Number.isFinite(Infinity));
3. Number.isNaN 检测一个数值是否为 NaN
console.log(Number.isNaN(123));
4. Number.parseInt Number.parseFloat字符串转整数
console.log(Number.parseInt('5211314love'));
console.log(Number.parseFloat('3.1415926神奇'));
5. Number.isInteger 判断一个数是否为整数
console.log(Number.isInteger(5));
console.log(Number.isInteger(2.5));
6. Math.trunc 将数字的小数部分抹掉
console.log(Math.trunc(3.5));
7. Math.sign 判断一个数到底为正数 负数 还是零
console.log(Math.sign(100));
console.log(Math.sign(0));
console.log(Math.sign(-20000));
</script>
对象方法扩展
<script>
//1. Object.is 判断两个值是否完全相等
// console.log(Object.is(120, 120));// ===
// console.log(Object.is(NaN, NaN));// ===
// console.log(NaN === NaN);// ===
//2. Object.assign 对象的合并
// const config1 = {
// host: 'localhost',
// port: 3306,
// name: 'root',
// pass: 'root',
// test: 'test'
// };
// const config2 = {
// host: 'http://bilibili.com',
// port: 33060,
// name: 'bilibili.com',
// pass: 'iloveyou',
// test2: 'test2'
// }
// console.log(Object.assign(config1, config2));// 用2的属性 覆盖第一个 1有2没有的属性不会变化,2有1没有的属性,1不会变化
//3. Object.setPrototypeOf 设置原型对象 Object.getPrototypeof
const school = {
name: '哔哩哔哩'
}
const cities = {
xiaoqu: ['北京','上海','深圳']
}
Object.setPrototypeOf(school, cities);
console.log(Object.getPrototypeOf(school));
console.log(school);
</script>
模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的好处:
防止命名冲突
代码复用
高维护性
模块化规范产品:
ES6 之前的模块化规范有:
1) CommonJS => NodeJS、Browserify
2) AMD => requireJS
3) CMD => seaJS
ES6 模块化语法
模块功能主要由两个命令构成:export 和 import。
export 命令用于规定模块的对外接口
import 命令用于输入其他模块提供的功能
export 举例
js文件:
//分别暴露
export let school = '哔哩哔哩';
export function teach() {
console.log("我们可以教给你开发技能");
}
-----------------------m2文件--------------------
//统一暴露
let school = '哔哩哔哩';
function findfriend(){
console.log("我们可以帮助你找机油!!");
}
//
export {school, findfriend};
--------------------------m3----------------------------
//默认暴露
export default { //{里面可以是一个任意内容,字符串,数字等,对象居多}
school: 'BLBL',
change: function(){
console.log("我们可以改变你的取向!!");
}
}
html文件:
<script type="module">
1. 通用的导入方式
引入 m1.js 模块内容
import * as m11 from "./src/js/m1.js"; //*将所有暴露的类容导入m11这个对象
//引入 m2.js 模块内容
import * as m22 from "./src/js/m2.js";
//引入 m3.js
import * as m33 from "./src/js/m3.js"; //m3 是默认暴露,如果要调用m33中的方法
//需要多调用一层default-----》m33.default.method()
2. 解构赋值形式
import {school, teach} from "./src/js/m1.js";
import {school as bilibili, findfriend} from "./src/js/m2.js";//school重名了 使用别名
import {default as m3} from "./src/js/m3.js";//不能直接使用default 要使用别名~
3. 简便形式 针对默认暴露!!!
import m3 from "./src/js/m3.js";
console.log(m3);
</script>
另一种引入方式:
项目中一般不会这样引入,因为有的浏览器不支持ES6~!!
<script src="./src/js/app.js" type="module"></script>
入口文件app.js
//入口文件
//模块引入
import * as m1 from "./m1.js";
import * as m2 from "./m2.js";
import * as m3 from "./m3.js";
babel对ES6模块化代码进行转换
不是所有浏览器都对ES6支持~!!
略!
<!--
1. 安装工具 npm i babel-cli babel-preset-env browserify(webpack) -D
2. 编译 npx babel src/js -d dist/js --presets=babel-preset-env
3. 打包 npx browserify dist/js/app.js -o dist/bundle.js
-->
<script src="dist/bundle.js"></script>