前言
😀let和const命令
一、特点
- let、const声明变量,没有变量提升
- 块级作用域
- 不能重复声明
- let声明变量,const声明常量
- const声明的对象,对象中的属性值可以修改
const person = {
name: '小马哥'
}
person.name = 'alex'
二、作用
- var 声明变量提升经典案例
var arr = [];
var i;
for (i = 0; i< 10; i++) {
arr[i] = function() {
return i;
}
}
console.log(arr[5]()); // 结果10
const arr = [];
for (let i = 0; i < 10; i++) {
arr[i] = function() {
return i;
}
}
console.log(arr[5]()); // 结果5
- let、const不污染全局变量
let RegExp = 10;
console.log(RegExp);
console.log(window.RegExp);
三、用法建议
在默认情况下用const,而只有在你知道变量值需要被修改的情况下使用let
😁 模板字符串
使用tab键上面的反引号``,插入变量时使用${变量名}
let id = 1,
name = '小马哥';
let htmlStr = `
<ul>
<li>
<p id = ${id}>${name}</p>
</li>
</ul>
`;
😂 函数
一、带参数默认值的函数
function add(a = 10, b = 20) {
return a + b;
}
console.log(add());
二、默认的表达式也可以是一个函数
function add(a, b = getVal(5)) {
return a + b;
}
function getVal(val) {
return val + 5;
}
console.log(add(10)); // 结果20
三、剩余参数:由三个点...和一个紧跟着的具名参数指定 ...keys(随便起)
// es5例子:
function pick(obj) {
let result = Object.create(null);
for(let i = 1; i < arguments.length; i++) {
result[arguments[i]] = obj[arguments[i]];
}
return result;
}
let book = {
title: 'es6的教程',
author: '小马哥',
year: 2019
}
let bookData = pick(book, 'year', 'author');
console.log(bookData);
// es6例子:
function pick(obj, ...keys) {
// ...keys 解决了arguments(伪数组)的问题,对象参数个数的不确定性
console.log(keys); // 数组结果:["year", "author"]
let result = Object.create(null); // 创建空的对象
for (let i = 0; i < keys.length; i++) {
result[keys[i]] = obj[keys[i]];
}
return result;
}
let book = {
title: 'es6的教程',
author: '小马哥',
year: 2019
}
let bookData = pick(book, 'year', 'author');
console.log(bookData);
// 另一个例子,结果是数组的话可以用es6的方法很方便的遍历出来
function checkArgs(...args) {
console.log(args); // 数组
console.log(arguments); // 伪数组
}
checkArgs('a','b','c')
四、扩展运算符...
剩余运算符:把多个独立的合并到一个数组中
扩展运算符:将一个数组分割,并将各个项作为分离的参数传给函数
案例,处理数组中最大值
const maxNum = Math.max(20, 30);
console.log(maxNum);
// es5处理方法
const arr = [10, 20, 50, 30, 100, 40];
console.log(Math.max.apply(null, arr));
// es6 扩展运算符用法
const arr = [10, 20, 50, 30, 100, 40];
console.log(Max.max(...arr));
五、箭头函数
使用=>来定义
function(){}等价于()=>{}
// es5写法
let add = function(a, b) {
return a + b;
}
console.log(add(10, 20));
// es6写法
let add = (a, b) => {
return a + b;
}
console.log(add(10, 20));
1.省略写法
let add = val => { // val 表示形参
return val;
}
// 省略如下
let add = val => val;
// 如果函数体内存在方法或者表达式
let add = val => {
return val + 5;
}
// 省略如下
let add = val => (val + 5);
console.log(add(10));
// 如果有多个参数
let add = (val1, val2) => (val1 + val2)
console.log(add(10, 20));
// 如果返回的是个对象
let getObj = id => ({
id: id,
name: "小马哥"
});
let obj = getObj(1);
console.log(obj)
2.无参数写法
let fn = ()=> {
}
3. 闭包函数
闭包函数es5写法
let fn = (function(){
return function() {
console.log('hello es6');
}
})(); // fn后边加(),表示运行,得到的是一个函数
fn(); // fn得到的是一个函数,再加()表示运行得到的这个函数
闭包函数es6箭头函数写法
let fn = (()=>{
return ()=>{
console.log('hello es6 2');
}
})();
fn();
4. this绑定
es5中this指向:取决于调用该函数的上下文对象
let PageHandle = {
id: 123,
init: function() {
document.addEventListener('click', function(event){
// 这儿的this发生了改变,指向了定义这个函数的上下文document,所以会报错,这么做行不通
this.doSomeThings(event.type);
}, false)
},
doSomeThings:function(type){
console.log(`事件类型${type},当前id:${this.id}`)
}
}
PageHandle.init();
es5中指向绑定方法bind()解决上述问题方法
let PageHandle = {
id: 123,
init: function() {
document.addEventListener('click', function(event){
this.doSomeThings(event.type);
}.bind(this), false) // 通过bind解决this指向问题
},
doSomeThings:function(type){
console.log(`事件类型${type},当前id:${this.id}`)
}
}
PageHandle.init();
es6解决方法
- 箭头函数没有明确的this指向,箭头函数this指向他的父级,没有父级则默认指向window
- 箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this。
- 对象的{}是不产生作用域
let PageHandle = {
id: 123,
init: function() {
// 箭头函数没有this指向,箭头函数内部this值只能通过查找作用域链来确定
document.addEventListener('click', (event)=>{
this.doSomeThings(event.type);
}, false)
},
doSomeThings:function(type){
console.log(`事件类型${type},当前id:${this.id}`)
}
}
PageHandle.init();
5. 箭头函数使用注意事项
- 使用箭头函数,函数内部没有
arguments
let getVal = (a, b) => {
console.log(arguments); // 报错
return a + b;
}
console.log(getVal(1, 3));
- 箭头函数不能使用
new关键字来实例化对象
function 函数也是一个对象,但是箭头函数不是一个对象,它其实是一个语法糖
let Person = ()=>{
};
let p = new Person(); // 报错
六、this指向总结
在JavaScript中,
this的值是在运行时基于函数的调用方式动态绑定的。简单来说,this指向的是执行当前代码的对象。
1. 在对象方法中使用this
const obj = {
prop: 10,
getPropValue: function() {
return this.prop;
}
};
console.log(obj.getPropValue()); // 输出:10
在这个例子中,this指向的是obj对象
2. 在构造函数中使用this
function MyClass(prop) {
this.prop = prop;
}
const myInstance = new MyClass(10);
console.log(myInstance.prop); // 输出:10
在构造函数中,this指向的是新创建的对象实例
3. 在事件监听函数中使用this
<button id="myButton">Click me</button>
<script>
document.getElementById('myButton').addEventListener('click', function() {
console.log(this === document.getElementById('myButton')); // 输出:true
});
</script>
在事件监听函数中,this指向的是触发事件的DOM元素
4. 在箭头函数中使用this
const obj = {
prop: 10,
getPropValue: () => {
return this.prop;
}
};
console.log(obj.getPropValue()); // 输出:undefined 或者 window.prop 的值
在箭头函数中,this的值是继承的,它不会从对象中获取,所以this.prop没有指向obj对象,而是指向了外层上下文中的this
this的值在函数执行时被确定,不会在函数被调用的时候改变,但是在箭头函数中是例外,箭头函数中的this是根据其定义时所在的上下文确定的,而不是执行时
5. 使用call、apply和bind方法可以显式地改变this的值
const obj = {
prop: 10
};
function logProp() {
console.log(this.prop);
}
logProp.call(obj); // 输出:10
在这个例子中,使用call方法将logProp函数中的this绑定到了obj对象
6. 在回调函数中使用this时要格外小心,因为this的值可能不是你预期的
const obj = {
prop: 10,
doSomething: function() {
setTimeout(function() {
console.log(this.prop); // 输出:undefined,因为这里的this不是obj
}, 100);
}
};
obj.doSomething();
为了在回调函数中使用this指向正确的对象,通常的解决方案是在外部保存this的引用,或者使用箭头函数自动绑定外层上下文的this
const obj = {
prop: 10,
doSomething: function() {
const that = this; // 在外部保存this的引用
setTimeout(function() {
console.log(that.prop); // 输出:10
}, 100);
}
};
obj.doSomething();
// 或者使用箭头函数
const obj = {
prop: 10,
doSomething: function() {
setTimeout(() => {
console.log(this.prop); // 输出:10
}, 100);
}
};
🤣 解构赋值
- 解构赋值是对赋值运算符的一种扩展,它是针对数组和对象来进行操作
- 优点:代码书写上简洁易读
一、对象解构赋值
let node = {
type: 'iden',
name: 'foo'
}
// es5写法
let type = node.type;
let name = node.name;
// es6解构赋值写法
// 这种写法叫做完全解构
let {type, name} = node;
console.log(type, name);
let obj = {
a: {
name: "张三"
},
b: [],
c: 'hello world'
}
// 这种写法叫做不完全解构
let {a} = obj;
console.log(a); //obj.a
// 别名写法
let {a:t} = obj;
console.log(t); //obj.a
// 剩余运算符写法
let {a, ...res} = obj;
console.log(res); // 返回的是包含b、c的对象,不是数组
// 默认值写法
let {a, b = 30} = {a:20}
二、数组解构赋值
let arr = [1, 2, 3];
let [a, b, c] = arr;
console.log(a, b, c);
可嵌套解构
let [a, [b], c] = [1, [2], 3];
😃 对象的扩展功能
es6直接写入变量和函数,作为对象的属性和方法
- es5写法
const name = '小马哥',
age = 20;
const person = {
name: name,
age: age,
sayName: function() {
console.log(this.name)
}
}
person.sayName();
- es6写法,属性方法同名省略
const name = '小马哥',
age = 20;
const person = {
name,
age,
sayName() {
console.log(this.name)
}
}
person.sayName();
function fn(x,y) {
return {x,y};
}
console.log(fn(10, 20)); // {x:10, y:20}
let cart = {
wheel: 4,
set(newVal) {
if(newVal < this.wheel) {
throw new Error('轮子数太少了');
}
this.wheel = newVal;
},
get() {
return this.wheel;
}
}
console.log(cart.get()); // 4
cart.set(6);
console.log(cart.get()); // 6
- 属性和方法表达式组合
const obj = {};
obj.isShow = true;
const name = 'a';
obj[name + 'bc'] = 123;
console.log(obj); // {isShow: true, abc: 123}
obj['f' + 'bc'] = function() {
console.log(this);
}
console.log(obj); // {isShow: true, abc: 123, fbc: f()}
const name = 'a';
const obj = {
isShow: true,
[name + 'bc']: 123,
['f' + name]() {
console.log(this);
}
}
- 对象的方法
is()、assign()
is()等同于===,既比较值也比较类型,但是===有一个缺陷,在比较NaN的时候返回false
console.log(NaN === Nan); // false
console.log(Object.is(NaN, NaN)); true
Object.assign(target, obj1, obj2...)用于对象的合并, 将所有的对象合并到target中 ,浅拷贝
let newObj = Object.assign({}, {a:1}, {b:2});
console.log(newObj); // {a:1, b:2}
😄 数据类型Symbol(了解)
Symbol表示独一无二的值
最大用途:用来定义对象的私有变量
let s1 = Symbol('s1');
console.log(s1); // Symbol('s1')
let obj = {
[s1]: '小马哥'
};
// obj[s1] = '小马哥';
// 如果用Symbol定义的对象中的变量,取值时一定要用[变量名]取值
console.log(obj[s1]); // '小马哥'
// 获取Symbol声明的属性名(作为对象的key)
let s = Object.getOwnPropertySymbols(obj);
console.log(s); // [Symbol(s1)]
console.log(s[0]); // Symbol(s1)
// 另一种方法,反射
let m = Reflect.ownKeys(obj);
console.log(m); // [Symbol(s1)]
😅 Map和Set
一、Set
集合,表示无重复值的有序列表
let set = new Set();
set.add(2);
set.add('4');
set.add('4');
set.add(['hello','world',3]);
// 删除元素
set.delete(2);
// 校验某个值是否在set中
console.log(set.has('4'));
// set的长度
console.log(set.size);
// 遍历,set中值即是键也是值,键值相等
set.forEach((val, key)=>{
console.log(val);
console.log(key);
})
// 将set转换成数组
let set2 = new Set([1,2,3,3,3,4]);
// 使用扩展运算符
let arr = [...set2];
console.log(arr);
// set中对象的引用无法被释放
let set3 = new Set(), obj = {};
set3.add(obj);
// 释放当前资源
obj = null;
console.log(set3); // 依然存在对象obj,无变化
//使用WeakSet
let set4 = new WeakSet(), obj = {};
set4.add(obj);
obj = null;
console.log(set4);
WeakSet
- 不能传入非对象类型的参数
- 不可迭代
- 没有forEach()方法
- 没有size属性
二、Map
Map类型是键值对有序的列表,键和值是任意类型
let map = new Map();
map.set('name', '张三');
map.set('age', 20);
console.log(map.get('name')); // 张三
map.has('name');
map.delete('name');
map.clear(); // 清空
console.log(map);
map.set(['a', [1,2,3]], 'hello');
console.log(map); // {Array(2) => "hello"}
// 直接初始化
let m = new Map([
['a', 1],
['c', 2]
]);
console.log(m); // {"a"=>1, "c"=>2}
// Map和Set差不多,也有WeakMap方法
😆 数组的扩展方法
一、数组的方法
1. from()方法
from()将伪数组转换成真正的数组,比如arguments对象就是伪数组
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
function add() {
console.log(arguments); // 伪数组,无数组方法
// es5转换
let arr = [].slice.call(arguments);
console.log(arr);
// es6写法
let arr1 = Array.from(arguments);
console.log(arr1);
}
add(1,2,3);
// 主要作用实例
let lis = document.querySelectorArr('li');
console.log(Array.from(lis)); // 转换成真数组
// 之前学过的扩展运算符...也可以将伪数组转为数组
console.log([...lis]);
// from() 还可以接受第二个参数,用来对每个元素进行处理
let liContents = Array.from(lis, ele => ele.textContent);
console.log(liContents); // ["1", "2", "3", "4"]
</script>
2. of()方法
of()将任意的数据类型,转换成数组
console.log(Array.of(3, 11, 20, [1, 2, 3], {id:1})); // [3, 11, 20, Array(3), {...}]
3. copywithin()方法
copywithin(开始替换位, 开始读取复制位, 结束读取复制位) 数组内部将指定位置的元素复制到其他位置
// 将索引3以及之后的值,从索引0的位置开始替换掉原来的值
let arr = [1,2,3,8,9,10].copywithin(0,3);
console.log(arr); // [8,9,10,8,9,10]
4. find()、findIndex()方法
find()找出第一个符合条件的数组成员
find()找出第一个符合条件的数组成员的索引
let num = [1, 2, -10, -20, 9, 2].find((n)=>{
return n < 0;
})
// 简写
// [1, 2, -10, -20, 9, 2].find(n=>n<0);
console.log(num); // -10
5. entries()、keys()、values()方法
entries()、keys()、values()返回一个遍历器,可以使用for...of循环进行遍历
entries()对键值对遍历
keys()对键名遍历
values()对键值遍历
for(let index of ['a', 'b'].keys()){
console.log(index); // 0 | 1
}
for(let ele of ['a', 'b'].values()){
console.log(ele); // a | b
}
for(let [index, value] of ['a', 'b'].entries()){
console.log(index, value); // 0 a | 1 b
}
6. includes()方法
返回一个布尔值,表示某个数组是否包含给定的值
console.log([1,2,3].includes(2)); // true
😉 迭代器Interator的用法
是一种新的遍历机制,两个核心
- 第一,迭代器是一个接口,能快捷的访问数据,通过
Symbol.iterator来创建迭代器,通过迭代器的next()方法获取迭代之后的结果 - 第二、迭代器是用于遍历数据结构的指针(数据库的游标)
// 使用迭代
const items = ['one', 'two', 'three'];
// 创建新的迭代器
const ite = items[Symbol.iterator]();
console.log(ite.next()); //{value: "one", done: false} done如果为false表示遍历继续,如果为true表示遍历完成
console.log(ite.next());
console.log(ite.next());
console.log(ite.next());
😊 生成器Generator的用法
generator函数,可以通yield关键字,将函数挂起,为了改变执行流提供了可能,同时为了做异步编程提供了方案
一、它和普通函数的区别
function后面 函数名之前有个*- 只能在函数内部使用
yield表达式,让函数挂起
// function *func(params) {}// *也可以放在这个位置
function* func() {
yield 2;
yield 3;
}
// 返回一个遍历器对象(和迭代器还不一样),可以调用next()方法
let fn = func();
console.log(fn.next()); // {value: 2, done: false}
console.log(fn.next()); // {value: 3, done: false}
console.log(fn.next()); // {value: undefined, done: true}
总结:generator函数是分段执行的,yield语句是暂停执行,而next()是恢复执行
二、用next()进行传值(抽象得很)
next的传参每次只传给上一个yield值
function* add() {
console.log('start');
// x 不是yield '2'的返回值,它是恢复当前yield继续执行的next()调用时传入的实参
let x = yield '2';
console.log('one:' + x);
let y = yield '3';
console.log('two:' + y);
return x + y;
}
const fn = add();
console.log(fn.next()); // {value: '2', done: false}
console.log(fn.next(20)); // {value: '3', done: false}
console.log(fn.next(30)); // {value: 50, done: true}
// 如果函数没有返回值,则可以手动调用return,一般不会这么用
// console.log(fn.return(100));
三、使用场景:为不具备Interator接口(数组有)的对象提供了遍历操作
function* objectEntries(obj) {
// 获取对象的所有的key,保存到数组中[name, age]
const propKeys = Object.keys(obj);
for(const propkey of propKeys) {
yield [propkey, obj[propkey]]
}
}
const obj = {
name: '小马哥',
age: 18
}
obj[Symbol.iterator] = objectEntries;
// [key, value] 相当于调用了next
for(let [key, value] of objectEntries(obj)) {
console.log(`${key}: ${value}`);
}
四、Generator的用法
1. 实现异步请求同步执行,或者解决回调地狱问题,例如ajax请求,
Generator 部署ajax操作,让异步代码同步化
function* main() {
let res = yield request('https://fress-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976');
console.log(res);
console.log('数据请求完成,可以继续操作');
}
const ite = main();
ite.next();
function request(url) {
$.ajax({
url,
method: 'get',
success(res) {
ite.next(res);
}
})
}
2. 加载页面
加载页面的业务逻辑:
① 加载loading...页面
② 请求数据并加载完成...(需要异步操作)
③ loading关闭掉
function* load() {
loadUI();
yield showData();
hideUI();
}
let itLoad = load();
itLoad.next();
function loadUI() {
console.log('加载loading...页面');
}
function showData() {
// 模拟异步请求
setTimeout(()=>{
console.log('数据加载完成');
itLoad.next();
}, 1000);
}
function hideUI() {
console.log('隐藏loading...页面');
}
// 如果依次执行三个方法,则会showData最后执行,业务逻辑行不通
😋 Promise对象
一、基本用法
相当于一个容器,保存着未来才会结束的事件(异步操作)的一个结果
各种异步操作都可以用同样的方法进行处理
特点:
① 对象的状态不受外界影响,处理异步操作三个状态(pending-进行中、Resolved/Fulfilled-成功、Rejected-失败)
② 一旦状态改变,就不会再变,任何时候都可以得到这个结果
let pro = new Promise(function(resolved, rejected) {
// 执行一步操作
let res = {
code: 200,
data: {
name: '小马哥'
}
}
// 模拟异步
setTimeout(()=>{
if(res.code === 200) {
// 返回正常结果
resolved(res.data);
} else {
res.error = "失败";
rejected(res.error);
}
}, 1000);
})
console.log(pro)
// 接受成功回调的结果,接受一个回调函数
pro.then((val)=>{
console.log(val); // res.data
},(err)=>{
console.log(val); // res.error
});
这种方式无法向Promise对象中传递参数,需要封装一下
function timeOut(ms) {
return new Promise((resolved, rejected)=>{
setTimeout(()=>{
resolved('hello promise success!!');
}, ms);
})
}
timeOut(2000).then((val)=>{
console.log(val);
})
二、使用Promise封装ajax
原生js封装ajax请求
const getJSON = function(url) {
return new Promise((resolve, reject)=>{
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = handler;
xhr.responseType = 'json'; // 返回数据类型
xhr.setRequestHeader('Accept', 'application/json'); // 请求头
xhr.send(); // 发送
function hanlder() {
console.log(this.readyState); // 这个this是xhr,readyState三个值2,3,4
if(this.readyState === 4) {
if(this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
}
}
})
}
getJSON('https://baidu.com')
.then((data) => {
}, (error) => {
conosole.log(error);
})
let axios = {
get(url, data) {
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
let query = '';
let flag = typeof data === 'object' && !Array.isArray(data)
let keys = Object.keys(data);
if (flag && keys.length > 0) {
query = '?'
keys.forEach((key) => {
query += `${key}=${data[key]}&`;
})
query = query.slice(0, query.length - 1);
}
xhr.open('get', url + query, true);
xhr.send(null)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) { // 成功完成
if (xhr.status === 200) {
resolve(xhr.responseText)
} else {
reject(xhr.status)
}
} else {
// HTTP请求还在继续...
}
}
})
},
post(url, data) {
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
let query = null;
let flag = typeof data === 'object' && !Array.isArray(data)
let keys = Object.keys(data);
if (flag && keys.length > 0) {
query = '';
keys.forEach((key) => {
query += `${key}=${data[key]}&`;
})
query = query.slice(0, query.length - 1);
}
xhr.open('post', url, true);
xhr.setRequestHeader('content-Type', 'application/x-www-form-urlencoded')
xhr.send(query)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) { // 成功完成
if (xhr.status === 200) {
resolve(xhr.responseText)
} else {
reject(xhr.status)
}
} else {
// HTTP请求还在继续...
}
}
})
}
}
axios.get('http://localhost:3000/get', { name: 1, age: 2 }).then(res => {
console.log(res);
})
axios.post('http://localhost:3000/post', { name: 1, age: 2 }).then(res => {
console.log(res);
})
三、Promise中的方法
1. then() 方法
then()第一个参数resolve回调函数,第二个参数是可选的,是reject状态回调函数then()返回的是一个新的promise实例,可以采用链式编程
getJSON(url)
.then(data => {
}).then(null, err => { // 这个then相当于第一个then返回的promise对象,null相当于resolve
});
// 等价于如下写法(常规写法)
getJSON(url)
.then(data => {
}).catch(err => {
});
2. resolve() 方法
resolve()能将现有的任何对象转换成Promise对象
let p = Promise.resolve('foo');
// 等价于
// let p = new Promise(resolve=>resolve('foo'));
p.then(data => {
console.log(data); // foo
})
3. reject()方法
4. all()方法
应用场景:一些游戏类的素材比较多,等待图片、flash、静态资源文件,都加载完成才进行页面的初始化
let promise1 = new Promise((resolve, reject)=>{});
let promise2 = new Promise((resolve, reject)=>{});
let promise3 = new Promise((resolve, reject)=>{});
let p4 = Promise.all([promise1, promise2, promise3]);
p4.then(()=>{
// 三个都成功 才成功
}).catch(err=>{
// 如果有一个失败 则失败,返回第一个失败状态的值
})
5. race方法
给某个异步请求设置超时时间,并且在超时后执行相应的操作
function requestImg(imgSrc) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = function() {
resolve(img);
}
img.src = imgSrc;
})
}
function timeout() {
return new Promise((resolve, reject) => {
setTimeout(()=>{
reject(new Error('图片请求超时'));
}, 3000)
})
}
Promise.race([requestImg('images/2.png'), timeout()]).then(data => {
console.log(data);
document.body.appendChild(data);
}).catch(err => {
console.log(err);
});
6. done()、finally()方法
😎 async的用法
作用:使得异步操作更加方便
基本操作: async它会返回一个Promise对象
async是Generator的一个语法糖
async function f() {
// return await 'hello async'; // 会自动将返回结果转为Promise对象
let s = await 'hello world'; // 这儿模拟相当于一个异步请求,等待返回结果
let data = await s.split(''); // 这儿模拟的另一个异步请求,等待返回结果
return data;
}
// 如果async函数中有多个await,那么then函数会等待所有的await指令,运
// 行完的结果才去执行
f().then(v=>console.log(v)).catch(e=>console.log(e));
async function f2() {
// throw new Error('出错啦');
try {
} catch(error) {
}
return await Promise.resolve('hello');
}
f2().then(v=>console.log(v)).catch(e=>console.log(e));
// 需求: 想获取天气now的数据
async function getNowWeather(url) {
// 发送 ajax 获取实况天气
let res = await getJSON(url);
console.log(res);
// 获取HeWeather6的数据 获取未来3~7天的天气状况
let arr = await res.HeWeather6; // 这儿的await是为了让then得到所有执行后的返回的结果
return arr[0].now;
}
getNowWeather('https://fress-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976')
.then(now => {
console.log(now);
})
😍 class类
一、创建方式
- es5 创建类的方式
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function() {
return this.name;
}
let p1 = new Person('小马哥', 28);
console.log(p1);
- es6 创建类的方式
class Person {
// 原型方法,实例化的时候会立即被调用
constuctor(name, age) {
this.name = name;
this.age = age;
}
// 方法
sayName() {
return this.name;
}
sayAge() {
return this.age;
}
// 另一种添加方法的方式
/**
Object.assign(Person.prototype, {
sayName() {
return this.name;
},
sayAge() {
return this.age;
}
})
**/
}
let p1 = Person('小马哥', 28);
console.log(p1);
二、类的继承
使用关键字extends
// 父类
class Animal {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayName() {
return this.name;
}
sayAge() {
return this.age;
}
}
// 子类
class Dog extends Animal {
constructor(name, age, color) {
super(name, age); // 相当于Animal.call(this, name, age);
this.color = color;
}
// 子类自己的方法
sayColor() {
return `${this.name}是${this.age}岁了,它的颜色是${this.color}`;
}
// 重写父类方法
sayName() {
return this.name + super.sayAge() + this.color;
}
}
let d1 = new Dog('小黄', 28, 'red');
console.log(d1.sayColor);
console.log(d1.sayName);
😘 module模块的使用
es6模块功能主要由两个命令构成:export和import
export用于规定模块的对外接口
import用于引入其他模块提供的功能
一个模块就是一个独立的文件
注意:一定要用服务器才可以运行导入的模块,静态文件访问不到模块
一、 基本使用方法
modules/index.js
export const name = '张三';
export const age = 18;
// 抛出函数的时候只能这种形式,不能定义函数后另起一行export sayName;
// 要抛出一个函数作为一个整体,一定是在函数前面加export关键字
// 不过可以用对象把函数包裹起来抛出,export {sayName};属性也可以这样
export function sayName() {
return 'my name is ' + name;
}
index.html引入模块,script标签类型必须是module
<script type='module'>
// 变量用 {} 是相当于解构赋值,还不算是解构
import {name, age, sayName} from './modules/index.js';
console.log(name, age, sayName());
</script>
二、命名default
default 一个文件中只能用一次,在外部文件引入的时候可以随便取别名,对应的就是这个命名
index.html
<script type='module'>
// cname 是 default对象
// 一般使用这种方式
/**
import cname, {name, age, sayName} from './modules/index.js';
console.log(cname, name, age, sayName());
**/
// * 全部导入
import * as f from './modules/index.js';
console.log(f);
// default对象使用方法
console.log(f.default)
// 导出类可以直接
// import cname, {name, age, sayName} from './modules/index.js';
const p = new Person();
p.sayAge;
</script>
modules/index.js
const name = '张三';
const age = 18;
function sayName() {
return 'my name is ' + name;
}
export {
name, age, sayName
}
// 对象
/*
const obj = {
foo: 'foo'
}
export default obj;
*/
// 类
class Person{
constructor() {
}
sayAge() {
console.log('16');
}
}
export default Person;