ES6+知识点集

目录

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()


 

let关键字

  • 声明变量
  • 块级作用域
  • 变量不能重复声明
  • 不存在变量提升
  • 不影响作用域链

const关键字

  • 声明常量并且必须赋值
  • 不存在变量提升
  • 不能重复赋值 但可以更改和添加常量对象的属性
  • 块级作用域
        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

遍历Map结构

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指向问题

  • 普通函数的this在声明时指向window,在调用时指向调用它的对象,如果直接调用,也指向window
  • 箭头函数的this在声明时指向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]
 
//如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。

迭代器(iterator)

  • 什么是迭代

从一个数据集合中按照一定的顺序,不断的取出数据的过程

  • 迭代和遍历有什么区别

迭代强调的是依次取出,不能确定取出的有多少,也不能保证把数据全部取完

  • 什么是迭代器

对迭代过程的封装,通常为对象,不同的语言,表现出来的迭代形式不一样

  • 迭代模式

一种设计模式,用于同一迭代的过程,并且规范迭代器的规格。

//普通的对象没有实现迭代器接口,不能通过迭代器遍历
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 对象

生成器(Generator)

//生成器函数
        //在函数定义时,在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

promise用法

    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);
            })
        })

set

属性和方法

  • size:  返回set实例的成员总数
  •     add( value ): 添加某个值,返回Set结构本身
  •     delete( value ): 删除某个值,返回布尔值
  •     has( value ): 返回布尔值,表示参数是否为set的成员
  •     clear(): 清除所有成员,没有返回值
        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方法接受一个新参数,这个参数就是将原数组变成新数组的映射关系。

	//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' ] }

classl-类

  • 在ES6中,class (类)作为对象的模板被引入,可以通过 class 关键字定义类。它可以被看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法。
  • 类实际上是个“特殊的函数”,就像你能够定义的函数表达式和函数声明一样,类语法有两个组成部分:类表达式和类声明。
//定义一个类的一种方法是使用一个类声明,即用带有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)
  }
}
  • 在类中声明方法的时候,方法前不加 function 关键字
  • 方法之间不要用逗号分隔,否则会报错
  • 类的内部所有定义的方法,都是不可枚举的(non-enumerable)
  • 一个类中只能拥有一个 constructor 方法

静态方法

//静态方法可以通过类名调用,不能通过实例对象调用,否则会报错
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

原型方法

  • 类的所有方法都定义在类的 prototype 属性上面,在类的实例上面调用方法,其实就是调用原型上的方法
  • 原型方法可以通过实例对象调用,但不能通过类名调用,会报错
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()  
    }
}
  • 上面代码中, constructor方法和toString方法之中, 都出现了super关键字, 它在这里表示父类的构造函数, 用来新建父类的this对象。
  • 子类必须在constructor方法中调用super方法, 否则新建实例时会报错。 这是因为子类没有自己的this对象, 而是继承父类的this对象, 然后对其进行加工。 如果不调用super方法, 子类就得不到this对象。

数值扩展

不同进制的字面量表示

  • Binary二进制 前缀: 0b 0B
  • Octal八进制 前缀: 0 0o 0O
  • Decimal十进制 无前缀
  • Hex十六进制 前缀: 0x 0X

常量

  • Number.EPLISION // 2.220446049250313e-16
  • EPSILON表示1与大于1的最小浮点数之间的差。
  • Number.MAX_SAFE_INTEGER // 9007199254740991
  • Number.MIN_SAFE_INTEGER // -9007199254740991

Math对象的扩展

ES6在Math对象上新增了17个数学相关的静态方法。

  • Number.isInteger()用来判断一个数是不是整数,3.0和3的效果一样
  • Number.parseInt/Number.parseFloat:字符串转整数
  • Number.EPSILON是一个极小的常量,用于比较浮点数
  • isFinite:判断是不是有尽的数值。
  • isNaN:判断是否是数值。
  • 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) 求反双曲正切

import 和 export的用法

模块功能主要由两个命令构成: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';

async  await用法

  • async/await出现的异常是无法捕获的,所以这个时候,我们需要借助try...catch来捕获异常;
  • async/await函数的声明和普通函数没有什么区别,函数声明式,对象方法,class类方法,和箭头函数等都可以声明async/await函数;
  • 任何一个await后面的promise对象变为reject,那么整个async都会被中断;
  • async/await函数返回的是一个promise,必须等到内部所有的await后面的promise都执行完成之后,才能发生状态改变,除非遇到return或者是跑出错误,也就是说,只要async函数内部的异步操作执行完成,才会执行then方法指定的回掉函数;
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()

Object.fromEntries(),Object.Entries()

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。

  • ES6新增Symbol :这种类型的对象永不相等,即始创建的时候传入相同的值,可以解决属性名冲突的问题,做为标记。
  • ES10版本中还出现了一种 bigInt。Javascript 中的任意精度整数,可以安全存储和操作大整数。即始超出 Number 能够表示的安全整数范围。是 chrome 67中的新功能。

基本数据类型

 String、Number、boolean、null、undefined。

  • 基本数据类型是按值访问的,就是说我们可以操作保存在变量中的实际的值;
  • 基本数据类型的值是不可变的,任何方法都无法改变一个基本数据类型的值,比如一个字符串
  • 基本数据类型的赋值是简单的赋值(如果从一个变量向另一个变量赋值基本类型的值,会在变量对象上创建一个新值,然后把该值赋值到位新变量分配的位置上)
  • 基本类型的值在内存中占据固定大小的空间,被保存在栈内存中。(从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本)
  • 基本数据类型不可以添加属性和方法
  • 基本数据类型的比较是值的比较

number类型

  • number类型包含整数和浮点数(浮点数数值必须包含一个小数点,且小数点后至少有一位数字)
  • 浮点数的最高精度是17位
  • NaN:非数字类型,特点:涉及到任何关于NaN的操作,都会返回NaN(false),而且NaN不等于自身
  • isNaN()函数用于判断是否是一个非数字类型,如果传入的参数是一个非数字类型,那么返回true,否则返回false
  • isNaN()函数传入一个参数,函数会先将参数转换为数值,如果参数类型为对象类型,会先调用对象的valueOf()方法,再确定该方法返回的值是否可以转换为数值类型,如果不能,再调用对象的toString()方法,再确定返回值 
  • 数值转化:

      Number(),转型函数,可以用于任何数据类型

      parseInt(),将值转换为整型,用的较多

      parseFloat(),将值转换为浮点型

string类型

  • 字符串类型中的单双引号作用一样
  • 字符串有length属性,可以取得字符串的长度
  • 字符串的值是不可变的,要改变一个字符串的值,首先要销毁原来的字符串,再用另一个包含新值得字符串区填充该字符串;
  • 字符串转换:

        String(),转型函数,适用于任何数据类型(null,undefined转换后为null和undefined)

        toString()方法可以把一个逻辑值转换为字符串,并返回结果(null、undefined没有toString()方法)

boolean类型

  • 这个类型只有两个值,true和false;
  • Boolean(),转型函数,将某个值转换为Boolean类型

null类型

  • null类型被看做空对象指针,只有一个值,即null值,所以在用typeof操作符去检测null类型的值得时候,结果是object类型;
  • 如果你定义了一个变量,但是想在以后把这个对象当做一个对象来使用,最好将该对象初始化为null值

undefined类型

  • 只有一个值,即undefined,如果声明了一个变量,但是未给变量初始化值,那么这个变量的值就是undefined:
  • 调用函数时,应该提供的参数没有提供,该参数等于undefined;
  • 对象没有赋值的属性,该属性的值为undefined;
  • 函数没有返回值,默认返回undefined
  • undefined 是从 null 中派生出来的(undefined 是没有定义的,null 是定义了但是为空)

”==”与”===”是不同的,一个是判断值是否相等(不同类型可自动转换),一个是判断值及类型是否完全相等

引用数据类型

引用数据类型(应运而生){} [] Date RegExp fn 

object对象数据类型

  • 对象 是复合数据的载体, 用{}包起来, 内容是一对一对的键值对(属性名: 属性值)
  • 这里的冒号相当于 等号 是赋值的意思,不同的键值对之间用逗号隔开
  • 属性名 对应 咱们变量名 (但是属性名可以是数字,也不能是数字开头的字符)
  • 对应咱们的 等号
  • 属性值 对应咱们的 变量的值(可以是任意的数据类型)
 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



    //定义属性时,属性名的引号可带可不带
    //调用时,若是通过打点的方式获取某个属性对应的值,我们不能给这个属性加引号
    //若是通过 [] 的方式获取某个属性对应的值,我们必须用引号把这个属性名包起来
    //如果不用引号包起来,则 [] 内代表的是变量对应的值;
    //若属性名是数字的时候, 我们必须用 [] 的方式获取该属性对应的值,这时的数字属性名的引号可加可不加

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

(2)给对象添加 一项()

 var user = {
        name:'xiaoming',
        password:'1234'
    };
  • 1
  • 2
  • 3
  • 4

(3)修改对象(直接给属性名重新赋值)

    user.name = 'xm1';
  • 1

当这个对象里边有这个属性的时候,我们再重新赋值时,是相当于修改这个属性对应的属性值
当这个对象里边没有这个属性时,我们给这个属性赋值时,就相当于给这个对象添加了这个属性
(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 : 换行符

function函数数据类型


    //我们要用函数的原因
    // 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 、instanceof、constructor、jQuery.type()、Object.prototype.toString.call()

typeof()——判断简单的数据类型,无法菊粉复杂数据类型,例如像Object和Array返回的都是Object
instanceof ——仅适用于对象来区分数据类型。同时还可以判断某个实例是否是某个构造函数的实例,但是会出现对应多个构造函数的情况//检测某个实例是否属于这个类
constructor——判断所有的数据类型。当然他的本质是盘算prototyep属性所在的函数的//获取当前实例的构造器
jQuery.type()——判断所有的数据类型。

Object.prototype.toString.call()//获取当前实例的所属类信息

Array.isArray(objectName)//判断数组

  • typeof()——返回对应的数据类型。如果是引用类型(复杂数据类型:对象和数组),那么返回的都是Object,无法具体区分
  • instanceof——只适用于对象类型,不适用于简单类型的数据类型,返回boolean值
//作用: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;
}
  • constructor——本身是prototype对象的一个属性,默认指向prototype属性所在的构造函数,此处我们用来判断数据类型。返回boolean值
//作用:1.判断数据类型,包括数组、日期、对象等,可以区分清楚
//语法:变量名.constructor === 数据类型

str.constructor===String   //true
num.constructor===Number   //true
obj.constructor===Object   //true
arr.constructor===Array   //true
new Date().constructor===Date   //true
  • jQuery.type()——称之为万能
//作用:判断数据类型。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.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

你可能感兴趣的:(前端,js,es6/es7)