一、剪头函数
1、第一种方法
//语法
let 函数名 = (参数) => {}
let func_name = (item) => {
return item * item;
}
2、第二种方法(参数只有一个时,可以省略括号)
//语法
let 函数名 = 参数 => {}
let func_name = item => {
return item * item;
}
3、第三种方法(函数只有一行代码时,可以省略花括号)
//语法
let 函数名 = 参数 => 参数 * 参数
const arr = [1,2,3,4,5,6,7]
const result = arr.filter(item => item % 2 ===0 )
注:filter()返回符合函数返回的值;
箭头函数适合与 this 无关的回调,定时器,数组的方法回调;
箭头函数不适合与this 有关的回调,时间回调,对象的方法;
参数默认值
函数形参可以给默认值,调用函数的时候如果传值则使用所传的值,没传值则使用默认值
let sum = (a,b,c=7) => a+b+c;
//调用,不给C传参,结果 10
sum(1,2);
//给C传参
sum(2,5,7);
解构赋值:
function sum(options){
console.log(options.host);
console.log(options.username);
console.log(options.password);
console.log(options.port);
}
//调用传参
sum({
host: 'www.baidu.com',
username: 'wayne',
password: '123456',
port: 3306
});
function sumTwo({host: '192.168.0.0',username,password,port}){
console.log(host);
console.log(username);
console.log(password);
console.log(port);
}
//调用传参
sumTwo({
host: 'www.baidu.com',
username: 'wayne',
password: '123456',
port: 3306
});
rest参数(es6新增)
//es5写法:
function data(){
console.log(arguments);//打印出来的是一个对象
}
data('wayne','del','zhang','bin');
…args必须放在最后面,因为他会把传的参数都归类到一个数组里
//es6写法:
function data(...args){
console.log(args);//打印出来的是一个数组
}
data('wayne','del','zhang','bin');
function data(a,b,...args){
console.log(args);//打印出来的是一个数组
}
data('wayne','del','zhang','bin');
…三个点可以将数组转化成逗号连接的元组
扩展运算符的应用
1、数组合并
1、常用方法concat:
let arr1 = [1,2];
let arr2 = [3,4];
let arr3 = arr1.concat(arr2);
2、扩展运算符:
let arr4 = [...arr1,...arr2];
2、克隆数组
let arr = [1,2,3,4];
let new_arr = [...arr];
3、将伪数组转成真数组
let divs = document.querySelectAll('div');
let divs_arr = [...divs];
二、symbol
symbol是唯一的,不可以用于计算,比较;symbol是独一无二的值;
//1、第一种创建方式
let name = symbol('zhang');
//2、第二种创建方式
let name = symbol.for('zhang');
使用for创建的相同值,会是相等的;
let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2 // true
JavaScript基本类型:
//记得技巧
USONB
U undefined
S string symbol
O object
N number null
B boolean
创建symbol对象属性:
let games = {
name: 'wayne',
[Symbol('say')]: function(){
console.log('添加成功!');
},
[Symbol('animate')]: function(){
console.log('燃起来吧!');
}
}
symbol值可以转化为boolear值,但是不能转化为数值;
symbol.description可以返回symbol的描述;
getOwnPropertySymbols()
方法,可以获取指定对象的所有 Symbol 属性名(只返回symbol属性);
Reflect.ownKeys()
方法可以返回所有类型的键名,包括常规键名和 Symbol 键名;
Symbol.for()
为 Symbol 值登记的名字,是全局环境的,不管有没有在全局环境运行。
三、迭代器
iterator,迭代器
const names = ['wayne','del','zhang','b']
let iterator = names[Symbol.iterator]();
//调用next()方法,指向下一个
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
四、生成器函数
创建生成器函数,就在function后面加个*;
function * names(arg){
console.log(arg);
yield 111;
console.log(arg);
yield 222;
console.log(arg);
yield 333;
}
//执行获取迭代器函数
let name = names('AAA');
console.log(name.next());
//next()方法可以传参
console.log(name.next('BBB'));
console.log(name.next('CCC'));
console.log(name.next('DDD'));
使用生成器函数解决回调地狱问题;
//我想使控制台输出1,2,3,每过一秒输出一个,老方法使用定时器嵌套
function one () {
setTimeout(() => {
console.log(111);
action.next();
}, 1000);
}
function two () {
setTimeout(() => {
console.log(222);
action.next();
}, 2000);
}
function three () {
setTimeout(() => {
console.log(333);
action.next();
}, 3000);
}
function* send () {
yield one();
yield two();
yield three();
}
let action = send();
action.next();
生成器用于异步操作:
//拿一个用户的数据
function user() {
setTimeout(() => {
let data = '用户数据';
action.next(data);
}, 1000);
}
function goods() {
setTimeout(() => {
let data = '商品数据';
action.next(data);
}, 1000);
}
function order() {
setTimeout(() => {
let data = '订单数据';
action.next(data);
}, 1000);
}
function* gen() {
let users = yield user();
console.log(users);
let good = yield goods();
console.log(good);
let orders = yield order();
console.log(orders);
}
let action = gen();
action.next();
五、promise
实例化promise对象:
// 实例化 promise 对象
const app = new Promise(function (resolve, reject) {
// 成功返回
// let data = '成功获取到数据!';
// resolve(data);
// 失败返回
let data = '获取数据失败了';
reject(data);
})
调用 promise 对象的 then 方法,then方法里面有两个函数,一个返回成功的,一个返回失败的,成功里面带的是value,失败里面带的是reason;
//调用promise对象的then方法
app.then(function (value) {
console.log(value);
}, function (reason) {
console.error(reason);
})
调用打开其他文件的内容;
const fs = require('fs');
// 实例化
const app = promise(function (resolve, reject) {
fs.readFile('./data.md', function (err, data) {
if (err) reject(err);
resolve(data);
})
})
// 调用 promise 对象的 then 方法
app.then(function (value) {
console.log(value.toString());
}, function (reason) {
console.error('读取失败');
})
最基础的请求数据方式:
// 1.创建对象
const xhr = new XMLHttpRequest();
// 2.初始化
xhr.open("GET", "https://test.api.com/v3/course/info?course_id=85");
// 3、发送请求
xhr.send();
// 4、绑定事件,处理响应结果
xhr.onreadystatechange = function () {
// 判断
if (xhr.readyState === 4) {
// 判断响应状态码 200-299
if (xhr.status >= 200 && xhr.status <= 299) {
// 成功则返回
console.log(xhr.response);
} else {
// 失败则返回
console.error(xhr.status);
}
}
}
使用promise封装Ajax:
// promise封装Ajax
const app = new Promise(function (resolve, reject) {
// 接口地址:https://api.apiopen.top/getJoke
// 1.创建对象
const xhr = new XMLHttpRequest();
// 2.初始化
xhr.open("GET", "https://test.api.com/v3/course/pageList?page_num=1");
// 3、发送请求
xhr.send();
// 4、绑定事件,处理响应结果
xhr.onreadystatechange = function () {
// 判断
if (xhr.readyState === 4) {
// 判断响应状态码 200-299
if (xhr.status >= 200 && xhr.status <= 299) {
// 成功则返回
resolve(xhr.response);
} else {
// 失败则返回
reject(xhr.status);
}
}
}
})
// 指定回调
app.then(function (value) {
console.log(value);
}, function (reason) {
console.error(reason);
})
使用promise解决回调地狱问题:
// 使用promise解决回调地狱问题
const app = new Promise((resolve, reject) => {
fs.readFile("./XXX.XX", (err, data) => {
resolve(data);
})
});
// 指定回调
app.then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./XXX.XX", (err, data) => {
resolve([value, data]);
})
})
}).then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./XXX.XX", (err, data) => {
value.push(data);
resolve(value);
})
})
})
六、Set
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
set是一个新增的构造函数,会自动去重,将重复的元素删除;
//创建set()数据结构 更多使用的是const进行创建
const names = new Set();
//也可以直接在Set()中添加数据,一般都是直接添加数组
const names = new Set(['wayne','zhang','del','bin']);
//对set()对象的操作有:.add(新增元素),.delete(删除元素),.has(检测元素),.clear(清空元素)
//添加元素
names.add('tian');
//删除元素
names.delete('tian');
//检测元素(检测数组中是否有该元素,又返回true,没有返回false)
names.has('tian');
//清空元素
names.clear();
//可以使用for……of进行遍历
for(let v of names){
console.log(v);
}
数组去重
// 去除数组的重复成员
[...new Set(array)]
// 也可以去除重复的字符
[...new Set('ababbc')].join('')
// Array.from 去除数组重复成员的另一种方法
const items = new Set([1, 2, 3, 4, 5]);
const array = Array.from(items);
Set 结构的实例有四个遍历方法,可以用于遍历成员。
Set.prototype.keys()
:返回键名的遍历器Set.prototype.values()
:返回键值的遍历器Set.prototype.entries()
:返回键值对的遍历器Set.prototype.forEach()
:使用回调函数遍历每个成员
默认遍历的方法是values
let arr = new Set(['wayne','del','zhang'])
// keys()
for(let item of arr.keys()){
console.log(item);//返回的是键名:'wayne','del','zhang'
}
// values()
for(let item of arr.values()){
console.log(item);//返回的是键值:'wayne','del','zhang'
}
// entries()
for(let item of arr.entries()){
console.log(item);//返回的是键值对:['wayne','wayne'],['del','del'],['zhang','zhang']
}
//forEach()
arr.forEach((value, key) => console.log(key + ' : ' + value));//返回的'wayne':'wayne','del':'del','zhang':'zhang'
Set 结构的键名就是键值(两者是同一个值),因此第一个参数与第二个参数的值永远都是一样的。
实例:
let num_one = [1, 2, 3, 4, 5, 2, 3, 6];
let num_two = [7, 4, 8, 9, 2, 5, 5, 5];
// 1、去重
let aa = [...new Set(num_one)];
let bb = [...new Set(num_two)];
console.log('去重', aa, bb);
// 2、交集
let intersection = aa.filter(item => new Set(bb).has(item));
console.log('交集', intersection);
// 3、并集
let union = [...new Set([...aa, ...bb])];
console.log('并集', union);
// 4、差集
let dif = aa.filter(item => !new Set(bb).has(item));
console.log('差集', dif);
七、Map
它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。
map是一个升级版的对象;
//声明一个map对象
let names = new Map();
// 对map的一些操作,set(添加元素),get(获取元素),size(查看对象长度),delete(删除对象,括号内填写所要删除的键),clear(清空对象)
// set操作
names.set('name', 'wayne');
names.set('change', () => {
console.log('Map是一个对象');
})
let age = () => {
console.log('map函数');
}
names.set(age, [22, 23, 24, 25]);
console.log(names, names.size);
//get操作
names.get('name');//返回:wayne
//size操作
console.log(names.size);
// delete操作
names.delete('change');
console.log(names, names.size);
// clear操作
names.clear();
console.log(names, names.size);
八、Class
Es5通过构造函数实例化对象的语法:
// 这是Es5通过构造函数实例化对象的语法
// 手机
function Phone(brand, price) {
this.brand = brand;
this.price = price;
}
// 添加方法
Phone.prototype.call = function () {
console.log('我可以打电话!');
}
// 实例化对象
let Huawei = new Phone('华为', 5999);
Huawei.call();
console.log(Huawei);
Es6 class写法:
// Es6 Class
class Iphone {
// 构造方法,名字不能修改
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
// Es5中对象创建方法使用的是call: function(){},在class中不允许使用:,直接call()
call() {
console.log('这是Es6 class的写法');
}
}
// 实例化类
let xiaomi = new Iphone('xiaomi', 4399);
xiaomi.call();
console.log(xiaomi);
static属性只属于类,不属于实例化对象
class Phone {
// 静态属性
static name = 'static静态属性只属于类,不属于实例化对象';
static change() {
console.log("我只属于类");
}
}
// 实例化对象
let call = new Phone();
console.log(call.name);
console.log(Phone.name);
Es5的继承
// 这是父
function Phone(brand, price) {
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function () {
console.log('我可以打电话');
}
// 智能手机 这是子
function son_phone(brand, price, color, size) {
Phone.call(this, brand, price);
this.color = color;
this.size = size;
}
// 设置子级构造函数的原型
son_phone.prototype = new Phone;
son_phone.prototype.constructor = son_phone;
// 声明子类的方法
son_phone.prototype.photo = function () {
console.log('我可以拍照');
}
son_phone.prototype.playGame = function () {
console.log('我可以玩游戏');
}
const app = new son_phone('小米', 4699, '黑色', '6.9inch');
console.log(app);
Es6 class的继承
// es6 封装继承
class Phone {
// 构造方法
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
call() {
console.log('我可以打电话');
}
}
class Son_phone extends Phone {
// 构造方法
constructor(brand, price, color, size) {
super(brand, price);
this.color = color;
this.size = size;
}
photo() {
console.log('我可以拍照');
}
playGame() {
console.log('我可以打游戏');
}
}
const app = new Son_phone('xiaomi', 4699, 'black', '6.9inch');
console.log(app);
app.call();
app.photo();
app.playGame();
九、数值的扩展
//1.Number.EPSILON是JavaScript表示的最小精度
//EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16
function equal(a, b) {
if (Math.abs(a - b) < Number.EPSILON) {
return true;
} else {
return false;
}
}
console.log(0.1 + 0.2 === 0.3);//false
console.log(equal(0.1 + 0.2, 0.3));//true
//2.Number.isFinite检测一个数值是否为有限数
// isFinite判断返回值是否有限,有限个返回TRUE,无限个返回FALSE
let num = 100;
console.log(Number.isFinite(num));//true
//3.Number.isNaN 检测一个数值是否为NaN,判断数值是否为非数字NaN
let a = NaN;
console.log(Number.isNaN(a));//true
// 4.Number.parseInt Number.parseFloat可以将字符串转化成整形,浮点型
let b = '1351adnaw';
let c = '852.332bbb';
console.log(Number.parseInt(b), Number.parseFloat(c));//1351 852.332
// 5.Number.isInteger 判断一个数值是否是整数
console.log(Number.isInteger(5));//true
console.log(Number.isInteger(2.5));//false
// 6.Math.trunc 将数字的小数部分抹掉
console.log(Math.trunc(3.5));//3
// 7.Math.sign 判断一个数是否是正数 负数 零
console.log(Math.sign(100));//1
console.log(Math.sign(0));//0
console.log(Math.sign(-100));//-1
// 1、Object.is 判断两个值是否完全相等
console.log(Object.is('zhang', 'wayne'));//false
console.log(Object.is('wayne', 'wayne'));//true
// 2、Object.assign 对象合并
const a = {
name: 'wayne',
age: 29,
sex: 'man',
money: 99999999
}
const b = {
name: 'zhang',
age: 24,
sex: 'man'
}
// 谁在前面谁就是模板,如果出现相同键名,后面的值会覆盖前面的值
console.log(Object.assign(a, b));
// 2、Object.prototypeof 设置原型对象 Object.prototypeof 获取原型对象
const app = {
name: 'wayne'
}
const cities = {
names: ['wayne', 'zhang', 'del']
}
// 第一个参数是需要设置的对象 第二个参数是定义的类型
Object.setPrototypeOf(app, cities);
console.log(Object.getPrototypeOf(app));
console.log(app);
十、模块化
使用模块化之前,vscode先下载一个live server;
只有export声明过的属性,方法,函数等才能被引用
//这是一个data.js文件
//第一种暴露方式
let name = 'wayne';
export let age = 24;
export function call () {
console.log('我可以打电话!');
}
//第二种暴露方式
let name = '韦恩';
function call () {
console.log("我可以打电话!");
}
export { name, call };
//第三种暴露方式(默认暴露),default后面可以是任意类型,数字、字符串、对象等
export default {
names: 'zhang',
money: function () {
console.log('99999999元');
}
}
导入方式:
//这是使用es6引用data.js内的数据
<script type="module">
//引入 data 模块内容
//第一种导入方式:通用导入方式
import * as data from './data.js'
console.log(data);
// 第二种导入方式:解构赋值形式
import { name, call } from './data.js';
// 当别名相同时,可以利用as进行更改名字
import { name as user, call } from './data.js';
// 默认导入,一定要重命名,不能直接使用default
import { default as data } from './data.js';
console.log(data);
// 3、简便形式 针对默认暴露
import data from './data.js';
console.log(data);
</script>
十一、async
声明一个async函数
async function call(){
return 'wayne';
}
const result = call();
console.log(result);
async返回的永远都是一个promise对象,除了主动抛出错误,或者手动返回一个promise对象,且返回错误,其他情况都是返回正确promise对象,resolve;
async function fn(){
return new Promise(resolve,reject){
//返回成功
resolve('成功的数据');
//返回失败
//reject('失败的数据');
}
}
const result = fn();
result.then(value=>{
console.log(value);
},reason=>{
console.log(reason);
})
await的使用:
const p = new Promise((resolve,rejecet)=>{
resolve('成功的值');
reject('失败的值');
})
async fucntion fn(){
try{
//try里面返回Promise正确的值,需要在p前面是用await
let result = await p;
console.log(result);
}catch(e){
//catch返回错误的值
console.log(e);
}
}
async和await结合起来使用,非常像同步的异步执行;
function fn1() {
return new Promise((resolve, reject) => {
resolve('成功数据111');
})
}
function fn2() {
return new Promise((resolve, reject) => {
resolve('成功数据222');
})
}
function fn3() {
return new Promise((resolve, reject) => {
resolve('成功数据333');
})
}
async function main() {
let one = await fn1();
let two = await fn2();
let three = await fn3();
console.log(one);
console.log(two);
console.log(three);
}
main();
封装Ajax进行请求数据
function sendAjax(url) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
xhr.status === 200 ? resolve(xhr.responseText) : reject(xhr.responseText);
}
}
})
}
async function fn() {
try {
let res = await sendAjax("http://test.api.com/v3/course/pageList?page_num=1&page_size=10");
console.log(res);
} catch (e) {
console.log(e);
}
}
fn();