一、ES6
1.1.let
变量声名以及声名特性
1.声明的变量不能重复声明
2.块级作用域(全局,函数,eval);
{
let girl = '***'
}
只在代码块里有效。
3.不存在变量提升
不允许在定义变量前调用变量
console.log(song)
var song = '***'
----underfine
console.log(song)
let song = '***'
----报错
4.不影响作用域链
1.2.const
声明常量以及特点
1.一定要赋初始值,不然控制台会报错
2.一般常量使用大写(潜规则)
3.常量的值不能修改
const fff = '$$$'
fff = '%%%'
----报错
4.块级作用域
{
const play = '^^^'
}
console.log(play)
---underfine
5.对于数组和对象的元素的修改,不算对常量的修改,不会报错。因为用const
定义数组和对象,常量名只是保存了它们的地址(指针),const
定义的引用数据类型,保存的事地址,地址本身不能修改,但是它所指的那片堆内存是可以改变的。
1.3.模板字符串
1.ES6引入新的声字符串的方式 [``]
2.内容中可以直接出现换行符。
3.变量拼接
let fff = '某某某'
let ddd = '${fff}水泥地发射点'
console.log(ddd)
---'某某某水泥地发射点'
1.4.解构赋值
ES6
允许按照一定模式从数组和对象中提取值,对变量进行赋值,者被称为解构赋值。解构同名属性就是获取那个同名属性,自定义变量名就按顺序解构赋值。数组是按顺序赋值的,对象是按变量名赋值的。
1.数组的结构
const F4 = ['11','22','33'];
let [one,two,three];
console.log(one)
console.log(two)
console.log(three)
----
11
22
33
----
2.对象的解构
const zhao = {
name:'赵',
age:'不知',
xiaoping: function(){
console.log("我可以")
}
}
let {name,age,xiaopin} = zhao;
console.log(name);
...
xiaoping();
let {xiaopin} = zhao
xiaopin() // 不用再前面加一个zhao.
1.5.对象的简化写法
ES6
允许再大括号里面,直接写入变量和函数,作为对象的属性和方法。
这样的书写更加简洁。
let name = '##';
let change = function(){
console.log('^^&&&%')
}
const school = {
name:name,
change:change,
improve:function(){
console.log("33445566")
}
}
-----简化后
const school = {
name,
change,
improve(){
console.log("33445566")
}
}
1.6.箭头函数以及声明特点(重点)
ES6
允许使用[箭头] (=>) 定义函数
声明一个函数
let fn = (a,b) => {
return a + b;
}
1.this 是静态的,this 始终指向函数声明时所在作用域下的this的值(无论用声明方法去调用箭头函数,箭头函数所指向的值都是不变的)。
function getName(){
console.log(this.name)
}
function getName2 = () => {
console.log(this.name)
}
// 设置 window 对象的 name 属性
window.name = '111';
const school = {
name:"222"
}
// 直接调用
getName(); // 111
getName2(); // 111
//call 方法调用,call 方法是可以改变函数方法里面的this的指向。
getName(school);// 222
getName2(school);// 111
2.不能作为构造实例化对象
let Person = (name,age) => {
this.name = name;
this.age = age;
}
let me = new Person('xiao',20)
console.log(me)
---控制台上会报错
3.不能使用 argument 变量(argument用于存放函数的所有形参)
let fn = () => {
console.log(argument)
}
fn(1,2,3)
---控制台上会报错
4.箭头函数的简写
(1)省略小括号,当形参有且只有一个的时候
let add = n => {
return n + n;
}
console.log(add(9));
--- 18
(2)省略花括号,当代码体只有一条语句的时候,此时 return 必须省略(还可以省略小括号),而且语句的执行结果就是函数的返回值
let pow = n => n*n;
console.log(pow(9))
---81
1.7.箭头函数总结
看箭头函数外层是否有函数,如果有,则外层函数的this就是箭头函数的this。如果没有,则this就是window。
普通函数
const arr = [1,6,9,10,100,25]
const result = arr.filter(function(){
if(item % 2 === 0)
return true
else{
return false
}
});
箭头函数
const result = arr.filter(item => item % 2 === 0)
console.log(result)
箭头函数适合与 this 无关的回调,如定时器,数组的方法问题;
箭头函数不适合与 this 有关的回调,如DOM元素的事件回调,对象的方法;
{
name:'###',
getName() => {
this.name;
}
}
btn.addEventListener("click",function(){
//此时普通函数的this指向事件源
//如果使用箭头函数,事件源将变成外部作用域的this值,即这个函数所在的作用域
})
扩展:就是对象中的箭头函数的 this 永远和最外层的对象所处的环境的this保持一致,不论套了多少层。
1.8.函数参数的默认值设置
ES6
允许给函数参数赋值初始化值
1.形参初始值 具有默认值的参数,一般位置要靠后(潜规则)
function add(a,b,c=10){
return a + b + c
}
let result = add(1,2);
let result2 = add(1,2,3);
console.log(result)
console.log(result2)
----13
----6
2.与解构赋值结合
function connect({host="127.0.01",username,password,port}{
console.log(host)
console.log(username)
console.log(password)
console.log(port)
})
// 往里面传一个对象实参
connect({
host:'ftpp.com',
username:'root',
password:'root',
port:3306
})
当你传了实参的值就用实参的值,若没有传递实参的值,就默认用形参的值。
1.9.rest
参数
ES6
引入rest参数,用于获取函数的实参,用来代替 arguments
ES5
获取实参的方法
function data(){
console.log(arguments);
}
data('11','22','33');
res参数(rest参数必须要放到参数后面)
function data(...arges){
console.log(arges);
}
data('11','22','33');
const obj1={
q:'zzl'
}
const obj2={
s:'wxl'
}
const data={...obj1,...obj2}; //相当于合并了两个对象
console.log(data);//{q:'zzl',s:'wxl'}
1.10.扩展运算符
[…] 扩展运算符能将 [数组] 转换为逗号分隔的 [参数序列]
const school =['赵','张','王']
function ch(){
console.log(arguments)
}
ch(...school) // 相当于 ch('赵','张','王')
ch(school) //相当于 ch(school)
1.11.扩展运算符的运用
1.数组的合并
const K = ['11','22'];
const M = ['33','44'];
const L = [...K,...M]
console.log(L)
---11,22,33,44
2.数组的克隆
const A = ['E','G','M']
const B = [...A]; // ['E','G','M']
数组的克隆:若是有引用数据类型的话,也是浅拷贝。深拷贝会另外创造一个一模一样的对象,新对象跟原来对象不共享内存,修改新对象不会改到原对象。
3.将伪数组转为真正的数组
const divs = document.querySelectorAll('div')
// divs是一个对象
const divArr = [...divs]
console.log(aivArr);//现在是一个数组
1.12.Symbol
ES6
引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol特点:
-
Symbol的值是唯一的,用来解决命名冲突的问题
-
Symbol值不能与其他数据进行运算
-
Symbol定义的对象属性不能使用for…in循环遍历,但是可以使用
-
Reflect.ownKeys
来获取对象的所有键名
1.创建Symbol
//1.
let s = Symbol()
let S1 = Symbol()
let S2 = Symbol()
console.log(S1 === S2)
// false
//2.Symbol.for创建
let S3 = Symbol.for('11')
let S4 = Symbol.for('22')
console.log(S3 === S4)
// true
2.不能与其他数据进行运算
let result = s + 100
let result = s > 100
let result = s + s
// 以上的结果再控制台上都会报错
Symbol.for
:该方法会根据给定的键 key ,来从运行时的 symbol 注册表中找到对应的 symbol ,如果找到了,则返回它,否则,新建一个与该键关联的 symbol ,并放入全局 symbol 注册表中。
js
中的八大数据类型:
u underfined
s string symbol
o object
n null number
b boolean
1.13.对象添加Symbol类型的属性
1.给对象添加方法方式一:
let game = {name:'ran'};
//声明一个对象
let game = {
up:Symbol();
down:Symbol()
};
game[method.up] = function(){
console.log("$$$")
}
game[method.down] = function(){
console.log("%%%")
}
// 用 Symbol 添加的属性不会与game中相同属性名的属性冲突
2.给对象添加方法方式二:
let youxi = {
name:'狼人杀',
[Symbol('say')]:function(){
console.log("我可以发言")
},
[Symbol('zibao')]:function(){
console.log("我可以自爆")
},
}
// 最后在对象youxi外部调用:youxi[say]()这样就可以调用“我可以发言”那个方法了,调用:先在对象外定义变量`let say = Symbol('say')`,在把对象youxi内部中括号的Symbol('say')替换成刚刚在外面定义的变量say,即[say]:function
总结:为了防止你创建的方法和之前已经创建的对象本身的方法冲突,选择在另一个对象中用symbol
创建独一无二的方法,用[]调用,不会污染本身对象中的方法。
Symbol
值作为对象属性名时,不能用点运算符,哎对象内部,使用 Symbol
值定义属性时,Symbol
值必须放在方括号之中。
Symbol()
在添加一个属性给一个方法时,不会和方法中现有的属性名冲突,更好添加属性。
1.14.迭代器的应用-自定义遍历数据
1.迭代器(lterator
)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署lterator
接口,就可以完成遍历操作。
2.原理:
(1)创建一个指针对象,指向数据结构的起始位置;
(2)第一次调用==next()==方法,指针自动指向数据结构第一个成员;
(3)接下来不断调用next(),指针一直往后移动,直到指向最后一个成员;
(4)每次调用next()就返回一个包含value和done属性的对象
手写迭代器,应用:
const banjin = {
name:'尼古拉斯凯奇',
stus:[
'xsz',
'dfc',
'sfd',
'sdf',
],
//自己给某些结构加上iterator接口
[Symbol.iterator](){
// 索引遍历
let index = 0;
// 存放btn的this
let _this = this;
return {//返回一个指针对象,即创建一个指针对象
next:function(){//创建对象的next方法
if(index < _this.stus.length){
const result = {vaule:_this.stus[index],done:false};
//下标自增
index++;
//返回结果
return result
}else{
return {value:undefined,done:true};
}
}
}
}
}
for(let v of banjin){
console.log(v);
}
由于自己定义的对象无法用 for of
来遍历,所以要自己手动添加迭代器。
数组的常用方法:
forEach
缺点:找到目标还会继续循环,并且不受return和break的影响。
some
找到目标后,可以通过return结束循环。
const arr=[]
arr.some((item,index)=>{
if(item=='zzl'){
console.log(item)
return true
}
})
every
只要每一项都满足every里面的判断条件,则最终返回true。
const arr=[
{id:1,state:true},
{id:2,state:true}
]
//判断数组中的所有state是否都为true
const result=arr.every(item=>item.state)
filter
const data=arr.filter(item=>item.state)
filter会把满足条件的数据重新过滤到的新数组中,不满足的通通过滤掉。
reduce
arr.filter(item=>item.state).reduce(累加的结果,当前循环项)=>{ },初始值)
第一次循环累加的结果默认等于初始值,以后循环累加的结果等于上一次累加的结果加上循环项里的数据。
const arr=[{id:1,state:true,price:10}]
let sum=0
arr.filter(item=> item.state).reduce((sum,item)=>{
return sum += item.price
//return给下一次累加使用
},0)
1.15.生成器函数声明与调用
生成器函数是ES6
提供的一种异步编程解决方案,语法行为与传统函数完全不同,是一种特殊的函数
异步编程,纯回调函数 node
,fs
,ajax
,mongdb
yield是函数代码的分隔符:
function * gen(){
yield '一只';
yield '二只';
yield '三只';
}
let iterator = gen()
console.log(iterator.next()) //{value:"一只",done:false} 执行第一段,并且返回yield后面的值。
console.log(iterator.next())//{value:"二只",done:false}
console.log(iterator.next())//{value:"三只",done:false}
console.log(iterator.next())//{value:"underfined",done:true}
for(let v of gen()){
console.log(v)
}
//一只,二只,三只
iterator刚开始指向gen函数的地址,而yield又把函数分成了若干个节点,iterator通过next可以依次访问各个节点。
1.16.生成器函数的传递参数
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 --- arg
//{value:111,done:false}
//BBB --- one
//{value:222,done:false}
//CCC --- two
//{value:333,done:false}
//DDD --- three
//{value:"underfined",done:true}
在next里传递参数进去,则是传给当前yield的上一个yield的值
1.17.生成器实例(重点)
异步编程:文件操作,网络操(Ajax,request)数据库操作
1.要求:过一秒输出111,过两秒输出222,过三秒输出333,
使用传统计时器:
setTimeout(()=>{
console.log(111);
setTimeout(()=>{
console.log(222);
setTimeout(()=>{
console.log(333);
},3000)
},2000)
},1000)
这样就会形成回调地狱。
使用生成器函数,解决回调地狱问题。
function one(){
setTimeout(()=>{
console.log(111);
},1000)
}
function two(){
setTimeout(()=>{
console.log(222);
},2000)
}
function three(){
setTimeout(()=>{
console.log(333);
},3000)
}
function * gen(){
yield one;
yield two;
yield three;
}
//调用生成器函数
let iterator = gen();
iterator.next();
2.模拟异步获取用户数据,再获取订单数据,再获取对应的商品数据
function getUsers(){
setTime(()=>{
let data = "用户数据";
// 调用next方法,并且将数据传入
iterator.next(data);
},1000)
};
function getGoods(){
setTime(()=>{
let data = "订单数据";
iterator.next(data);
},1000)
};
function getOrder(){
setTime(()=>{
let data = "商品数据";
iterator.next(data);
},1000)
};
function * gen(){
let users = yield getUsers;
console.lod(users)
let goods = yield getGoods;
console.lod(goods)
let order = yield getOrder;
console.lod(order)
}
// 调用生成器函数
let iterator = gen()
//启动生成器函数
iterator.next()
与同步有些相似,实际上还是异步操作
1.18.Promise
Promise是ES6
引入的异步编程的新解决方案。语法上 Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
1.基本特性:
<script>
const p =new Promise((resolve, reject)=>{
setTimeout(()=>{
let data='数据库数据'
// resolve(data);
reject(data);
})
})
p.then(function (value){ //成功则执行第一个回调函数,失败则执行第二个
console.log(value)
},function (reason){
console.error(reason)
})
</script>
2.Promise.then()
方法
<script>
const p =new Promise((resolve, reject) =>{
setTimeout(()=>{
resolve('用户数据');
})
});
//then()函数返回的实际也是一个Promise对象
//1.当回调后,返回的是非Promise类型的属性时,状态为fulfilled,then()函数的返回值为对象的成功值,如reutnr 123,返回的Promise对象值为123,如果没有返回值,是undefined
//2.当回调后,返回的是Promise类型的对象时,then()函数的返回值为这个Promise对象的状态值
//3.当回调后,如果抛出的异常,则then()函数的返回值状态也是rejected
let result = p.then(value => {
console.log(value)
// return 123;
// return new Promise((resolve, reject) => {
// resolve('ok')
// })
throw 123
},reason => {
console.log(reason)
})
console.log(result);
</script>
3.Promise.catch()
方法
//catch() 函数只有一个回调函数,意味着如果 Promise 对象状态为失败就会调用 catch() 方法并且调用回调函数
<script>
const p = new Promise((resolve, reject) => {
setTimeout(()=>{
reject('出错啦')
},1000)
})
p.catch(reason => {
console.log(reason)
})
</script>
1.19.Promise封装Ajax的请求
function sendAjax(url) {
return new Promise((resolve, reject) => {
// 1.创建对象
const xhr = new XMLHttpRequest();
xhr.responseType = 'json';
// 2.初始化设置请求方法(类型)和url
xhr.open("GET", "https://api.apiopen.top/getJoke", true);
// 3.发送
xhr.send();
// 4.绑定事件,onreadystatechange,存储函数(或函数名)处理响应结果(每当 readyState 改变时,就会触发 onreadystatechange 事件,一共会触发 4 次,从 0 到 4)
// readyState 属性存有 XMLHttpRequest 的状态信息
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject(xhr.status);
}
}
}
})
}
sendAjax()
.then(value => {
console.log(value);
// console.log(sendAjax());
}, reason => {
console.warn(reason);
})
1.20.Promise.then()
方法
<script>
const p =new Promise((resolve, reject) =>{
setTimeout(()=>{
resolve('用户数据');
})
});
//then()函数返回的实际也是一个Promise对象
//1.当回调后,返回的是非Promise类型的属性时,状态为fulfilled,then()函数的返回值为对象的成功值,如reutnr 123,返回的Promise对象值为123,如果没有返回值,是undefined
//2.当回调后,返回的是Promise类型的对象时,then()函数的返回值为这个Promise对象的状态值
//3.当回调后,如果抛出的异常,则then()函数的返回值状态也是rejected
let result = p.then(value => {
console.log(value)
// return 123;
// return new Promise((resolve, reject) => {
// resolve('ok')
// })
throw 123
},reason => {
console.log(reason)
})
console.log(result);
</script>
1.21.Promise
实践练习-多个文件内容读取
使用传统的函数嵌套会造成回调地狱
使用promise实现
const p = new Promise((resolve,reject) => {
fs.readFile("./文件夹/文件1.md",(err,data) => {
resolve(data);
});
});
// 可以使用Promise链来实现,而且p.then()返回的也是一个Promise类型的值
p.then(value => {
return new Promise(((resolve,reject) => {
fs.readFile("./文件夹/文件2.md",(err,data) => {
//以数组的形式传递给下一个then
resolve([value,data]);
});
})
}).then(value => {
return new Promise((resolve,reject) => {
fs.readFile("./文件夹/文件3.md",(err,data) => {
value.push(data)
resolve(value)
})
})
}).then(value => {
console.log(value)
})
1.22.Promise.catch()
方法
//catch()函数只有一个回调函数,意味着如果Promise对象状态为失败就会调用catch()方法并且调用回调函数
<script>
const p = new Promise((resolve, reject) => {
setTimeout(()=>{
reject('出错啦')
},1000)
})
p.catch(reason => {
console.log(reason)
})
</script>
2.1.Set
ES6
提供了新的数据结构set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用[扩展运算符]和[ for…of…]进行遍历,集合的属性和方法(还可以数组去重):
-
size返回集合的元素个数
-
add增加一个新元素,返回当前集合
-
delete删除元素,返回boolean值has检测集合中是否包含某个元素,返回boolean值
<script>
let s = new Set();
let s2 = new Set(['A','B','C','D'])
//元素个数
console.log(s2.size);
//添加新的元素
s2.add('E');
//删除元素
s2.delete('A')
//检测集合中是否存在要检测的元素
console.log(s2.has('C'));
//清空
s2.clear()
console.log(s2);
</script>
2.2.集合实践
<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 result2 = [...new Set(arr)].filter(item => new Set(arr2).has(item))
console.log(result2);
//3.并集
let result3=[new Set([...arr,...arr2])]
console.log(result3);
//4.差集
let result4= [...new Set(arr)].filter(item => !(new Set(arr2).has(item)))
console.log(result4);
</script>
2.3.Map
ES6
提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,所以可以使用『扩展运算符』和「for…of…』进行遍历。Map的属性和方法。
<script>
let m = new Map();
m.set('name','ran');
m.set('change',()=>{
console.log('改变!')
})
let key={
school:'atguigu'
}
m.set(key,['成都','西安']);
//size
console.log(m.size);
//删除
m.delete('name');
//获取
console.log(m.get('change'));
// //清空
// m.clear()
//遍历
for(let v of m){
console.log(v);
}
</script>
3.1.Class
ES6
提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6
的class可以看作只是一个语法糖,它的绝大部分功能,ES5
都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
<script>
class shouji {
// constructor是构造方法,名字不能修改
constructor(brand,price) {
this.brand=brand;
this.price=price
}
//方法必须使用该语法,不能使用 ES5 的对象完整形式
call(){
console.log('我可以打电话')
}
}
//实例化对象
let A = new shouji('1+',1999);
console.log(A)
</script>
3.2.Class
的静态成员
<script>
class Person{
static name='手机'
}
let nokia = new Person();
console.log(nokia.name);
</script>
3.3.构造函数继承
javascript
的继承主要是依托其 原型与原型链
的概念来实现的。
- 构造函数:用来初始化新对象的函数叫做构造函数。如示例中的
Cat
函数就是构造函数 - 实例对象:通过
new
关键字创建出来的对象。如3.2中的Person
就是实例对象 - 原型对象及
prototype
:构造函数有一个prototype
属性,它指向实例对象的原型。常使用原型对象来实现继承 - constructor:原型对象具有
constructor
属性,指向原型对象的构造函数 proto
:__proto__
属性类似是指针,指向构造函数的原型对象。prototype
和__proto__
的区别,简单理解为:构造函数.prototype === 实例对象.__proto__
,他们都指向同一个原型对象。
原型链:JavaScript
对象(除了 null
)在创建的时候就会关联一个对象,这个对象就是原型,每一个对象都会从原型上继承属性,原型也是对象,所以原型也有原型对象,层层往上,直到 Object.prototype
,这就是原型链。
<script>
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('我可以玩游戏');
}
const chuizi = new SmartPhone('锤子',2499,'黑色','5.5inch')
console.log(chuizi);
</script>
3.4.Class
的类继承
定义一个子类,来继承一个父类,子类通过super传递参数,来调用父类的构造函数,来进行初始化子类构造方法中一些与父类构造方法中同名的变量,也可以说super === 父类的constructor
<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传递参数,来调用父类的构造函数,(super === Phone.constructor)来做初始化
super(brand,price);
this.color=color;
this.size=size;
}
// 以下是子类独有的方法
photo(){
console.log('拍照');
}
playGame(){
console.log('打游戏');
}
}
const xiaomi=new SmartPhone('小米',1999,'黑色','4.7inch')
xiaomi.call();
xiaomi.photo();
xiaomi.playGame();
</script>
3.5.子类对父类方法的重写
子类对父类中的方法重写覆盖。
<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);
this.color=color;
this.size=size;
}
photo(){
console.log('拍照');
}
playGame(){
console.log('打游戏');
}
//重写!!内容会将父类中的同名方法中的内容覆盖掉
//但在子类显示原型的隐形原型里面,原有的方法还存在。
call(){
console.log('我可以进行视频通话')
}
}
const xiaomi=new SmartPhone('小米',1999,'黑色','4.7inch')
xiaomi.call();
xiaomi.photo();
xiaomi.playGame();
</script>
3.6.get
和set
的设置
<script>
class Phone{
get price(){
console.log("价格被读取了")
return 'I LOVE YOU'
}
set price(val){
console.log('价格被修改了')
return val;
}
}
//实例化对象
let s = new Phone();
s.price=12
// console.log(s.price) //其实是调用price方法
</script>
3.6.数值扩展
<script>
// Number.EPSILON是 JavaScript的最小精度,属性的值接近于 2.22044...E-16
function equal(a,b){
if(Math.abs(a-b) < Number.EPSILON){
return true;
}else {
return false;
}
}
console.log(equal(0.1 + 0.2 === 0.3)) //false
console.log(equal(0.1+0.2,0.3)) //true
//二进制和八进制
let b = 0b1010; //2进制
let o = 0o777; //8进制
let d = 100; //10进制
let x = 0xff; //16进制
console.log(x) //255
//检测一个数是否为有限数
console.log(Number.isFinite(100)); //true
console.log(Number.isFinite(100/0)); //false
console.log(Number.isFinite(Infinity)); //false
//检测一个数值是否为NaN
console.log(Number.isNaN(123)) //false
//字符串转整数
console.log(Number.parseInt('5213123love')); //5213123
console.log(Number.parseFloat('5.123123神器')); //5.123123
//判断是否为整数
console.log(Number.isInteger(5)); //true
console.log(Number.isInteger(2.5)); //false
//将小数部分抹除
console.log(Math.trunc(3.45345345345)) //3
//检测一个数到底是正数、负数、还是0
console.log(Math.sign(100)) //1
console.log(Math.sign(0)) //0
console.log(Math.sign(-123)) //-1
</script>
3.7.对象方法扩展
<script>
//1.Object.is 判断两个值是否完全相等
console.log(Object.is(120,120)) //true
console.log(Object.is(NaN,NaN)) //false
//2.Object.assign 对象的合并
const a = {
name:'ran',
age:12
}
const b = {
pass:'i love you'
}
console.log(Object.assign(a,b)) //{name:'ran',age:'12',pass:'i love you'}
//3.Object.setPrototypeOf 设置原型对象 Object.getPrototypeof
const school = {
name:'尚硅谷'
}
const cities = {
xiaoqu:['北京','上海']
}
Object.setPrototypeOf(school,cities)
console.log(Object.getPrototypeOf(school)) //{xiaoqu: Array(2)}
console.log(school) //{name: "尚硅谷"}
</script>
4.1.模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的好处:
- 防止命名冲突
- 代码复用
- 高维护性
- 模块化规范产品
ES6之前的模块化规范有:
CommonJS ====> NodeJS、Browserify
AMD ====> requireJS
CMD ====> seaJS
语法:
模块功能主要有两个命令构成:export和import
export命令用于规定模块的对外接口
import命令用于输入其他模块提供的功能
浏览器使用ES6的模块化方式一
1.通用的导入方式
m1.js文件(分别暴露)
export let school = '尚硅谷'
export function teach(){
console.log('教技能')
}
m2.js文件(统一暴露)
let school = 'ATSDFG'
function teach1(){
console.log("%%")
}
export {school,teach}
m3.js文件(默认暴露)
export default {
school:'ATSDFG',
change:function (){
console.log("&&&")
}
}
<script type="module">
import * as m1 from "./src/js/m1.js";
import * as m2 from "./src/js/m2.js";
import * as m3 from "./src/js/m3.js";
console.log(m1);
</script>
2.解构解析
<script type="module">
import {school,teach} from "./src/js/m1.js";
import {school as gui,teach1} from "./src/js/m2.js";
import {default as m3} from "./src/js/m3.js";
// 有名称上的冲突,需要用别名来解决
console.log(school,teach)
console.log(gui,teach1)
console.log(m3)
</script>
3.简便方式 (针对默认暴露)
<script>
import m3 from "./src/js/m3.js";
</script>
暴露抛出来的是一个对象,引入也是对象,就是对象的结构解析,如let{a,b}={a:...,b=....}
浏览器使用ES6的模块化方式二
app.js文件
// 入口文件
//模块引入
import * as m1 from "./m1.js";
import * as m2 from "./m2.js";
import * as m3 from "./m3.js";
console.log(m1)
console.log(m2)
console.log(m3)
<script src="./src/js/app.js" type='module'></script>
4.2.ES6-babal对模块化代码的转换
1.安装工具 babel-cli babel-preset-env browserify(webpack)
2.npx babel src/js -d dist/js
3.打包
4.3.lncludes方法
lncludes方法用来检测数组中是否包含某个元素,返回布尔类型值
4.4.
在ES7中引入指数运算符「**」,用来实现幂运算,功能与Math.pow结果相同
二、ES8
1.1.ES8的async函数
async function fn(){
//返回一个字符串
//return '@@@'
//返回的结果不是一个 Promise 类型的对象,返回的结果就是成功 Promise 对象
//抛出错误,返回的结果是一个失败的 promise
//throw 呢哇 Error('出错啦!')
//返回的结果如果是一个 Promise 对象
return new Promise((resolve,reject) => {
resolve('成功的数据')
})
}
const result = fn()
//调用 then 方法
result.then(value => {
console.log(value)
},reason => {
console.warn(reason)
})
这里的返回值如果不是一个Promise对象,则默认返回一个成功状态的promise,如果你不显式的return一个值,则默认返回undefined。
1.2.await表达式
一般与async函数一起使用,当await定义的Promise对象返回的是一个失败的值,那么就要与try...catch...
结合使用,使用try...catch...
来捕获错误。
如何体现await与async函数的异步操作:只要有一个await语句后的promise对象是reject,那么整个async函数都会中断执行。
1.3.async与await结合发送ajax请求
async 与 await 测试
// 发送 AJAX 请求,返回的结果是 Promise 结果
function sendAjax(url) {
return new Promise((resolve, reject) => {
// 1.创建对象
const x = new XMLHttpRequest()
// 2.初始化
x.open('GET', url)
// 3.发送
x.send()
// 4.事情绑定
x.onreadystatechange = function () {
if (x.readyState === 4) {
if (x.status >= 200 && x.status < 300) {
// 成功!
resolve(x.response)
} else {
// 如果返回是一个错误的结果
reject(x.status)
}
}
}
})
}
// Promise then 方法测试
sendAjax("https://api.apiopen.top/getJoke").then(value => {
console.log(value)
}, reason => {
})
// async与await结合发送Ajax请求
async function fn() {
let re1 = await sendAjax('https://api.apiopen.top/getJoke')
console.log(re1)
}
fn()
1.3.ES8的扩展
// 声明对象
const school = {
name:'@@',
cities:['43','##','$$'],
xueke:['adf','dsf','sdf','sdfg']
}
//获取对象所有的键
console.log(object.keys(school));//获取对象所有的值
console.log(object.values(school));/ / entries
console.log(object.entries(school));//创建Map
const m = new Map(Object.entries(school));
console.log(m.get( 'cities ' ));
三、ES9
1.1.ES9扩展运算符与rest参数
Rest参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符。
//1.
function connect({host,port, ...user}){
console.log(host);
console.log(port);
console.log(user);
}
connect({
host: '127.0.0.1',
port: 3306,
username: 'root',
password: 'root',
type: 'master'
});
// ---- 输出的是 127.0.0.1,3306,root,root,master
//2.
const skill1 = {
q:'!!',
w:'@@'
}
// ... skill1 => q:'!!',w:'@@'
const skill2 = {
e:'$$'
const skill3 = {
r:'%%'
}
const mangseng = {...skill1,...skill2,...skill3}
console.log(magseng) // q:'!!',w:'@@',e:'$$',r:'%%'
1.2.ES9正则扩展-命名捕获分组
// 声明一个字符串
let str1 = '<a href="http://www.atgui.com">尚硅谷</a>'
// /提取 url 与 【标签文本】
const reg = /<a href="(.*)">(.*)<\/a>/
const result = reg.exec(str1)
console.log(result)
---result.group:undefined
// 命名捕获分组
let str2 = 'a href="http://www.atgui.com">尚硅谷</a>'
const reg = /<a href="( ?<ur1>.*)">(?<text>.*)<\V/a>/;
const result = reg.exec(str2);
console.log(result.groups.ur1);
console.log(result.groups.text);
四、ES10
1.1.ES10对象扩展方法—Object.fromEntries
方法 Object.fromEntries()
把键值对列表转换为一个对象,这个方法是和 Object.entries()
相对的。
//二维数组
const result = Object.fromEntries([
[ 'name','尚硅谷'],
[ 'xueke' , 'Java,大数据,前端,云计算']
]);
console.log(result)
---
{name:"尚硅谷",xueke:"Java,大数据,前端,云计算"}
//Map
const m = new Map()
m.set('name','11')
const result = Object.fromEntries(m)
console.log(result)
----
{name:"11"}
//Object.entries ES8
const arr = Object.entries({
name:"11"
})
console.log(arr)
---
[Array(2)]
0:(2) ["name","11"]
1.2.数组扩展方法–flat与flatMap
//flat
//将多维数组转化为低位数组
const arr1 = [1,2,3,4,[5,6]]
console.log(arr1.flat())
--- [1,2,3,4,5,6]
const arr2 = [1,2,3,4,[5,6,[7,8,9]]]
//参数为深度,是一个数字
console.log(arr2.flat(2))
--- [1,2,3,4,5,6,7,8,9]
//flatMap
const arr3 = [1,2,3,4]
const result1 = arr3.flatMap(item => item * 10)
console.log(result1)
五、ES11
1.1.ES11-私有属性
class Person {
//公有属性
name;
//私有属性
#age;
#weight;
//构造方法
constructor(name,age,weight){
this.name = name;
this.#age = age;
this.#weight = weight
}
intro(){
console.log(this.name)
console.log(this.#age)
console.log(this.#weight)
}
}
//实例化
const mm = new Person('meimei',18,'45kg')
1.2.ES11-Prmoise.allSettled属性
//声明两个promise对象
const p1 = new Promise((resolve, reject)=>{
setTimeout(() => {
resolve('商品数据-1');
},1000)
});
const p2 = new Promise((resolve, reject)=>{
setTimeout(() => {
resolve('商品数据- 2');// reject('出错啦!');
},1000)
});
//调用 allSettled 方法
const result = Promise.allSettled([p1,p2])
//调用 all 方法
const result1 = Promise.all([p1,p2])
//allSettled得出的结果是一个数组,数组里面包含了Promise对象的状态与value值
//all如果数组中的所有的Promise对象的状态都为成功的,那么将输出所有该数组中Promise对象中的键值,如果有一个Promise对象的状态为失败,那么all的状态则为失败的。
1.3.ES11-可选链操作符
function main( config){
// const dbHost = config && config.db &8 config.db.host;
const dbHost = config?.db?.host;
console.log(dbHost);
}
main({
db:{
host: ' 192.168.1.100',username: "root'
},
cache: {
host: '192.168.1.208' ,username: ' admin'
}
})
选用可选链操作符不会显示相关报错。
1.4.ES11-动态import
一般为了维护,会选择用动态引入模块。
//import * as m1 from "./hello.js";//获取元素
const btn = document.getElementById('btn');
btn.onclick = function(){
import('./hello.js').then(module => {
module.hello();
});
}
1.5.ES11-BigInt类型
//大整形,在定义好的整形数据后放一个n,则表示这个数据为最大整形数据
// let n = 521n;
// console.log(n,typeof(n));
//函数,可以通过BigInt这个函数将整形转化为最大整形
// let n = 123;
// console.log(BigInt(n));
// 但是不能是除整形类型数据的其他类型数据
// console.log(BigInt(1.2));
//大数值运算
let max = Number.MAX_SAFE_INTEGER;
console.log(max);
console.log(max + 1);
console.log(max + 2);
console.log(BigInt(max))
console.log(BigInt(max) + BigInt(1))
console.log(BigInt(max) + BigInt(2))
1.6.ES11-绝对全局对象globalThis
使用场景:由于子啊 Number 与 BigInt 之间进行转化回损失精度,因而建议仅在值可能大于253时使用 BigInt 类型,并且不在两种类型之间进行相互转化。