1.解构赋值(针对数组array,字符串String及对象object以)
结构赋值是一种特殊的语法,通过将各种结构中的元素复制到变量中达到"解构"的目的,但是数组本身没有改变
1.1解构单层数组
<script>
let arr = [1,2,3,4,5];
//获取数组中的第一个元素
let ha = arr[0];
//获取数组中的每一个元素
//将数组arr中的元素一次赋值给变量a,b,c,d,e
let [a,b,c,d,e] = arr;
console.log(a,b,c,d,e);//输出1 2 3 4 5
//取第3个值,数组中不想要的元素可以添加逗号把它丢弃
let [a1,,c1] = arr;//等于let [,,c1] = arr;
console.log(c1);//输出3
</script>
1.2解构多层次的数组
<script>
let array = [[1,2,3],[4,5,6],[7,8,9]];
//解构获取数组第3个元素的第2个元素
let [,,[,b]] = array;
console.log(b);//输出8
</script>
1.3解构字符串类型String同上
<script>
let string = 'xyz';
let [a,b,c] = string;
console.log(a,b,c);//输出x y z
[,,c] = string;
console.log(c);//输出z
</script>
1.4解构赋值对象Object
按对象中的属性名进行解构赋值,修改变量名
<script>
let obj = {
name:'张三',
age:18,
};
//按属性名进行解构
let {name,age} = obj;
console.log(name);//输出张三
//修改变量名
let {name:aaa,age:bbb} = obj;
console.log(bbb);//输出18//aaa,bbb是重新声明的变量名称
</script>
对已经存在的变量进行解构赋值
<script>
let obj = {
name:'张三',
age:18,
};
let name,age;
//{name,age} = obj;//报错,语句被解析为对代码块进行赋值,代码块不允许被赋值
({name,age} = obj);//解决办法加一个()
console.log(name,age);//输出 张三 18
</script>
默认值属性值为undefined时默认值生效
<script>
let obj = {
name:'张三',
age:18,
};
let {name,age,_sex:sex='男'} = obj;
console.log(name,age,sex);//输出 张三 18 男
let abc = {
name1:'李四',
age1:'19',
_sex1:'女',
}
let {name1,age1,_sex1:sex2='男'} = abc
console.log(name1,age1,sex2);//输出 李四 19 女//默认值被覆盖
</script>
嵌套解构赋值
<script>
let obj = {
name:'张三',
age:18,
hobby:['足球'],//hobby是数组用[],作用是定位
};
let {name,hobby:[a]} = obj;
console.log(name,a);//输出张三 足球
</script>
2.迭代器
迭代器对象是由 可迭代协议([Symbol.iterator]方法) 和 迭代器协议(next方法) 构成
迭代器是一个对象,定义一个序列,并在终止时可能附带一个返回值;
2.1枚举for-in,会无序遍历对象里面的属性(没有办法自定义循环过程)
<body>
<script>
let obj = {
name:'zhangsan',
age:19,
};
for(let index in obj){//index代表索引和属性
console.log(index,obj[index]);
//index代表所有属性名,obj[index]代表所有属性值
}
</script>
2.2可迭代协议
有一个[Symbol.iterator]方法,需要返回一个迭代器对象,具有唯一性
2.3迭代器协议
迭代器通过使用 next() 方法实现了迭代器协议的任何一个对象,该方法返回具有两个属性对象
value:迭代的值;
done:是否迭代完完成;(ture迭代完成)(false迭代没完成)
2.4迭代for-of,自定义遍历过程
<script>
let obj = {
//obj是一个迭代器对象,因为里面拥有一个next方法并且返回了一个值
name: "zhangsan",
age: 19,
count: 5,
//可迭代协议 条件1
[Symbol.iterator]: function () {
return this;//返回迭代器对象 条件2
},
//迭代器协议 条件1
next() {
if (this.count > 0) {
return { value: this.count--, done: false };//迭代器协议 条件2
}else{
return{value:0,done:true};
}
},
};
//迭代
for (let item of obj) {
console.log(item);//输出5 4 3 2 1//item拿到的是if里面value的值
}
</script>
3.生成器函数
生成器对象(generator)是由一个generator function返回的,它同时符合可迭代协议和迭代器协议
生成器函数是一种特殊类型的函数,它返回一个生成器对象,这个对象可以用来实现可迭代对象。它可以使用特殊的语法来控制生成器对象的输出,实现按需生成值序列,避免一次性生成大量的值,减少了内存的使用(都是为了构建可迭代对象,自定义迭代过程)
3.1生成器函数定义使用function*关键字,语法如下:
function* generator() {
// 函数体
}
<script>
function* generator(){
console.log('run1');
//return默认返回undefined
}
//调用生成器函数,返回生成器对象,--此时生成器函数的代码块并不执行
let g = generator();//g是一个生成器对象
console.log(g);
g.next();//调用生成器函数当中的next()方法//此时生成器函数当中的代码块开始执行
let r = g.next();
console.log(r);//输出结果如下
</script>
3.2yield关键字,暂停代码执行,并将后面的值返回
function* generateSequence() {
yield 1;
yield 2;
yield 3;
}
const generator = generateSequence();
console.log(generator.next().value); // 1
console.log(generator.next().value); // 2
console.log(generator.next().value); // 3
3.3结束迭代.return()
<script>
function* generator(){
yield 1;
yield 2;
yield 3;
}
let g = generator();
let r1 = g.next();
g.return();
let r2 = g.next();
let r3 = g.next();
console.log(r1,r2,r3);//{value: 1, done: false}
//{value: undefined, done: true}
//{value: undefined, done: true}
</script>
3.4生成器函数的应用
yield*(展开可得迭代对象)
<script>
let obj = {
name:'张三',
age:18,
sex:'男',
*[Symbol.iterator](){
yield [this.name,this.age,this.sex];//['张三', 18, '男']
//yield this.name;
//yield this.age;
//yield this.sex;简约写法
yield* [this.name,this.age,this.sex];
},
};
//迭代对象
for(const item of obj){
console.log(item);
}
</script>
内嵌式对象应用
<script>
let obj = {
hobbies:['篮球','足球','品胖球'],
*[Symbol.iterator](){
//Object.values()是Object对象中的静态方法
//返回对象自身的所有可枚举属性值的数组
yield* Object.values(this);//和下行两种写法输出结果相同
yield* [this.hobbies];
},
};
for(const item of obj){
console.log(item);
}
</script>
4.Symbol
一种基本的数据类型,Symbol()函数会返回symbol类型的值,该类型具有静态属性和静态方法。
Symbol不支持语法new Symbol();
4.1每个从Symbol返回的值都是唯一的,如有需要可以使用new Object(Symbol())
<body>
<script>
let s1 = Symbol(1);
let s2 = Symbol(1);
//let s3 = new Symbol();//报错。不允许直接实例化
console.log(s1 == s2);//false//产生一个唯一的值和其他值不等,和自身相等
//把Symbol转换成对象
let s4 = new Object(s1);
console.log(s1,typeof s1);
console.log(s4,typeof s4);
</script>
4.2全局共享的Symbol
Symbol.for()用于全局注册Symbol,存在则取值,不存在则创建
Symbol.keyFor()用于获取全局注册的Symbol的key
<script>
//键位a的Symbol值,是否存在全局注册表中,不存在则创建
let s1 = Symbol.for('a');//创建
let s2 = Symbol.for('b');
let s3 = Symbol.for('c');
console.log(s1,s2,s3);//Symbol(a) Symbol(b) Symbol(c)
//键位a的Symbol值是否存在全局注册表中,存在则取值,返回Symbol值
let s4 = Symbol.for('a');
console.log(s4 == s1);//ture
//根据Symbol 值获取key值
let k1 = Symbol.keyFor(s1);
console.log(k1);//a
</script>
4.3内置的Symbol属性应用
Symbol.iterator用于定义对象的默认遍历器
Symbol.hasInstance用于判断对象是否为某个机构赞函数的事例
Symbol.isConcatSpreadable用于判断对象是否可以展开
<script>
let arr1 = [1,2,3,4,5];
let arr2 = ['a','b','c','d','e'];
// let arr3 = arr1.concat(arr2);
// console.log(arr3);//[1, 2, 3, 4, 5, 'a', 'b', 'c', 'd', 'e']
arr2[Symbol.isConcatSpreadable] = false;//关闭展开
let arr3 = arr1.concat(arr2);
console.log(arr3);//[1, 2, 3, 4, 5, Array(5)]
</script>
Symbol.spacies用于指定对象的构造函数
Symbol.split指向一个正则表达式的索引处分割字符串的方法,这个方法通过String.prototype.split()调用。