概念
特点:
1、function 与函数名之间有一个星号(*)
2、内部用yield表达式来定义不同的状态
例如:
function* generatorExample(){
let result = yield 'hello'; // 状态值为hello
yield 'generator'; // 状态值为generator
}
3、generator函数返回的是指针对象(接11章节里iterator),而不会执行函数内部逻辑
4、调用next方法函数内部逻辑开始执行,遇到yield表达式停止,返回{value: yield后的表达式结果/undefined, done: false/true}
5、再次调用next方法会从上一次停止时的yield处开始,直到最后
6、yield语句返回结果通常为undefined, 当调用next方法时传参内容会作为启动时yield语句的返回值。
<script type="text/javascript">
//测试
function* generatorTest() {
console.log('函数开始执行');
yield 'hello';
console.log('函数暂停后再次启动');
let result=yield 'generator';
console.log(result);
}
// 生成遍历器对象
let Gt = generatorTest();//返回的是指针对象
// 执行函数,遇到yield后即暂停
console.log(Gt); // 遍历器对象
let result = Gt.next(); // 函数执行,遇到yield暂停
console.log(result); // {value: "hello", done: false}
result = Gt.next(); // 函数再次启动
console.log(result); // {value: 'generator', done: false}
result = Gt.next('这里可以传值');//yield的语句默认返回undefined,如果不传值默认undefined
console.log(result); // {value: undefined, done: true}表示函数内部状态已经遍历完毕
// 对象的symbol.iterator属性 指向遍历器对象
let obj={usernameL:'xuefeng',age:12};
obj[Symbol.iterator]=function* myTest() {
yield 1,
yield 2,
yield 3
};
for (let i of obj) {
console.log(i);
}//输出 1 2 3
</script>
第一步先开服务器 cmd中
测试服务器是否打开
<script type="text/javascript">
// 案例练习
/*
* 需求:
* 1、发送ajax请求获取新闻内容
* 2、新闻内容获取成功后再次发送请求,获取对应的新闻评论内容
* 3、新闻内容获取失败则不需要再次发送请求。
*
* */
function getNews(url) {
$.get(url,function (data) {
console.log(data);
let url= `http://localhost:3000`+data.commentsUrl;
SX.next(url);//此处传入url会作为 yield getNews(url);中的url
//回调函数中的next函数被调用,就说明前面一定执行成功
})
}
function* sendXML() {
let url=yield getNews('http://localhost:3000/news?id=3');
yield getNews(url);
}
//获取遍历器对象
let SX=sendXML();
SX.next();//先调用这个next方法 此时指针下移
script>
async函数(源自ES2017)
概念: 真正意义上去解决异步回调的问题,同步流程表达异步操作
本质: Generator的语法糖
语法:
async function foo(){
await 异步操作;
await 异步操作;
}
特点:
*
,await取代Generator的yield<script type="text/javascript">
//async的基本使用
async function foo() {
return new Promise( resolve => {
// setTimeout(function () {
// resolve();
// },2000)
setTimeout(resolve(),2000);
})
}
async function test() {
console.log('开始执行',new Date().toTimeString());
await foo();
console.log('执行完毕',new Date().toTimeString());
}
test();
//async里await返回值
async function asyncPrint() {
let result=await Promise.resolve('promise');
console.log(result);
result=await Promise.reject('失败了...');
console.log(result);
}
asyncPrint();//报错 Uncaught (in promise) 失败了...
script>
<script type="text/javascript">
// 案例练习
/*
* 需求:
* 1、发送ajax请求获取新闻内容
* 2、新闻内容获取成功后再次发送请求,获取对应的新闻评论内容
* 3、新闻内容获取失败则不需要再次发送请求。
*
* */
async function getNews(url) {
return new Promise((resolve, reject) => {
$.ajax({
method: 'GET',
url,//同名的属性可以省略不写
success: data => resolve(data),//ES6箭头函数
/*error: function (error) {//正常写法
reject();
}*/
error: error =>resolve(false)//当出错的时候 返回false
})
})
}
async function sendXML() {
let result=await getNews('http://localhost:3000/news?id=2')
console.log(result);
if(!result){alert('暂时没有评论');}//出错result为false 取反就为true
result=await getNews('http://localhost:3000'+result.commentsUrl);
console.log(result);
}
sendXML();
script>
通过class定义类/实现类的继承
在类中通过constructor定义构造方法
通过new来创建类的实例
通过extends来实现类的继承
通过super调用父类的构造方法
重写从父类中继承的一般方法
<script type="text/javascript">
/*function Person(name.age) {
this.age=age;
this.name=name;
}
let person=new Person('xuefeng',12);*/
//定义一个人物的类
class Person{
//类的构造方法
constructor(name,age){
this.name=name;
this.age=age;
}
//类的一般方法
showName(){
console.log('子类实例也能调用我');
console.log(this.name,this.age);
}//这些方法都定义在原型上
}
let person=new Person('tianjinfeng',12);
person.showName();
class StarPerson extends Person{
constructor(name,age,salary){
super(name,age);//调用父类的构造方法 一定要把父类构造器的参数传过来
this.salary=salary;
}
showName() {//父类的方法重写
console.log('调用子类的方法');
console.log(this.name,this.age,this.salary);
}
}
let p1=new StarPerson('daofeng',12,12000);
console.log(p1);
p1.showName();//daofeng 12 12000
script>
includes(str) : 判断是否包含指定的字符串
startsWith(str) : 判断是否以指定字符串开头
endsWith(str) : 判断是否以指定字符串结尾
repeat(count) : 重复指定次数
<script type="text/javascript">
let str='awsl';
console.log(str.includes('a'));//true
console.log(str.startsWith('a'));//true
console.log(str.endsWith('l'));//true
console.log(str.repeat(3));//awslawslawsl
script>
二进制与八进制数值表示法: 二进制用0b, 八进制用0o
Number.isFinite(i) : 判断是否是有限大的数
Number.isNaN(i) : 判断是否是NaN
Number.isInteger(i) : 判断是否是整数
Number.parseInt(str) : 将字符串转换为对应的数值
Math.trunc(i) : 直接去除小数部分
<script type="text/javascript">
console.log(0b1010);//10
console.log(0o75);//61
console.log(Number.isFinite(Infinity));//false Infinity为无限大的书
console.log(Number.isNaN(NaN));//true
console.log(Number.isInteger(123.0));//true
console.log(Number.parseInt('a1s5d6'));//NaN
console.log(Number.parseInt('123a'));//123
console.log(Math.trunc(123.231));//123
script>
Array.from(v) : 将伪数组对象或可遍历对象转换为真数组
Array.of(v1, v2, v3) : 将一系列值转换成数组
find(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素
findIndex(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素下标
<script type="text/javascript">
let btns=document.getElementsByTagName('button');//这得到的数组就是伪数组,伪数组没有数组的一般方法
/* forEach(function (item,index) {
console.log(item);
});//报错 伪数组不能遍历*/
Array.from(btns).forEach(function (item,index) {
console.log(item);
});
let arr=Array.of(1,4,'awsl',false);
console.log(arr);//(4) [1, 4, "awsl", false]
let arr2=[4,5,8,1,9,3,7,6,5];
let result=arr2.find(function (item,index) {
return item>5;
});
console.log(result);//8
let index=arr2.findIndex(function (item,index) {
return item>5;
});
console.log(index);//2
script>
1.Object.is(v1, v2) :判断2个数据是否完全相等 以字符串形式判断
2.Object.assign(target, source1, source2…) :将源对象的属性复制到目标对象上
3.直接操作 __proto__
属性 let obj2 = {}; obj2.__proto__ = obj1;
<script type="text/javascript">
console.log(0 == -0);//true
console.log(NaN == NaN);//false NaN与任何值都不相等
console.log(Object.is(0,-0));//false 字符串0和字符串-0是不一样的
console.log(Object.is(NaN,NaN));//true 以字符串的形式来判断
let obj={};
let obj1={username: 'xuefeng',age:12};
let obj2={sex:'女'};
Object.assign(obj,obj1,obj2);
console.log(obj);//age: 12 sex: "女" username: "xuefeng"
let obj3={};
let obj4={money :12000};
obj3.__proto__=obj4;
console.log(obj3);//{}
console.log(obj3.money);//12000
script>
1.Set容器 : 无序不可重复的多个value的集合体
2.Map容器 : 无序的 key不重复的多个key-value的集合体
<script type="text/javascript">
let set=new Set(['a','w','s','l']);
console.log(set.size,set);//4 Set(4) {"a", "w", "s", "l"}
set.add(2);
console.log(set.size,set);//5 Set(5) {"a", "w", "s", "l", 2}
console.log(set.has('a'));//true
let map=new Map([ ['daofeng',12],['xuefeng',12],['tianjinfeng',12]]);
console.log(map);//Map(3) {"daofeng" => 12, "xuefeng" => 12, "tianjinfeng" => 12}
map.set(10,'dian');
script>
for(let value of target){}循环遍历
1. 遍历数组
2. 遍历Set
3. 遍历Map
4. 遍历字符串
5. 遍历伪数组
<script type="text/javascript">
let arr=[1,4,7,5,4,8];
let arr1=arr;
arr=[];
let set=new Set(arr1);//Set方法可以用来去重
for(let i of set){
arr.push(i);//向arr里添加元素
}
console.log(arr);//Array(5)
script>
1、数据类型:
2.复制数据
<script type="text/javascript">
/*
//不会影响原数据
let str='abcd';
let str2=str;
console.log(str2);//abcd
str2='';
console.log(str);
let bool1=true;
let bool2=bool1;
bool2=false;
console.log(bool1);//true
//会改变原数据
let obj={username:'xuefeng',age:12};
let obj1=obj;
console.log(obj1);
obj1.username='daofeng';
console.log(obj.username);//daofeng
//拷贝数组/对象 没有生成新的数据而是复制了一份引用
let arr=[1,4,{username:'jifeng',age:12}];
let arr2=arr;
arr2[0]='awsl';
console.log(arr,arr2);//Array(3) [ "awsl", 4, {…} ] Array(3) [ "awsl", 4, {…} ]
*/
/*
拷贝数据:
基本数据类型
拷贝后生成一份新的数据,修改拷贝以后的数据不会影响原数据
对象/数组
拷贝后不会生成新的数据,而拷贝是引用, 修改拷贝后的数据会影响原来的数据
拷贝数据的方法
1.直接赋值给一个变量 //浅拷贝
2.Object.assign() //浅拷贝
3.Array.prototype.concat() //浅拷贝
4.Array.prototype.slice() //浅拷贝
5.JSON.parse(JSON.stringify()) //深拷贝(深度拷贝),拷的数据里不能有函数
浅拷贝(对象/数组):
特点: 拷贝的引用,修改拷贝以后的数据也会影响原数据
深拷贝(对象/数组):
特点:拷贝的时候生成新数据,修改拷贝以后的数据不会影响原数据
*/
let newObj={username:'dian'};
let newObj2=Object.assign(newObj);
console.log(newObj2);//{username: "dian"}
newObj.username='feng';
console.log(newObj);//{username: "feng"}
console.log(newObj2);//{username: "feng"}
let arr=[1,3,{username:'xiang'}];
let arr2=arr.concat();//修改arr2的数据影响了原数据 所以是浅拷贝
console.log(arr2);//Array(3) [ 1, 3, { username: "lei"} ]
arr2[2].username='lei';
console.log(arr);//Array(3) [ 1, 3, { username: "lei"} ]
let arr3=arr.slice();//两个参数startIndex endIndex 修改了arr3的数据也影响了原数据 所以是浅拷贝
arr3[2].username='shijinfeng';
console.log(arr);//Array(3) [ 1, 3, { username: "shijinfeng"} ]
console.log('*********');
let arr4=JSON.parse(JSON.stringify(arr));//arr4改变没有修改原数据 所以是深拷贝
console.log(arr4);//Array(3) [ 1, 3, { username: "yingfeng"} ]
arr4[2].username='yingfeng';
console.log(arr);//Array(3) [ 1, 3, { username: "shijinfeng"} ]
script>
深度克隆的方法(此方法还有误,需要调试)
<script type="text/javascript">
/**
* 如何实现深度拷贝(克隆)
* 拷贝的数据里有对象/数组
* 拷贝的数据里不能有对象/数组,
* 即使有对象/数组可以继续遍历对象、数组拿到里面每一项值,一直拿到是基本数据类型,然后再去复制,就是深度拷贝
*/
//知识储备
/*
如何判断数据类型 arr ---> Array null==>Null
1.typeof返回的数据类型:String Number Boolean Undefined Object Function
2.Object.prototype.toString.call(obj)
3.
*/
let result='abcd';
console.log(Object.prototype.toString.call(result));//[object String]
console.log(Object.prototype.toString.call(result).slice(8,-1));//String
//for in循环 对象(的属性名) 数组(的下标)
let obj={username:'xuefeng',age:12};
for (let i in obj){
console.log(i);
}
let arr =[1,3,'awsl'];
for (let i in arr){
console.log(i);
}
//定义检测数据类型的功能函数
function checkedType(target) {
return Object.prototype.toString.call(target);
}
//实现深度克隆 --> 对象/数组
function clone(target) {
//判断拷贝的数据类型
//初始化变量result 成为最终克隆的数据
let result,targetType =checkedType(target);
if(targetType === 'Object'){
result ={};
}else if(targetType === 'Array'){
result=[];
}else{
return target;// 如果是其他数据类型不复制,直接将数据返回
}
//遍历目标数据
for(let i in target){
//获取遍历数据结构的每一项值
let value=target[i];
//判断目标结构里的每一项值是否存在对象/数组
if(checkedType(value) === 'Object'||checkedType(value) ==='Array'){
//继续遍历获取到的value值
result[i]=clone(value);
}else{//获取到的value值是基本的数据类型或者是函数
result[i]=value;
}
}
return result;
}
let arr3=[1,2,{username:'xuefeng',age:12}];
let arr4=clone(arr3);
console.log(arr4);//Array(3) [ 1, 2, { username: "xuefeng", age: 12} ]
arr4[2].username='lian';
console.log(arr3,arr4);
let obj3={username:'tianjinfeng',age:12};
let obj4=clone(obj3);
console.log(obj4);//{username: "tianjinfeng", age: 12}
obj4.username='shijinfeng';
console.log(obj3,obj4);
script>
1.指数运算符(幂): **
2.Array.prototype.includes(value) : 判断数组中是否包含指定value
<script type="text/javascript">
console.log(3 ** 3);//27
let arr=[1,4,7,59,11,'abv'];
console.log(arr.includes('a'));//false 这里判断是否对等 不是模糊匹配
script>