目录
let关键字
const关键字
解构赋值
数组解构
对象解构
字符串/数值/布尔值
浅拷贝
交换变量
遍历Map结构
模板字符串
简化对象写法
箭头函数
this指向问题
纯函数
扩展运算符
迭代器(iterator)
生成器(Generator)
promise用法
set
属性和方法
map函数
classl-类
类的方法
数值扩展
不同进制的字面量表示
常量
Math对象的扩展
import 和 export的用法
async await用法
Object.fromEntries(),Object.Entries()
数据类型
基本数据类型
number类型
string类型
boolean类型
null类型
undefined类型
引用数据类型
object对象数据类型
[] 数组
正则
function函数数据类型
判断数据类型的方法
typeof 、instanceof、constructor、jQuery.type()、Object.prototype.toString.call()
const car = { type: "porsche", model: "911", color: "Black" };
// 您可以更改属性:
console.log(car);
car.color = "White";
// 您可以添加属性:
car.owner = "Bill";
// 基础类型解构
let [a, b, c] = [1, 2, 3]
console.log(a, b, c) // 1, 2, 3
// 对象数组解构
let [a, b, c] = [{name: '1'}, {name: '2'}, {name: '3'}]
console.log(a.name, b, c) // 1, {name: '2'}, {name: '3'}
// ...解构
let [head, ...tail] = [1, 2, 3, 4]
console.log(head, tail) // 1, [2, 3, 4]
// 嵌套解构
let [a, [b], d] = [1, [2, 3], 4]
console.log(a, b, d) // 1, 2, 4
// 解构不成功为undefined
let [a, b, c] = [1]
console.log(a, b, c) // 1, undefined, undefined
// 解构默认赋值
let [x = 1] = [undefined];// x=1;
let [x = 1] = [null];// x=null; // 数组成员严格等于undefined,默认值才会生效
let [x = 1, y = x] = []; // x=1; y=1
let [x = 1, y = x] = [2]; // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = []; // ReferenceError: y is not defined 因为x用y做默认值时,y还没有声明
// 可以不按照顺序,这是数组解构和对象解构的区别之一
let { f2, f1 } = { f1: 'test1', f2: 'test2' }
console.log(f1, f2) // test1, test2
// 解构对象重命名
let { f1: rename, f2 } = { f1: 'test1', f2: 'test2' }
console.log(rename, f2) // test1, test2
// 嵌套解构
let { f1: {f11}} = { f1: { f11: 'test11', f12: 'test12' } }
console.log(f11) // test11
// 默认值
let { f1 = 'test1', f2: rename = 'test2' } = { f1: undefined, f2: 'current2'}
console.log(f1, rename) // test1, current2
// String
let [ a, b, c, ...rest ] = 'test123'
console.log(a, b, c, rest) // t, e, s, [ 't', '1', '2', '3' ]
let {length : len} = 'hello'; // en // 5
// number
let {toString: s} = 123;
s === Number.prototype.toString // true
// boolean
let {toString: s} = true;
s === Boolean.prototype.toString // true
// Map
let [a, b] = new Map().set('f1', 'test1').set('f2', 'test2')
console.log(a, b) // [ 'f1', 'test1' ], [ 'f2', 'test2' ]
// Set
let [a, b] = new Set([1, 2, 3])
console.log(a, b) // 1, 2
let colors = [ "red", "green", "blue" ];
let [ ...clonedColors ] = colors;
console.log(clonedColors); // "[red,green,blue]"
let x = 1;
let y = 2;
[x, y] = [y, x];
console.log("x:"+x,",y:"+y);//x:2 ,y:1
var map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for (let [key, value] of map) {
console.log(key + " is " + value);//first is hello second is world
}
//用反引号(`)标识,它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
// 普通字符串
`In JavaScript '\n' is a line-feed.`
// 多行字符串
`In JavaScript this is
not legal.`
// 字符串中嵌入变量
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?` // Hello Bob, how are you today?
let x = 3;
let y = 5;
//普通写法
let obj = {
x:x,
y:y,
getXy:function(){
return this.x+this.y;
}
}
//ES6写法 同名的属性可以省略,函数可以省略关键字function
let obj = {
x,
y,
getXy(){
return this.x+this.y;
}
}
console.log(obj,obj.getXy);
箭头函数有几个使用注意点。
(1)函数体内的this
对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new
命令,否则会抛出一个错误。
(3)不可以使用arguments
对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用yield
命令,因此箭头函数不能用作 Generator 函数。
var fn1 = function(a, b) {
return a + b
}
function fn2(a, b) {
return a + b
}
//将原函数的“function”关键字和函数名都删掉,并使用“=>”连接参数列表和函数体。
var fn1 = (a, b) => {
return a + b
}
(a, b) => {
return a + b
}
//当函数参数只有一个,括号可以省略;但是没有参数时,括号不可以省略。
var fn1 = () => {}
var fn2 = a => {}
var fn3 = (a, b) => {}
var fn4 = (a, b, ...args) => {}
//箭头函数有两种格式,一种只包含一个表达式,省略掉了{ ... }和return。还有一种可以包含多条语句,这时候就不能省略{ ... }和return
() => return 'hello'
(a, b) => a + b
this
在声明时指向window
,在调用时指向调用它的对象,如果直接调用,也指向window
window
,在调用时指向声明时所在的上下文this
一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用,我们就把这个函数叫做纯函数。
对象中的扩展运算符(...)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中
扩展运算符对对象实例的拷贝属于一种浅拷贝
//合并数组
// ES5 的写法
[1, 2].concat(more);
arr1.concat(arr2, arr3);
// ES6 的写法
[1, 2, ...more];
[...arr1, ...arr2, ...arr3]
let bar = { a: 1, b: 2 };
let baz = { ...bar }; // { a: 1, b: 2 }
//上述方法实际上等价于:
let bar = { a: 1, b: 2 };
let baz = Object.assign({}, bar); // { a: 1, b: 2 }
//扩展运算符可以与解构赋值结合起来,用于生成数组
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
//如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。
什么是迭代
从一个数据集合中按照一定的顺序,不断的取出数据的过程
迭代强调的是依次取出,不能确定取出的有多少,也不能保证把数据全部取完
对迭代过程的封装,通常为对象,不同的语言,表现出来的迭代形式不一样
一种设计模式,用于同一迭代的过程,并且规范迭代器的规格。
//普通的对象没有实现迭代器接口,不能通过迭代器遍历
let myIterable = {
a: 1,
b: 2,
c: 3
}
// 使用 for..of 循环
for(let elem of myIterable) {
console.log(elem);
}//报错 Uncaught TypeError: myIterable is not iterable
//那如何实现迭代器(Iterator)接口呢,只需要在这个对象中实[Symbol.iterator]属性方法,[Symbol.iterator]这个属性名看起来怪怪的,Symbol是ES6表示唯一性的标识符,是Symbol的静态属性,标准委员会是为了避免命名的冲突,所以才这样命名。下面我们来实现[Symbol.iterator]属性。如下:
let myIterable = { a: 1,b: 2,c: 3 }
myIterable[Symbol.iterator] = function() {
let self = this;
let arr = Object.keys(self);
let index = 0;
return {
next() {
return index < arr.length ? {value: self[arr[index++]], done: false} : {value: undefined, done: true};
}
}
}
for(const i of myIterable) {
console.log(i);
}
原生的具备 Iterator 接口的数据结构如下:Array、Map、Set、String、TypedArray(类数组)、函数的 arguments 对象、DOM NodeList 对象
//生成器函数
//在函数定义时,在function 后加*的就是生成器函数
function* fun() {
console.log('1');
yield '2'
console.log('3')
yield '4'
console.log('5')
return
}
//生成器函数在调用时是不执行的,会返回一个对象,这个对象有个next方法
let i = fun();
console.log(i)
let o = i.next();
console.log(o.value, o.done, o.done ? '函数执行完毕' : '函数未执行完毕')
//调用next方法后,函数执行到 第一个yield停止 会返回一个对象{value:'',done:''}
//value的值为yield的值
//done有两个值 true false
//false 函数为执行完毕
//true 函数执行完毕
o = i.next()
console.log(o.value, o.done, o.done ? '函数执行完毕' : '函数未执行完毕')
//第二次调用,会从上次退出的位置,执行到下面的第一个yield停止 返回一个对象
o = i.next()
console.log(o.value, o.done, o.done ? '函数执行完毕' : '函数未执行完毕')
//第三次调用时,会从上一次函数退出的位置,继续执行,到下一个yield停止
//直到遇到return
var p = new Promise(function(resolve,reject){
console.log("结果");
resolve("结果")
})
//以上代码将一段同步代码封装成了一个promise实例,promise实例有两个三个状态
//peding 正在请求
//resolved 成功
//rejected 失败
//这个实例内部调用resolve,返回成功状态,并将结果通过resolve传递。
//传递出来的结果如何使用呢?
//下面的代码,通过调用promise实例上面的then方法来获得resolve传递的数据。
p.then(function(data){
console.log(data)
})
$(function(){
// 封装一个promise;
var p = function(url){
return new Promise(function(resolve,reject){
$.get(url,function(data){
resolve(data);
})
})
}
var arr = []
p("https://cnodejs.org/api/v1/topics?tab=ask")
.then(function(data){
arr.push(data);
return p("https://cnodejs.org/api/v1/topics?tab=share")
}).then(function(data){
arr.push(data);
return p("https://cnodejs.org/api/v1/topics?tab=ask")
}).then(function(data){
arr.push(data);
return p("https://cnodejs.org/api/v1/topics?tab=good")
}).then(function(data){
arr.push(data);
console.log(arr);
})
})
如何捕获promise的错误呢?在promise的调用链的最后调用catch函数,一旦promise调用链中有reject执行,promise就会终止执行直接进入catch函数,否则catch不会执行。
$(function(){
// 封装一个promise;
var p = function(url){
return new Promise(function(resolve,reject){
$.get(url,function(data){
resolve(data);
})
})
}
// P2的另一种形态:
// 如果是reject会直接跳到catch里面去,如果是resolve,会接着执行,不会跳跃
var p2 = function(){
return new Promise(function(resolve,reject){
setTimeout(function(){
reject("err");
},100)
})
}
Promise.race([
p("https://cnodejs.org/api/v1/topics?tab=good"),
p2()
]).then(function(result){
console.log(result);
}).then(function(){
console.log("我运行了")
}).catch(function(data){
console.log(data);
})
})
let arr = [1, 2, 3, 4, 5, 6, 6, 8, 7, 5, 5, 7, 6, 4];
// 1.数组去重
let result = [...new Set(arr)]
console.log("去重:" + result)
// 2.交集
let arr1 = [1, 3, 5, 7, 7, 5, 1];
// let result1 = [...new Set(arr)].filter(item => {
// let s1 = new Set(arr1);
// if(s1.has(item)){
// return true
// }else{
// return false
// }
// })
let result1 = [...new Set(arr)].filter(item => new Set(arr1).has(item))
console.log("交集:" + result1)
// 3.并集
let result2 = [...new Set([...arr, ...arr1])]
console.log("并集:" + result2)
// 4.差集
let result3 = [...new Set(arr)].filter(item => !(new Set(arr1).has(item)))
console.log("差集" + result3)
map()方法:map,映射,即原数组映射成一个新的数组;
map方法接受一个新参数,这个参数就是将原数组变成新数组的映射关系。
//Map
const map=new Map();
//存储值
map.set("xx","ss");
//只有对同一个对象 引用时 才会返回该键的值
map.set(['1'],"this is a objcet");
console.error(map.get(['1']));
//在map 两个值严格相同才会返回同个键值
//-0 和 0 相同
map.set(-0,'xxx');
console.log(map.get(0)); //xxx
//undefind 和 null 不同
map.set(undefined,"this is undefined");
map.set(null,'null');
console.log(map.get(undefined));
//NaN 相同
map.set(NaN,'this is NaN');
console.log(map.get(NaN)); //this is NaN
//方法
//size
console.log(map.size); //6
//map.prototype.set(key,value)
console.log(map.set("key","this is value"));
// Map {
// 'xx' => 'ss',
// [ '1' ] => 'this is a objcet',
// 0 => 'xxx',
// undefined => 'this is undefined',
// null => 'null',
// NaN => 'this is NaN',
// 'key' => 'this is value' }
//可以看出 返回的是map对象
//所以还可以
console.log(map.set('key1',"key1").set("key2","key2"));
// Map {
// 'xx' => 'ss',
// [ '1' ] => 'this is a objcet',
// 0 => 'xxx',
// undefined => 'this is undefined',
// null => 'null',
// NaN => 'this is NaN',
// 'key' => 'this is value',
// 'key1' => 'key1',
// 'key2' => 'key2' }
//Map.prototype.get
console.log(map.get("key1")); //key1
//当键是函数时
function fun(){
console.log("fun")
}
map.set(fun,"funny");
console.log(map.get(fun)); //funny
//当值不存在时
console.log(map.get("key3")); //undefiend;
//Map.prototype.has();
console.log(map.has("key1")); //true
console.log(map.has("key3")); //false
// Map.prototype.clear 清除所有键 没有返回值
console.log(map)
// Map {
// 'xx' => 'ss',
// [ '1' ] => 'this is a objcet',
// 0 => 'xxx',
// undefined => 'this is undefined',
// null => 'null',
// NaN => 'this is NaN',
// 'key' => 'this is value',
// 'key1' => 'key1',
// 'key2' => 'key2',
// [Function: fun] => 'funny' }
map.clear()
console.log(map) //Map {}
//遍历
map.set("key1","value1");
map.set("key2","value2");
//先输出map.keys() 和 values()
console.log(map.keys()); //MapIterator { 'key1', 'key2' } //查看键
console.log(map.values()); //MapIterator { 'value1', 'value2' } //查看值
for (let k of map.keys()) {
console.log(k);
//key1
//key2
}
//遍历值
for (let v of map.values()) {
console.log(v);
//value1
//value2
}
//遍历键值
for(let item of map.entries()){
console.log(item);
// [ 'key1', 'value1' ]
// [ 'key2', 'value2' ]
console.log(item[0]);
//key1
//key2
}
for(let [key,value] of map.entries()){
console.log("键是"+key+"值是"+value);
// 键是key1值是value1
// 键是key2值是value2
}
//forEach方法
map.forEach((key,value)=>{
console.log("键1是"+key+"值2是"+value);
// 键1是value1值2是key1
// 键1是value2值2是key2
})
for (let [key, value] of map) {
console.log("键是"+key+"值是"+value);
// 键是key1值是value1
// 键是key2值是value2
}
//上面那个例子说明 Map 结构的默认遍历器接口(Symbol.iterator属性),就是entries方法。
console.log(map[Symbol.iterator] === map.entries) //true
//Map转化为数组对象
console.log([...map.keys()]) //[ 'key1', 'key2' ]
console.log([...map.values()]) //[ 'value1', 'value2' ]
console.log([...map]) //[ [ 'key1', 'value1' ], [ 'key2', 'value2' ] ]
//过滤 map没有过滤方法 只能通过数组过滤
map.clear();
map.set(1,"x").set(2,"xx")
const map2=new Map([...map].filter(([k,v])=> k>1 ));
console.log(map2) //Map { 2 => 'xx' }
map2.clear();
const map3 = new Map(
[...map].map(([k, v]) => [k * 2, 'value=' + v])
);
console.log(map3)
//Map { 2 => 'value=x', 4 => 'value=xx' }
//相互转换
//Map转化为数组
console.log([...map]) //[ [ 1, 'x' ], [ 2, 'xx' ] ]
//数组转化为map
var arr=[ [ 1, 'x' ], [ 2, 'xx' ] ];
console.log(new Map(arr)); //Map { 1 => 'x', 2 => 'xx' }
//Map转化为字符串
function maptoObject(map){
let obj=new Object();
for(let [k,v] of map){
obj[k]=v;
}
return obj;
}
console.log(maptoObject(map)) //{ '1': 'x', '2': 'xx' }
//如果键不是对象的话 会转化为对象
//对象转化为数组
function ObjcettoMap(obj){
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
var obj={"x":"k","y":"k1"};
console.log(ObjcettoMap(obj)); //Map { 'x' => 'k', 'y' => 'k1' }
//Map转化为Json
//1.可以吧map转化为object 再次转为JSON
console.log(maptoObject(map)); //{ '1': 'x', '2': 'xx' }
console.log(JSON.stringify(maptoObject(map))); //{"1":"x","2":"xx"}
//2 如果键里有不是字符串的值 比如true 可以吧map转化为数组在转化为JSON
map.set(true,"true")
console.log(JSON.stringify(maptoObject(map))); //{"1":"x","2":"xx","true":"true"} true 变成字符串
console.log(JSON.stringify([...map])) //[[1,"x"],[2,"xx"],[true,"true"]]
//JSON转化为map
//1直接转化 用JSON.parse
var obj1='{"x":"xx","x1":"xxx"}';
console.log(ObjcettoMap(JSON.parse(obj1))); //Map { 'x' => 'xx', 'x1' => 'xxx' }
//2 整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组。
//这时,它可以一一对应地转为 Map。这往往是 Map 转为数组 JSON 的逆操作。
console.log(new Map(JSON.parse('[[true,7],[{"foo":3},["abc"]]]')));
//Map { true => 7, { foo: 3 } => [ 'abc' ] }
//定义一个类的一种方法是使用一个类声明,即用带有class关键字的类名
class Person {
constructor(x, y) {
this.x = x
this.y = y
}
}
//函数声明和类声明之间的一个重要区别是函数声明会提升,类声明不会。需要先进行声明,再去访问,否则会报错
var person= new Person()
class Person {
constructor(x, y) {
this.x = x
this.y = y
}
}// Personis not defined
//类声明不可以重复
//类必须使用 new 调用,否则会报错。
constructor 方法
class Person {
constructor(x, y) {
this.x = x // 默认返回实例对象 this
this.y = y
}
toString() {
console.log(this.x + ', ' + this.y)
}
}
静态方法
//静态方法可以通过类名调用,不能通过实例对象调用,否则会报错
class Person {
static sum(a, b) {
console.log(a + b)
}
}
var p = new Person()
Person.sum(1, 2) // 3
p.sum(1,2) // TypeError p.sum is not a function
原型方法
class Person {
constructor() {
// 默认返回实例对象 this
}
sum() {
}
toString() {
console.log('123456')
}
}
// 给 Person 的原型添加方法
Person.prototype.toVal = function() {
console.log('I am is toVal')
}
// 等同于
Person.prototype = {
constructor() {},
sum() {},
toString() {}
}
var p = new Person()
p.toString() // 123456
p.toVal() // I am is toVal
Person.toString() // TypeError Person.toStringis not a function
Person.toVal() // TypeError Person.toVal is not a function
实例方法
class Person {
constructor() {
this.sum = function(a, b) {
console.log(a + b)
}
}
}
var p = new Person()
p.sum(1,2) // 3
Person.sum(1,2) // TypeError Person.sum is not a function
类的继承
class Point {
}
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // 调用父类的 constructor(x, y)
this.color = color;
}
toString() {
return this.color + ' ' + super.toString(); // 调用父类的 toString()
}
}
Binary
二进制 前缀: 0b
0B
Octal
八进制 前缀: 0
0o
0O
Decimal
十进制 无前缀Hex
十六进制 前缀: 0x
0X
Number.EPLISION
// 2.220446049250313e-16EPSILON
表示1与大于1的最小浮点数之间的差。Number.MAX_SAFE_INTEGER
// 9007199254740991Number.MIN_SAFE_INTEGER
// -9007199254740991ES6在Math对象上新增了17个数学相关的静态方法。
Number.parseInt/Number.parseFloat
:字符串转整数Math.trunc(x)
截取数值的整数部分Math.sing(x)
判断数值的正负号。返回(1, -1, 0, -0或NaN)。Math.cbrt(x)
求立方根Math.hypot(...values)
计算所有参数的平方和的平方根Math.imul(x, y)
两个数以32位带符号整数形式相乘的结果。返回的也是32位的带符号整数。(signed int,带符号4字节)
Math.clz32(x)返回x的4字节整数形式的前导0的个数
Math.fround(x)` 获取数字的4字节单精度浮点数形式Math.exmpl(x)
计算e的x次方-1的结果。即Math.exp(x)-1
。Math.log1p(x)
计算1+x的自然对数,即Math.log(1+x)
。Math.log10(x)
计算以10为底的对数。Math.log2(x)
计算以2为底的对数。Math.sinh(x)
求双曲正弦Math.cosh(x)
求双曲余弦Math.tanh(x)
求双曲正切Math.asinh(x)
求反双曲正弦Math.acosh(x)
求反双曲余弦Math.atanh(x)
求反双曲正切模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能
//导出 ept.js(导出模块所在文件)
export var name = "scy";
//对应导入
import {name} from './ept.js';
//导出ept.js
var name = "scy";
var age = 19;
export {name, age};
//导入
import {name, age} './ept';
export function f1()...
import {f1} from './ept';
export class A ...
import {A} from './ept';
下面介绍默认模块的操作 ,默认模块只能有一个
//变量
var name = 'scy';
export default name;
import name from './ept';//注意这里没有花括号
//函数
function f1()...
export default f1;//这是默认模块的写法
import f1 from './ept';//注意这里没有花括号
//类
export default class A{ ... };
import A from './ept';
const fetch = require('node-fetch')
/*
把任意类型的函数 转成async风格
*/
//修改为异步请求
// 修改为箭头函数
const getZhihuColumn = async (id) => {
const url = `https://zhuanlan.zhihu.com/api/columns/${id}`
const response = await fetch(url) // 相当于得到请求数据
// const data = await response.json()
// return data;
// 上面两行 直接修改成
return await response.json();
}
// 在async 在顶级作用域下是非法的, 所以需要使用匿名函数, 也需要声明为async
(async () => {
const data = await getZhihuColumn('feweekly');
console.log(`NAME: ${data.description}`);
console.log("INTRO:" + `${data.intro}`);
})();
const fetch = require('node-fetch')
/*
把任意类型的函数 转成async风格 在类上面的使用
*/
class APIClent {
async getColumn(id) {
const url = `https://zhuanlan.zhihu.com/api/columns/${id}`
const response = await fetch(url) // 相当于得到请求数据
return await response.json();
}
}
// 在async 在顶级作用域下是非法的, 所以需要使用匿名函数, 也需要声明为async
(async () => {
const client = new APIClent();
const data = await client.getColumn('feweekly'); //注意别忘记加await
console.log(`NAME: ${data.description}`);
console.log("INTRO:" + `${data.intro}`);
})();
const fetch = require('node-fetch')
/*
处理async中的错误
*/
//修改为异步请求
async function getZhihuColumn(id) {
const url = `https://zhuanlan.zhihu.com/api/columns/${id}`
const response = await fetch(url) // 相当于得到请求数据
//从状态去判断
if(response.status !== 200){
throw new Error(response.statusText)
}
return await response.json();
}
//假如feweekly123不存在
const showColumnInfo = async (id) =>{
try {
const data = await getZhihuColumn(id)
console.log(`NAME: ${data.description}`)
console.log("INTRO:" + `${data.intro}`)
} catch (error) {
console.log(error)
}
}
showColumnInfo('feweekly123')
/*
打印的错误信息,被catch 捕获到
Error: Not Found
at getZhihuColumn (/home/nianxiongdi/Development/nodejs/es6/async/demo8.js:16:15)
at process._tickCallback (internal/process/next_tick.js:68:7)
*/
const fetch = require('node-fetch')
/*
正确处理多个await操作的并行串行
并行代码更快
*/
//修改为异步请求
async function getZhihuColumn(id) {
const url = `https://zhuanlan.zhihu.com/api/columns/${id}`
const response = await fetch(url) // 相当于得到请求数据
//从状态去判断
if(response.status !== 200){
throw new Error(response.statusText)
}
return await response.json();
}
//假如feweekly123不存在
const showColumnInfo = async () =>{
try {
//串行的代码
// const feweekly = await getZhihuColumn('feweekly')
// const toolingtips = await getZhihuColumn('toolingtips')
//并行代码
const feweeklyPromise = getZhihuColumn('feweekly')
const toolingtipsPromise = getZhihuColumn('toolingtips')
const feweekly = await feweeklyPromise;
const toolingtips =await toolingtipsPromise;
console.log(`NAME: ${feweekly.description}`)
console.log("INTRO:" + `${feweekly.intro}`)
console.log(`NAME: ${toolingtips.description}`)
console.log("INTRO:" + `${toolingtips.intro}`)
} catch (error) {
console.log(error)
}
}
showColumnInfo('feweekly123')
const fetch = require('node-fetch')
/*
使用promise.all()让多个await操作并行
并行代码更快
*/
//修改为异步请求
async function getZhihuColumn(id) {
const url = `https://zhuanlan.zhihu.com/api/columns/${id}`
const response = await fetch(url) // 相当于得到请求数据
//从状态去判断
if(response.status !== 200){
throw new Error(response.statusText)
}
return await response.json();
}
//假如feweekly123不存在
const showColumnInfo = async () =>{
try {
//并行代码
//all() 本身也是返回promise实例 可以使用await
const [feweekly, toolingtips ] = await Promise.all([
getZhihuColumn('feweekly'),
getZhihuColumn('toolingtips')
])
console.log(`NAME: ${feweekly.description}`)
console.log("INTRO:" + `${feweekly.intro}`)
console.log(`NAME: ${toolingtips.description}`)
console.log("INTRO:" + `${toolingtips.intro}`)
} catch (error) {
console.log(error)
}
}
showColumnInfo('feweekly123')
const bluebird = require('bluebird')
/**
* 结合await和任意兼容.then()的代码
*/
async function main(){
// const number = await 890;
/**
* 若await后面不是promise 则会转化为promise
* 上面的代码会转换为
* await Promise.resolve(890);
*/
// console.log(number)
await bluebird.delay(2000) //延迟2秒
}
main()
const bluebird = require('bluebird')
const fetch = require('node-fetch')
/**
* 在for循环中正确使用await
*/
async function getZhihuColumn(id) {
// await bluebird.delay(1000);
const url = `https://zhuanlan.zhihu.com/api/columns/${id}`
const response = await fetch(url) // 相当于得到请求数据
return await response.json();
}
const showColumnInfo = async () =>{
try {
console.time('showColumnInfo') //方法名
const names = ['feweekly', 'toolingtips']
/*
//方法1
for(const name of names) {
const data = await getZhihuColumn(name)
console.log(`NAME: ${data.description}`)
console.log("INTRO:" + `${data.intro}`)
}
*/
// 方法2
const promises = names.map(x => getZhihuColumn(x));
for(const promise of promises){
const data = await promise
console.log(`NAME: ${data.description}`)
console.log("INTRO:" + `${data.intro}`)
}
console.timeEnd('showColumnInfo') //方法名
} catch (error) {
console.log(error)
}
}
showColumnInfo()
const keyValuePair = [
['cow', '????'],
['pig', '????'],
]
Object.fromEntries(keyValuePair);
// { cow: '????', pig: '????' }
// 使用构造函数
const map = new Map([
['key 1', 'value 1'],
['key 2', 'value 2']
])
// 或者我们可以使用实例方法“set”
const map = new Map()
map.set('key 1', 'value 1')
map.set('key 2', 'value 2')
// 结果
Map(2) {"key 1" => "value 1", "key 2" => "value 2"}
Object.fromEntries(map);
// { key 1: "value 1", key 2: "value 2"}
Object.fromEntries
是 Object.entries
反向。 Object.entries()
方法返回一个给定对象自身可枚举属性的键值对数组,而Object.fromEntries()
方法把键值对列表转换为一个对象。
const object = { key1: 'value1', key2: 'value2' }
const array = Object.entries(object)
// [ ["key1", "value1"], ["key2", "value2"] ]
Object.fromEntries(array)
// { key1: 'value1', key2: 'value2' }
Number、String、Boolean、Null、undefined、object、symbol、bigInt。
String、Number、boolean、null、undefined。
Number(),转型函数,可以用于任何数据类型
parseInt(),将值转换为整型,用的较多
parseFloat(),将值转换为浮点型
String(),转型函数,适用于任何数据类型(null,undefined转换后为null和undefined)
toString()方法可以把一个逻辑值转换为字符串,并返回结果(null、undefined没有toString()方法)
”==”与”===”是不同的,一个是判断值是否相等(不同类型可自动转换),一个是判断值及类型是否完全相等
引用数据类型(应运而生){} [] Date RegExp fn
var per = { c
"name":'zfpx',
1:'wwww',
age:9,
bol: true,
hobby:{
hobby1:'play',
hobby2: 'read'
},
fn: function () {
}
};
var per2 = {
name:'小明',
'name':'小红',
age:12,
age: 15,
2:13,
'2':18
};
console.log(per2["name"],per2.name);
对象的 增 删 改 查
(1)查
如果属性名是数字的话 我们再获取该属性对应的属性值的时候只能用 [] 的这种方式(属性名可以带引号 也可以不带引号(不区分单双); 带不带引号,表示的都是一个属性)
// 1、 打点的方式 (从属关系)
per.name;
console.log(per2[2]);//当属性名是数字的时候 我们只能用 [] 的方式获取
//2、中括号的方式
console.log(per['name']);
var name1 = 'age';
console.log(per[name1],per.name1,per["name1"],per[1],per["1"]);
var name2 = 'hobby';
console.log(per[name2].hobby1,per.name,per["bol"]);
console.log(per[name2][12222222]);
console.log(per[name2]['hobby1']);
per[name] //--> per['age'] -- > 9 per.age
//定义属性时,属性名的引号可带可不带
//调用时,若是通过打点的方式获取某个属性对应的值,我们不能给这个属性加引号
//若是通过 [] 的方式获取某个属性对应的值,我们必须用引号把这个属性名包起来
//如果不用引号包起来,则 [] 内代表的是变量对应的值;
//若属性名是数字的时候, 我们必须用 [] 的方式获取该属性对应的值,这时的数字属性名的引号可加可不加
(2)给对象添加 一项()
var user = {
name:'xiaoming',
password:'1234'
};
(3)修改对象(直接给属性名重新赋值)
user.name = 'xm1';
当这个对象里边有这个属性的时候,我们再重新赋值时,是相当于修改这个属性对应的属性值
当这个对象里边没有这个属性时,我们给这个属性赋值时,就相当于给这个对象添加了这个属性
(4)对象的属性的删除
1、真删除 2、假删除
数组的每一项都有一个属性名(数组本身就是一个对象,他只是对象的一个细分)跟他对应。这里的属性名(依次递增的数字) 我们叫做索引
数组对象的作用是:使用单独的变量名来存储一系列的值。
[12,23,34]
var ary = [1,true,'qqq',null,undefined,{q:1},function(){console.log(2)},sum,sum()];
var ary2 = [sum,sum()];// [sum,NaN]
var t = sum();//NaN
var ary3 = [sum,t,'t'];//[sum,NaN,'t']
// 数组里的变量,我们是要把对应的变量值放到相应的位置
// obj[name]
//对象中的查看 打点 ['']
// 数组本身也因该有打点和 [''] 两种方式 ,但是 对象中 数字的属性名,我们只能用 [''][]的方式,所以数组中的查看我们只能用 [''][]
// console.log(ary['8'],ary[8]);
正则:就是用来处理字符串的一种规则
处理字符串的两种方式
一种是匹配 test; 编写了一个正则;用这个正则去查看这个字符串是否满足你的规则;
另一种是捕获 exec;编写一个正则;然后去字符串中获取满足你规则的字符串
-/^-?(\d|([1-9]\d+))(\.\d+)?$/ /*匹配有效数的正则*/
var reg = /-/;//字面量的声明定义方式
var reg2 = new RegExp('-');// 构造函数式的定义方式
console.log(reg, reg2);
console.log(reg == reg2);//false
//用上边字面量方式 生成的正则 ;两个斜杠中的内容叫做 元字符
var reg = / /;
// 元字符 修饰符
// 修饰符
// i ignoreCase : 忽略大小写
// m multiline : 多行匹配
// g global : 全局匹配
//特殊意义的元字符
// \ :转义的意思; 把在正则里有特殊意义的字符 转成 字符本身
// . :除了换行以外的所有字符;
// \d: 代表 0~9 之间的数字
// \D: 代表除了0~9以外的字符
// \w: 数字 字母 下划线
// |W: 除了 数字 字母 下划线 以外的字符
//[a-z]:a到z之间的任意字母
//[A-Z]:
//[A-z]
//[abc]: a,b,c中的任意一个
// a|b : a或者b
//[^abc]: 除了 abc 以外的任意字符
//[^a-z]: 除了 小写字母 以外的任意字符
// 量词元字符
var reg = /\d+/;
// + : 代表前边的字符出现一次或者多次
// * :代表前边的字符出现零次或者多次
// ? : 代表前边的字符出现零次或者一次
//{n}: 代表前边的字符出现n次
//{n,}:代表前边的字符最少出现n次
//{n,m}:代表前边的字符出现 n到m次
//^ $
var reg = /^\d+$/; //23424253
//^ 代表字符串以什么开头
//$ 代表字符串以什么结尾
// () 在正则里边代表分组
// ?: -–> 代表只匹配 不捕获
// ?= -–> 正向预查
// ?! -–> 负向预查
// \s : 空白符
// \n : 换行符
//我们要用函数的原因
// 1、 节省代码
// 2、 高内聚(把东西缩到一块,这一块就是为了实现某个功能,跟其他代码没有任何联系) 低耦合(跟其他代码没关联)
// 函数的 语法
/*
* 1、function 函数名(){
* 函数体
* }
*
* 2、var 函数名 = function [函数名-可写可不写](){
* 函数体
* }
*
* 第一种声明方式, 我们在声明的代码的之前调用这个函数
* 第二种声明方式, 我们只能在声明的代码之后调用
*
* 函数声明之后 可以无限次调用
*
* return //返回的意思
*
* */
clearRoom();//函数的调用 --> 函数名()
function clearRoom() {
console.log('收拾桌子');
console.log('收拾卧室');
console.log('出门');
}
// clearRoom();
// clearPer();
var clearPer = function (){
console.log('洗脸');
console.log('刷牙');
console.log('穿鞋');
return '出门';// return 什么 那函数执行完 返给外界的就是啥
};
var a = clearPer();//把函数执行的结果赋值给 a
console.log(a);
// clearPer();
typeof()——判断简单的数据类型,无法菊粉复杂数据类型,例如像Object和Array返回的都是Object
instanceof ——仅适用于对象来区分数据类型。同时还可以判断某个实例是否是某个构造函数的实例,但是会出现对应多个构造函数的情况//检测某个实例是否属于这个类
constructor——判断所有的数据类型。当然他的本质是盘算prototyep属性所在的函数的//获取当前实例的构造器
jQuery.type()——判断所有的数据类型。
Object.prototype.toString.call()//获取当前实例的所属类信息
Array.isArray(objectName)//判断数组
//作用:1:识别对象类型;
// 2:判断一个对象是否属于某个构造函数的实例
//语法:变量名 instanceof 数据类型 || 实例对象名 instaneof 构造函数
arr instanceof Array //true
new Date() instanceof Date //true
var F = new fn(); //实例化构造函数
F instanceof fn ; //true,说明F是属于fn的实例
F instanceof Object //true
instanceof原理
instanceof (A,B) = {
var L = A.__proto__;
var R = B.prototype;
if(L === R) {
//A的内部属性__proto__指向B的原型对象
return true;
}
return false;
}
//作用:1.判断数据类型,包括数组、日期、对象等,可以区分清楚
//语法:变量名.constructor === 数据类型
str.constructor===String //true
num.constructor===Number //true
obj.constructor===Object //true
arr.constructor===Array //true
new Date().constructor===Date //true
//作用:判断数据类型。PS.其判断的结果显示都是小写的字符串形式
//语法:jQuery.type(变量名)
jQuery.type(str) //string
jQuery.type(num) //number
jQuery.type(arr) //array
jQuery.type(obj) //object
jQuery.type(fn) //funtion
Object.prototype.toString.call('') ; // [object String]
Object.prototype.toString.call(1) ; // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
更多细节请点击该链接进行学习https://es6.ruanyifeng.com/?search=map&x=0&y=0