day03 ES6
高级
2.
扩展运算符
...
2.1 reset
参数
reset
参数
必须放在最后
,为了替代
arguments
,在函数形参中使用,
接受剩余参数
,
以
数组
的形式去接受
2.2
spread
参数
reset
参数的逆运算
[
展开
]
,复制,合并,伪数组转数组
数组操作
简写(推荐):
let
{
key1
,
key2
}
=
{
"name"
:
"web"
,
"age"
:
26
}
let
{
name
,
age
}
=
{
"name"
:
"web"
,
"age"
:
26
}
完整:
let
{
key1
:变量
1
,
key2
:变量
2
}
=
{
"name"
:
"web"
,
"age"
:
26
}
//1.
解构失败
let
{
a
,
sex
}
=
{
"a"
:
"Web"
,
"age"
:
20
};
console
.
log
(
a
,
sex
);
//Web undefined
//2.
设置默认值
let
{
a
,
sex
=
"
男
"
}
=
{
"a"
:
"Web"
,
"age"
:
20
};
console
.
log
(
a
,
sex
);
//Web undefined
//1. reset
参数:
...
参数名,在函数形参中使用,接受剩余参数
,
以数组的形式去接受
function
fun1
(
that
,
...
args
){
console
.
log
(
args
);
}
fun1
(
1
,
2
,
3
,
4
,
5
);
//[2, 3, 4, 5]
function
fun2
(
...
args
){
console
.
log
(
args
);
}
fun2
(
1
,
2
,
3
);
//[1,2,3]
//Rest parameter must be last formal parameter reset
参数必须放在最后,为了替代
arguments
function
fun2
(
...
args
,
t
){
console
.
log
(
args
);
}
fun2
(
1
,
2
,
3
);
//spread
参数:将数据
(
数组,对象
)
展开成参数序列
//1.
数组展开
let
arr
=
[
1
,
5
,
9
,
3
,
6
];
// console.log(Math.max(1, 5, 9, 3, 6));
console
.
log
(
Math
.
max
(
...
arr
));
//1, 5, 9, 3, 6
展开为参数序列
//2.
数组的浅拷贝
let
arr1
=
[
1
,
2
,
3
,[
"A"
]];
let
arr2
=
[
...
arr1
];
console
.
log
(
arr2
);
//[1,2,3,["A"]]
//
浅拷贝,如果数组中没有其他的引用数据类型,用于拷贝就很方便
arr2
[
3
].
push
(
"B"
);
console
.
log
(
arr1
);
//[1,2,3,["A","B"]]
//3.
伪数组转数组
let
oLis
=
document
.
getElementsByTagName
(
"li"
);
//[oLi1,oLi2,oLi3]
let
oLisArr
=
[
...
oLis
];
console
.
log
(
oLisArr
);
//[li, li, li, li, li]
//4.
组合数组
let
arr3
=
[
1
,
2
];
let
arr4
=
[
"a"
,
"b"
];
let
arr5
=
[
...
arr3
,
...
arr4
];
console
.
log
(
arr5
);
//[1, 2, "a", "b"]
对象操作
//5.
展开对象
(
拷贝的也是浅拷贝
n)
let
obj1
=
{
"name"
:
"web"
,
"age"
:
18
,
"detail"
:{
"height"
:
18
}
}
let
obj2
=
{
...
obj1
};
// "name":"web", "age":18
console
.
log
(
obj2
);
//
练习
2
:有已知以下某公司员工薪金信息,把每一位员工的
salary
薪金信息 加
2000
,并返回新数组,注意:不
影响原数组
let
persons
=
[
{
username
:
'
张飞
'
,
sex
:
'
男
'
,
salary
:
50000
},
{
username
:
'
关羽
'
,
sex
:
'
男
'
,
salary
:
60000
}
]
var
p
=
persons
.
map
(
function
(
value
,
index
){
//value = {}
return
{
...
value
,
salary
:
value
.
salary
+
2000
}
3.
函数扩展
--
箭头函数
函数类型:普通函数,事件处理函数,构造函数,表达式函数,匿名函数,回调函数,闭包函数,递归函数,
防抖,节流
函数相关:
this
,参数,返回值,作用域,作用域链,变量提升
(
预解析
)
箭头函数:减少代码量
let f = a => a*a,
作为回调函数使用的频率最高
setTimeout(()=>{})
3.1
箭头函数基础用法
语法:
实例:
3.2
箭头函数参数
多个参数
一个参数
});
console
.
log
(
p
);
普通函数声明:
function
函数名
(){
函数体
}
表达式声明方式声明箭头函数
let
函数名
=
()
=>
{
函数体
}
//1.
声明箭头函数
let
fun1
=
()
=>
{
console
.
log
(
"
箭头函数
"
);
}
fun1
();
//2.
一般作为回调函数使用
setTimeout
(()
=>
{
console
.
log
(
"
再等
4
天就放中秋节假了
"
);
},
1000
);
//3.
当箭头函数的代码只有一行的时候,可以省略
{}
(建议写上)
let
fun2
=
()
=>
console
.
log
(
100
*
100
);
fun2
();
//1.
多个参数
,
多个参数之间用逗号隔开
let
fun1
=
(
a
,
b
)
=>
{
console
.
log
(
a
+
b
);
}
fun1
(
100
,
200
);
//300
参数个数不确定
函数参数默认值
3.3
箭头函数返回值
箭头函数和普通的函数的返回值特性是一样的 【一次只能返回一个,函数只要遇到
return
函数就结束执行】
注意
//2.
一个参数
,
如果参数只有一个,可以省略小括号
// let fun2 = (c) => console.log(c);
let
fun2
=
c
=>
console
.
log
(
c
);
fun2
(
100
);
//3.
参数个数不确定 箭头函数中没有
arguments
,需要使用
reset
参数
let
fun3
=
(
...
args
)
=>
{
// console.log(arguments); arguments is not defined
箭头函数中没有
arguments
console
.
log
(
args
);
//[1, 2, 3, 4, 5]
}
fun3
(
1
,
2
,
3
,
4
,
5
);
//4.
参数默认值
(
所有函数都有的
)
function
fun4
(
n
=
6
){
if
(
n
<=
1
)
return
1
;
return
n
*
fun4
(
n
-
1
);
}
console
.
log
(
fun4
());
//
使用默认
,
值严格等于
undefined
有效
console
.
log
(
fun4
(
4
));
let
fun5
=
(
n
=
6
)
=>
{
if
(
n
<=
1
)
return
1
;
return
n
*
fun4
(
n
-
1
);
}
console
.
log
(
fun5
());
//1.
箭头函数中只有一行代码,并且这行代码是
return
,可以省略
return
和
{}
let
pow
=
(
n
)
=>
{
return
n
*
n
;
}
//
简写
let
pow1
=
n
=>
n
*
n
;
let
money
=
pow1
(
10000
);
console
.
log
(
money
);
//100000000
//2.
注意:如果返回的是对象,省略了大括号报错,在外面加
()
,提升优先级
let
fun1
=
()
=>
({
"name"
:
"lj"
,
"age"
:
"30"
})
3.4
箭头函数注意事项
箭头函数不能做为构造函数,箭头函数不建议作为对象的方法
箭头函数不能做为构造函数
箭头函数不建议作为对象的方法
因为对象中使用箭头函数,
this
会指向
window
,一般情况下我们都希望
this
指当前对象,所有不建议使用
3.5
箭头函数中的
this
this
在函数中使用,指向调用函数的对象
在普通函数中指
window function sum(){ this }
事件处理函数中指触发事件的对象
对象方法中的
this
指当前对象
构造函数中
this
指实例对象
箭头函数中没有
this
,箭头函数中的
this
取决于他所处的上层的环境(作用域)
//
箭头函数不作为构造函数,没有
constructor
let
Person
=
()
=>
{
this
.
name
=
"fd"
}
var
p
=
new
Person
();
console
.
log
(
p
);
//Person is not a constructor
//1.5
对象的方法
,
只有函数的
{}
才是环境(作用域)
let
obj
=
{
"name"
:
"web"
,
"eat"
:()
=>
{
console
.
log
(
this
)},
//window
skill
(){
console
.
log
(
this
.
name
+
"
能吃饭
"
);}
}
obj
.
skill
();
obj
.
eat
();
//1.
取决于上层环境
//1.1
全局
---
》
window
let
fun1
=
()
=>
{
console
.
log
(
this
,
"fun1"
);
}
fun1
();
//Window "fun1"
let
oBtn
=
document
.
getElementsByTagName
(
"button"
)[
0
];
//1.2 window
oBtn
.
onclick
=
()
=>
{
console
.
log
(
this
,
"oBtns"
);
//window
}
3.6
箭头函数实操
4.class
类
//1.3
在事件处理函数内,指事件处理函数
oBtn
.
onclick
=
function
(){
let
fun2
=
()
=>
{
console
.
log
(
this
);
// oBtn
}
fun2
();
}
//1.4
在构造函数内,指实例对象
function
Student
(){
this
.
name
=
"fd"
;
let
fun3
=
()
=>
{
console
.
log
(
this
);
}
fun3
();
//Student {name: "fd"}
return
fun3
;
}
let
s
=
new
Student
();
//s = fun3
s
();
//Student {name: "fd"}
在那声明的
this
就指向谁,指向所处的上层环境
//1.5
对象的方法
,
只有函数的
{}
才是环境(作用域)
let
obj
=
{
"name"
:
"web"
,
"eat"
:()
=>
{
console
.
log
(
this
)},
//window
skill
(){
console
.
log
(
this
.
name
+
"
能吃饭
"
);}
}
obj
.
skill
();
obj
.
eat
();
//
需求:
let
obj
=
{
person
:[
3200
,
6000
,
10000
,
15000
,
20000
],
num
:
3000
,
//
添加一个涨薪的方法,调用这个方法就可以返回涨薪后的工资
zx
(){
let
p
=
this
.
person
.
map
((
value
)
=>
{
return
value
+
this
.
num
;
});
console
.
log
(
p
);
}
}
obj
.
zx
();
4.1
概念
面向对象是一种以对象为中心的编程思想。面向对象是相对于面向过程来讲的,面向对象把相关的数据和方法组织为
一个整体来看待,从更高的层次来进行系统建模。
PHP/JAVA/Python/.... JS
都可以使用面向对象思想编写功能。
面向过程
面向过程思想强调的是步骤,当碰见问题时,思考的是
“
我该怎么做
”
,分析出解决问题所需要的步骤,一步步的去实
现。 例如:想吃蛋炒饭,首先想到的是我要如何做,包括哪些步骤。比如:起锅烧油,加入鸡蛋,加入米饭,加入
调料,翻炒,装盘等。
面向对象
面向对象思想强调的是对象(是一个整体),当碰见问题时,思考的是
“
我该让谁来做
”
。这个
“
谁
”
其实就是对象。找
合适的对象做合适的事情。而对象如何去做
(
采用什么样的步骤
)
我们就不关心了,最终把问题解决掉就可以了。
例如:还是想吃蛋炒饭,首先想到的是让谁来帮我做蛋炒饭,比如找厨师来帮我做蛋炒饭。具体厨师如何去做这个蛋
炒饭,做饭的步骤是怎么样的我们并不关心。只要最终把蛋炒饭做好就可以了。
不同的对象有不同的功能( 对于你这个来说:去下单、吃 ),由属性和方法
4.2
类和对象的关系
现实中先有对象,根据不同的对象有着相似的特点(归为一类)
程序中(先有类,使用类实例化对象),之前都是使用构造函数创建对象
es5
的构造函数有一些问题:方法必须原型上、使用
function
创建对象对于 其它语言的工程师觉得很另类 。
4.3 class
创建对象
基础操作
完整语法
//
基础语法:
class
类名
{
属性
=
值
}
class
Person
{
name
=
"
薛宗森
"
;
age
=
28
}
//
创建对象
var
p1
=
new
Person
;
//
()可以省略
console
.
log
(
p1
);
//Person {name: "
薛宗森
", age: 28}
//
完整语法:
class
Student
{
//
构造函数
constructor
(
name
,
age
){
//
构造函数
--
构造器,实例化对象
this
.
name
=
name
;
this
.
age
=
age
;
this
.
skill
=
function
(){
4.4
静态属性和静态方法
实例属性和实例方法。实例(对象、私有的),之前所用的属性和方法都属于对象的。
静态属性和方法:是公共的( 是属于类的、是属于函数的 ),不属于对象,所以对象访问不到。
语法
实例
4.5
继承
Class
可以通过
extends
关键字实现继承,这比
ES5
的通过修改原型链实现继承,要清晰和方便很多。
面向对象继承
console
.
log
(
"sleep"
);
}
}
//
原型上添加方法
,
自动加入到原型上
study
(){
console
.
log
(
"
好好学习,天天睡觉
"
);
}
}
let
s1
=
new
Student
(
"
田泽宇
"
,
22
);
console
.
log
(
s1
);
class
类名
{
static
属性名
=
属性值
static
方法()
{}
}
class
Person
{
//
添加静态属性
static
A
=
"
我是一个人
"
;
//
添加静态方法
static fun
(){
console
.
log
(
"
我是一个静态方法
"
);
}
}
console
.
log
(
Person
.
A
);
//
我是一个人
Person
.
fun
();
//
我是一个静态方法
let
p
=
new
Person
();
console
.
log
(
p
.
A
);
//undefined
实例对象是访问不了的,静态属性和方法属于类
//1.
声明父类
class
Student
{
name
=
"
中公学生
"
;
age
=
18
;
类不用
constructor,
用这种继承方式没有问题,但是不能传参,不常用
super
用法
4.6
面向对象的应用场景
对面向对象不要有负担,你只要懂语法即可。我们更多提使用面向对象思想封装的框架去写业务,而不是用面向对象
思想封装框架。
4.6.1
封装工具原理
代码案例:
}
//2.
声明子类: 继承:
class
子类
extends
父类
{}
class
SmallStudent
extends
Student
{
height
=
140
;
}
//3.
实例化一个子类
let
ss1
=
new
SmallStudent
;
console
.
log
(
ss1
);
//SmallStudent {name: "
中公学生
", age: 18, height: 140}
//
注意:类不用
constructor,
用这种继承方式没有问题
//1.
声明父类
class
Student
{
constructor
(
name
,
age
){
//
构造器
this
.
name
=
name
;
this
.
age
=
age
;
}
toString
(){
//
原型上方法
console
.
log
(
this
.
name
+
"
是中公的学生
"
);
}
}
//2.
声明子类: 继承:
class
子类
extends
父类
{}
class
SmallStudent
extends
Student
{
constructor
(
name
,
age
){
//console.log(this)
;
//
报错
//
第一行代码调用
super,
调用父类的构造函数,用于继承的子类没有
this
super
(
name
,
age
);
console
.
log
(
this
);
//
调用父类构造函数,继承
this
this
.
hobby
=
"
打架
"
;
}
}
let
ss1
=
new
SmallStudent
(
"lj"
,
18
);
console
.
log
(
ss1
);
Math
、
Date
、
String
、
Array
...
..
5.iterator
迭代器
了解即可。遍历( 循环、迭代 )
5.1
简介
Iterator
是一种接口机制,
为各种不同的数据结构提供统一的访问(循环)机制
,
遍历器
,
因为现在有
Array / Object /
Set / Map / String / NodeList / HTMLCollection / Arguments
等 结构
,
所以
ES6
加入了
Iterator
遍历器
,
只要拥有这
个
Iterator
遍历器
,
就都可以使用
for...of
进行遍历
for while for.in forEach
。
ES6
觉得提供的遍历方式太混乱
5.2
作用
为各种数据结构,提供一个统一的、简便的访问接口
使得数据结构的成员能够按某种次序排列
ES6
创造了一种新的遍历命令
for...of
循环,
Iterator
接口主要供
for...of
使用
class Js
{
constructor
(){
this
.
version
=
'ES202106'
}
Math
(){
return
{
ceil
(){
//
},
floor
(){
}
}
}
Array
(){
return
{
push
(){
},
pop
(){
}
}
}
}
//1.
实例化
js
let
t
=
new
Js
()
console
.
log
(
t
);
//2.
我想使用
Array
上的方法
//
先实例
array
let
arr
=
t
.
Array
()
console
.
log
(
arr
);
Iterator
是一个抽象的概念
,
具体的实现
for...of / Symbol.iterator
只要可遍历的数据结构的原型上有
Symbol.iterator
属性,则此数据就可以使用
for...of
进行遍历。唯独
Object
没
有。
5.2 for-of
作用:遍历数据
语法:
for(let values of
遍历数据
)
原生数据类型具体
iterator
接口的数据有:
Array/String/Map/Set/NodeList/ HTMLCollection/ Arguments
5.3 Iterator
在使用
for...of
的时候。如果数据原型上有
Symbol.iterator
此属性,那么会自动创建指针对象然后一步一步往移
动。直到看见
true
终止循环。
//1.
遍历数组
let
arr
=
[
"a"
,
"b"
,
"c"
,
"d"
];
//for(let value of
遍历对象
)
for
(
let
value
of
arr
){
console
.
log
(
value
);
//a,b,c,d
}
//2.
遍历字符串
let
str
=
"webhahahahah"
;
for
(
let
s
of
str
){
console
.
log
(
s
);
}
//3.
遍历对象
let
obj
=
{
"name"
:
"txf"
,
"age"
:
18
,
"height"
:
165
,
"weight"
:
110
}
for
(
let
attr
of
obj
){
console
.
log
(
attr
);
//obj is not iterable
}
5.4
给对象部署
let
arr
=
[
"A"
,
"B"
,
"C"
];
console
.
log
(
arr
);
//Symbol.iterator
:是一个函数,调用这个函数会返回一个指针对象
let
ite
=
arr
[
Symbol
.
iterator
]();
//
指针对象中有一个
next
方法,每调用一次
next
会返回一个值
{value
:当前值,
done:tue/false
是否到达了
末尾
}
console
.
log
(
ite
.
next
());
//{value:A,done:false}
console
.
log
(
ite
.
next
());
//{value:B,done:false}
console
.
log
(
ite
.
next
());
//{value:C,done:false}
console
.
log
(
ite
.
next
());
//{value:undefind,done:true}
let
obj
=
{
"name"
:
"txf"
,
"age"
:
18
,
"height"
:
165
,
"weight"
:
110
}
obj
[
Symbol
.
iterator
]
=
function
(){
//
部署一个
Symbol.iterator
let
datas
=
Object
.
values
(
obj
);
// ["txf", 18, 165, 110]
let
index
=
0
;
return
{
//
返回一个对象,里面包含
next
next
:
function
(){
//
调用
next
返回一个对象,
{value:
值
,done:true};
if
(
index
==
datas
.
length
){
return
{
value
:
datas
[
index
++
],
done
:
true
};
}
else
{
return
{
value
:
datas
[
index
++
],
done
:
false
};
}
}
}
}
let
ite
=
obj
[
Symbol
.
iterator
]();
console
.
log
(
ite
.
next
());
console
.
log
(
ite
.
next
());
console
.
log
(
ite
.
next
());
console
.
log
(
ite
.
next
());
console
.
log
(
ite
.
next
());
for
(
var
attr
of
obj
){
console
.
log
(
attr
);
}