es6总结

本文主是对于es6的总结,其分别从它的使用到它的新特性进行介绍。

1. ES6介绍

ES6是ES2015、ES2016、ES2017他们的统称
官方名字:《ECMAScript 2015 标准》=> ES6

2. 包管理机制(npm)

1.npm init -y 初始化nodejs项目
       生成一个package.json文件,该文件中保存了项目所有相关信息。
2.全局依赖 cnpm install xxx --global   简写: cnpm i xxx -g
3.局部依赖
   (1) 产品依赖 cnpm install xxx --save    简写:cnpm i xxx -S
   (2)开发依赖 cnpm install xxx --save-dev    简写:cnpm i xxx -D

3. Bable安装与使用

1.babel-cli安装
      cnpm install babel-cli -global
      cnpm install babel-preset-latest
2.使用:
    (1)在项目的根目录新建文件.babelrc文件
          {
                 “presets”: “latest”
            }
    (2)转码命令
      转码并输出到控制台
          babel . /1 - es6.js  
      转码并输出到新的文件
           babel . /1 - es6.js – out - filt 1 - es5.js   简写:babel ./1 - es6.js - o 1 - es5.js
      转码并输出整个文件夹
           babel src – out - dir dist   简写: babel src - d dist

4. 模块化机制

4.1 CommonJS模块化规范

  //导入
    let { firstName, lastName } = require('./1-module.js');
    //等同于
    let obj = require('./1-module.js');
    let first = obj.firstName;
    let last = obj.lastName;
    //对象解构(模式匹配)
    let data = {
      username: '张三',
      age: 12
    }
    let { username, age } = data;
  //导出
    let name = 'zhangsan';
    let num = 1;
    module.exports = {
      name,
      num
    }

4.2 AMD模块化规范

     AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。
     它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

4.3 ES6模块化规范

  //导入
    import { firstName, lastName, a, post } from './module1.js';
    import { firstName as first, lastName as last } from './module1.js';
    //导入默认
      import data from './module1.js'
    //导入全部
      import * as data from './module1.js';
    //导入执行(模块加载)
      import './module1.js';
    //导入第三方模块(去项目的根目录找node_modules)
      import 'babel-preset-latest';
  //导出
    export { firstName, lastName };
    export { firstName as fist, lastName as last };//重命名导出
    export let a = 1;//导出a
    export function post() {

    } //导出post函数
    //默认导出(一个模块有且只能有1个默认导出,默认导出与普通导出可以共存)
    export default {
    
    }

4.4 CommonJS与ES6模块化规范区别

①CommonJS
        var a = {age:12}; a.age = 13
        b = a;
     对于基本数据类型,属于复制。即会被模块缓存。同时,在另一个模块可以对该模块输出的变量重新赋值。
     对于复杂数据类型,属于浅拷贝。由于两个模块引用的对象指向同一个内存空间,因此对该模块的值做修改时会影响另一个模块。
     当使用require命令加载某个模块时,就会运行整个模块的代码。
     当使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值。也就是说,CommonJS模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存。
     运行时加载
② ES6
     ES6模块中的导入导出值属于【动态只读引用】。
     对于只读来说,即不允许修改引入变量的值,import的变量是只读的,不论是基本数据类型还是复杂数据类型。当模块遇到import命令时,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
     对于动态来说,原始值发生变化,import加载的值也会发生变化。不论是基本数据类型还是复杂数据类型。
      编译时输出接口。

ES6模块与CommonJS模块的差异:
   1. CommonJS 模块输出的是一个值的拷贝/复制,ES6 模块输出的是值的引用。
   2. CommonJS 模块是运行时加载,ES6 模块是编译时输出接口.

1.CommonJS模块化规范 值得拷贝
	1.1导出模块
    let firstname='ren';
    let lastname='terry';
    setTimeout(()=>{
        firstname:'zhao'
    },2000)
    module.exports={
        firstname,
        lastname
    };
	1.2导入模块
    let {firstname,lastname}=require('./module1.js');
    console.log(firstname,lastname);
    setTimeout(()=>{
       console.log(firstname,lastname);//ren terry
    },4000)
2.ES6模块 值得引用
	2.1导出模块
    let firstname='ren';
    let lastname='terry';
    setTimeout(()=>{
        firstname='zhao'
    },2000)
    export {
        firstname,
        lastname
    };
	2.2导入模块
    import {firstname,lastname} from './module3.js';
  	console.log(firstname,lastname);
	setTimeout(()=>{
       console.log(firstname,lastname);//zhao terry
    },4000)

5. es6新特性

5.1 let const 变量/常量声明

 5.1.1 let 用于声明一个变量

        ①变量不会提升,即在变量声明之前无法使用该变量;
        ②不能重复声明
        ③具有块级作用域,只在当前作用域有效。

 5.1.2 const 用于声明一个常量

        ①变量声明不会被提升,即在变量声明之前无法使用该变量;
        ②不能重复声明
        ③具有局部作用域,即const声明的变量只能在对应代码块中使用;
        ④const声明的变量在声明的时候就需要赋值,并且只能赋值一次,不能修改
        注意:这里const变量不能修改的是存储的地址值不可被修改,意思就是简单类型的数据是不能修改的。复合类型的数据(主要是对象和数组)const只能保证这个指针是固定的,而这个具体的对象实例包含的属性是可以被修改的

 //1.es6 不存在变量声明的提升
	console.log(name);
	let name = "zhangsan";
    //所处作用域内部可以访问外部,但外部不可以访问内部,不可以重复声明
	{
	   let name1="lisi"
	   console.log('内部',name1,);
	}
 //2.局部作用域,标识{}
   //第一种
	for(let i=1;i<10;i++){
	   console.log(i);
	}
	console.log('for循环',i);  // let 在外部,不能被访问到  会报错
   //第二种
	for(var i=1;i<10;i++){
	   console.log(i);
	}
	console.log('for循环',i);  //var 在外部,可以被访问到  10
	console.log('外部',name);
	function myFun (){
	  var age= 12;//当前此变量被声明了,但未使用
	    console.log(name);
	}
	myFun();
	console.log(age); //error 在函数内部定义了,但与函数外部无关
 //3.不允许重复声明  let const都不允许重复声明
	const b=1;
	const b=true; //error
 //4.const声明的变量声明是就要赋值,而且不允许修改
	const c = 0;

5.2 解构(模式匹配)

  5.2.1 介绍

       ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。解构的本质属于“模式匹配”,只要等号两边的模式相同左边的变量就会被赋予对应的值。如果解构不成功,变量的值就等于undefined。

  5.2.2 数组解构
 //1.等号左边的变量放到中括号内部,匹配右侧数组中的元素。
	let [a,b,c,d,e]=[1,2,3,[4,5],6];
	console.log(a,b,c,d,e); //1 2 3 [4,5] 6
 //2.不完全解构
	let [a,b,c,[d],e]=[1,2,3,[4,5,6],7];
	console.log(a,b,c,d,e);//1 2 3 4 7
 //3.拓展运算符解构(用在=左边聚合作用,返回一个新数组)
    let [a, ...b] = [1,2,3]; 
    console.log(a,b);//1 [2,3]
 //4.默认值解构
   //4.1
    let [a,b,c] = [1,2]
	console.log(a,b,c); //1 2 undefined
	//此时设置默认值为10
	let [a,b,c=10] = [1,2]
	console.log(a,b,c); //1 2 10
	//有值默认值就不生效
	let [a,b,c] = [1,2,3]
    console.log(a,b,c); //1 2 3
   //4.2 //函数返回值作为默认值  注意:只要是函数,就有返回值
	function myFun(){
	    console.log('函数');
	    return 100;
	}
	let [a,b,c=myFun()]=[1,2]
	console.log(a,b,c);  //1 2 undefined(没有返回值的时候)
	console.log(a,b,c);  //1 2 100
  5.2.3 对象解构

       等号左边的变量放到大括号内部,匹配右侧对象中的元素。对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

    //对象的解构,使用对象的简写形式(省略key,保留value对应的值)
	let {name:username,age:userage} ={name:"张三",age:12};
	console.log(username,userage);//张三 12	
	//重命名  将x重命名为z
	let {x:z}={x:'zhangsan',y:16};
	console.log(z);//zhangsan
	//嵌套解构
	let obj ={p:['hello',{y:'world'}]};
	let {p:[a,{y:b}]} =obj;//a:'hello'  b:'world'
	console.log(a+b);//helloworld
	//默认值解构
	let {name,age,gender = "male"}={name:'张三',age:12}
	console.log(name,age,gender); //张三 12 male
	let {name,age,gender}={name:'张三',age:12,gender:'男'}
	console.log(name,age,gender); //张三 12 男
	//拓展运算符解构
	let {a, ...b} ={a:1,b:2,c:3}
	console.log(a,b); //1 { b: 2, c: 3 }
	//使用拓展运算符可以解构数组和对象,并返回解构后的新数组或者新对象
	let obj={a:1,b:2,c:3}
	let {...b} =obj
	console.log(b); //{ a: 1, b: 2, c: 3 }
	console.log(obj == {...b});//false
  5.2.4 字符串解构
	//字符串既可以使用[]解构,也可以使用{}解构
	//使用[]解构字符串内部的字符
	//使用{}解构字符串原型中的方法和属性
	let [a,b,c,d,e] ="hello";
	console.log(a,b,c,d,e); //h e l l o
	//基本类型没有实例和方法,使用JavaScript来调用
	//对象解构:从字符串原型中解构属性和方法
	let {toString,valueOf,length}='hello';//相当于把‘hello’当成String基本包装器类型
	console.log(toString,valueOf,length);//[Function: toString] [Function: valueOf] 5
	//将string字符串转数组的方法  拓展运算符
	let [...arr] ="hello";
	console.log(arr); //[ 'h', 'e', 'l', 'l', 'o' ]
  5.2.5 number解构和boolean解构

      可以获取到数值包装器构造函数原型中指定的方法。

// 数字和Boolean只能使用{}解构其原型对象中的方法和属性
//而不能使用[]解构  因为它们都是不可迭代  string可迭代
	let { valueof } = 10
	console.log(valueof);//[Function: valueOf]
let { valueOf } = 12   valueOf === Number.prototype.valueOf()
let { valueOf } = true valueOf === Boolean.prototype.valueOf()

5.3 对象

  5.3.1 简写
    let name="张三";
	let obj={
	    name,
	    //以前写法:
	    // sayName:function(){
	    //     console.log(this.name);
	    // }
	    sayName(){
	        console.log(this.name);
	    }
	}
	obj.sayName();//张三
  5.3.2 API拓展-静态方法(通过构造函数来调用)

1.Object.is(a,b) 判断a,b两个值是否一样,类似于===
2.Object.assign() 深复制或者合并对象
3.Object.assign(obj1, obj2) 深复制,将obj2复制给obj1
4.Object.assign(obj1, obj2, obj3) 对象合并,将obj2、obj3合并后复制给obj1
5.Object.setPrototypeOf(obj1, obj2) 为目标对象设置原型,将obj2设置成obj1的原型
6.Object.getPrototypeOf() 获取目标对象的原型
7.Object.keys() 返回对象属性名组成的数组
8.Object.values() 返回对象属性值组成的数组
9.Object.entries() 返回对象[属性名, 属性值]组成的二维数组

API具体实现:

  //1.Object.is(a,b)比较两个值是否一样
	console.log(1===1);//true
	console.log(Object.is(1,1));//true
	console.log(+0 === -0);//true
	console.log(Object.is(+0,-0));//false
	console.log(NaN === NaN);//false
	console.log(Object.is(NaN,NaN));//true
  //2.assign() //第一个参数是目标对象 第二个参数是复制的内容 返回值是第一个参数
	let obj1={};
	let obj2={
	    name:'zhangsan',
	    age:12
	};
	let obj3={
	    name:'lisi', //这里的name与obj2的name重复,起作用的是这里,"后来者居上"
	    gender:'男'
	};
	Object.assign(obj1,obj2);// 2-3.深复制 将obj2复制给obj1
	console.log(obj1); //{ name: 'zhangsan', age: 12 }
	console.log(obj1 === obj2); //false
	//对象合并的结果
	let a={
	
	};
	let b={
	    name:"zs",
	    age:12
	};
	let c={
	    name:"lis",
	    gender:'男'
	}
	let result =Object.assign(a,b,c);
	console.log(result); //{name:'lisi',age:12,gender:'男’}
	Object.assign(obj1,obj2,obj3);//4.三个参数代表的是合并对象obj2,obj3到obj1当中并返回obj1对象
	console.log(obj1);//{ name: 'lisi', age: 12, gender: '男' }
	//5.获取原型对象中的方法
	Object.setPrototypeOf(obj1,obj2);
	// 原型  实例
	console.log(obj1.__proto__);//{ name: 'zhangsan', age: 12 }
	//构造函数
	console.log(obj1.constructor.prototype);//[Object: null prototype] {}
	// 6.通过getPrototypeOf方法
	console.log(Object.getPrototypeOf(obj1));//{ name: 'zhangsan', age: 12 }
	//7-9
	let keys =Object.keys(obj1); //获取所有属性名组成的数组
	let values =Object.values(obj1); //获取所有属性值组成的数组
	let entries =Object.entries(obj1); //获取键值对组成的数组
	entries.forEach((item,index)=>{
	    console.log(item[0],item[1]);
	})

5.4 数组

  5.1.1 拓展运算符(★)

...用在=左边,聚合的作用(对象、数组的解构)
...用在=右边,展开(剥离)的作用
     let arr1 = [ ‘tom’ , ‘lerry’ , ‘jacky’ ];
     let arr2 = [ …arr1 , ‘zhangsan’ , ‘lisi’ ] ;
     console.log(arr2);    // [ ‘tom’, ‘lerry’, ‘jacky’, ‘zhangsan’, ‘lisi’ ]
...(拓展运算符)也可以用在函数的形参中,作为rest参数,也叫拓展运算符的逆运算

  5.4.2 API拓展

Array.from() 将其他类型数据转成数组
Array.of() 创建数组实例,实参就是数组的元素
Array.prototype.find() 返回满足条件的第一个元素,参数为函数
Array.prototype.findIndex() 返回满足条件的第一个元素的索引,参数为函数
Array.prototype.includes() 判断当前数组中是否包含某个元素,参数为元素,返回true/false
Array.prototype.fill() 填充数组(所有元素填充),修改数组原值
Array.prototype.keys() 索引的迭代器对象
Array.prototype.values() 元素的迭代器对象
Array.prototype.entries() 键值对的迭代器对象

API具体实现:

 //1.Array.from()  将其他类型数据转成数组
	 let arrObj={
	     0:"张三",
	     1:"李四",
	     2:"王五",
	     length:3
	 }
	 let arr1 = Array.from(arrObj);
	 console.log(arr1);//[ '张三', '李四', '王五' ]
 //2.Array.of()  创建数组实例,实参就是数组的元素
	 let arr1 = new Array(3);//这里的3为默认为长度 [empty,empty,empty]
	 let arr1= Array.of(3);//这里的3是数组元素的长度
	 console.log(arr1);//[3]	
 //3.Array.prototype.find()  返回满足条件的第一个元素,参数为函数
	 let arr1= Array.of(1,2,3,4,5,6);
	 let result =arr1.find((item,index)=>{
	     //语法约束
	     return item>2;//查找下标大于2
	 })
	 console.log(result);//3
 //4.findIndex  返回满足条件的第一个元素的索引,参数为函数  找不到返回-1
	 let result =arr1.findIndex((item,index)=>{
	     return item>2;
	     //return item>6;  找不到返回-1
	 })
	 console.log(result);//2
 //5.includes()  判断当前数组中是否包含某个元素,参数为元素,返回true/false
	 let result1=arr1.includes(1);//判断当前数组中是否还有1
	 console.log(result1);//true
 //6.fill()  填充数组(所有元素填充),修改数组原值
	 let result2 = arr1.fill(7);
	 console.log(result2);//[ 7, 7, 7, 7, 7, 7 ]
	 console.log(result2 === arr1);//true
	 console.log(arr1);//[ 7, 7, 7, 7, 7, 7 ]
 /*7.Array.prototype.keys()      索引的迭代器对象
	 Array.prototype.values()    元素的迭代器对象
	 Array.prototype.entries()   键值对的迭代器对象
 */
	 let keys =arr1.keys();
	 let values =arr1.values();
	 let entries =arr1.entries();
	 //迭代器对象
	 console.log(keys,values,entries);//Object [Array Iterator] {} Object [Array Iterator] {} Object [Array Iterator] {}
	 console.log(Array.from(keys));//[ 0, 1, 2, 3, 4, 5 ]
	 console.log(Array.from(values)); //[ 1, 2, 3, 4, 5, 6 ]
	 console.log(Array.from(entries));//[ [ 0, 1 ], [ 1, 2 ], [ 2, 3 ], [ 3, 4 ], [ 4, 5 ], [ 5, 6 ] ]	

5.5 函数

  5.5.1 函数参数
 //1.默认值
	let myFun1 = function(a,b,c=10){
	    console.log(a,b,c); //null 2 10
	    //类数组对象,可迭代的  可通过Array.from来转换数据类型
	    console.log(arguments);//[Arguments] { '0': null, '1': 2 }  
	}
	// myFun1(null,2);//null 2 undefined(没有默认值)
	myFun1(null,2);//null 2 10
 //2.对象的解构 {}
	let myFun2 = function({a,b,c}){
		//根据对象的key值
	    console.log(a,b,c);//tom 1 2
	}
	//类似于  let {a,b,c} = {a:1,c:2,b:'tom'}
	myFun2({b:1,c:2,a:'tom'});
 //3.数组 []
	let myFun3 = function ([a,b,c]) {
	    console.log(a,b,c);//undefined 2 3
	}
	myFun3([,2,3]);//数组里面可以存空 
 //4.获取es6的实参
	//...运算符,用在函数形参位置,叫做rest参数,也叫拓展运算符的逆运算
	let myFun4 = function (a,...b) {
	    console.log(a,b);
	}
	myFun4(1,2,3,4,5,6);//1 [ 2, 3, 4, 5, 6 ]	
  5.5.2 箭头函数(★)

①this指向
    普通函数:this指向调用者,没有调用者指向global
    箭头函数:没有自己的this,this指向’声明时’外部作用域的this
②箭头函数写法
     极简写法(形参只有一个时,可省略括号,只有一句返回语句时,箭头后面可直接写表达式)
          let result = arr.filter(item => item > 5)
     箭头函数完整写法=>
           let result = arr.filter((item) => {
                retrun item > 5
           })
③ES5写法=>
     let result = arr.filter(function(item) {
           retrun item > 5
     })

	let arr = ['tom','terry','jacky'];
	//1.普通函数
	let result1 = arr.filter(function (item) {  
	    return item == 'tom';
	})
	//return后产生新的数组
	console.log(result1);//[ 'tom' ]
	//2.箭头函数
	let result2 = arr.filter((item) => {
	    return item  == 'tom';
	})
	console.log(result2); //[ 'tom' ]
	//3.有且只有一条返回语句--->箭头函数的极简形式
	let result3 = arr.filter(item => item=='tom');
	console.log(result3); //[ 'tom' ]
	//箭头函数指向声明时外部作用的this
	let arrowFun = () =>{
	    console.log(this);
	}
	let obj={
	    name:'张三',
	    age:12,
	    gender:'male',
	    // sayName:()=> {
    	//     console.log(this);//{}
    	// },
	    // sayName(){
	    //     return () =>{
	    //         console.log(this);//{} 指向声明时外部作用域的this
	    //     }
	    // },
	    //return后面的箭头函数就相当于前面全局声明的arrowFun函数
	    sayName () {
	        return arrowFun;
	    }
	}
	this.name = 'lisi';
	console.log('全局',this); //全局 { name: 'lisi' }
	//进行新赋值 gender  直接使用module.exports.gender
	module.exports.gender = 'male'; //module.exports { name: 'lisi', gender: 'male' }
	//不能是module.exports给它地址,这样会改变其指向,比如:
	// module.exports = {
	//     a:1,
	//     b:2
	// }
	//console.log('module.exports',module.exports);//module.exports { a: 1, b: 2 }
	// this指向就是当前模块的默认导出
	console.log('module.exports',module.exports);//{ name: 'lisi', gender: 'male' }
	obj.sayName()();//执行obj-->sayName-->arrowFun函数

5.6 迭代器Iterator

(一) 定义
       实现了iterator接口的数据,即是可迭代的数据。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
(二) Iterator 的作用
       (1)为各种数据结构,提供一个统一的、简便的访问接口;
       (2)使得数据结构的成员能够按某种次序排列,通过调用.next()方法,指向下一个成员
       (3)ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费
(三) Iterator 的遍历过程
      1. 创建一个指针对象,指向当前数据结构的起始位置。也就是说这个遍历器对象本质上,就是一个指针对象。
      2. 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
      3. 第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
      4. 不断调用指针对象的next方法,直到它指向数据结构的结束位置。
(四)for of使用,可以遍历实现了iterator接口的数据
      for-of实现原理就是调用迭代器的next()方法,第一次调用将指针指向数据结构的第一个成员,依次调用依次指向,直到没有成员可以指向,done为true
      具体的迭代过程:
            1.创建一个指针对象,指向当前的数据结构起始位置;
            2. 第一次调用指针对象的next方法,指向数据结构的第一个成员;
            3. 第二次调用指针对象的next方法,指向数据结构的第二个成员;
            4. 直到done为true,指向数据结构的结束位置;
       for of 遍历的是键值对中的值
       for in 遍历的是键值对中的键
(五) 访问
       {value: 1, done: false}
       {value: 2, done: false}
       {value: undefined, done: true}
   iterator.next()    通过调用.next方法,可以使迭代器对象中的指针向下移一位
      value有值,done就为false
      value为undefined时,done为true
(六) for of 实现(.next())
(七) 原生具备 Iterator 接口的数据结构如下
       Array、Map、Set、String、arguments、NodeList 等

具体实现:

	let arr1 = ['tom','vicky','jacky'];
	let keys =arr1.keys();
	let values =arr1.values();
	let entries =arr1.entries();
	//1.通过 ".next"  每调用一次就向下指引一次
	console.log(typeof(values.next())); //object对象
	console.log(values.next());//{ value: 'tom', done: false }
	console.log(values.next());//{ value: 'vicky', done: false }
	console.log(values.next());//{ value: 'jacky', done: false }
	console.log(values.next());//{ value: undefined, done: true }
	//当done为true后,不在执行
	// 2.使用while循环   for of循环的重构(实现)  内部工作机制/逻辑
	let item; //保证item是个对象  将value.next取出的值传给item
	//values是迭代对象,执行下一步后,将取出来的值赋值给item,一般情况下,item的值为false,
	//为了整个循环可以执行,对item = values.next()进行取反,然后执行,等到取反为true,执行结束。
	while(!(item = values.next()).done){
	    console.log(item.value);//tom vicky jacky
	}
	//for of循环
	for(let value of values){
	    console.log(value);//tom  vicky  jacky
	}
	for(let entry of entries){
	    console.log(entry);//[ 0, 'tom' ]  [ 1, 'vicky' ]  [ 2, 'jacky' ]
	}

5.7 Set集合

  5.7.1 定义

       set 类似于数组,但是成员的值都是唯一的,没有重复的值。set 本身是一个构造函数,用来生成 set 数据结构展。set 构造函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。

  5.7.2 特性

        不允许重复值出现
        应用:数组去重 Array.form(new Set(arr))
        数组去重方法: https://blog.youkuaiyun.com/hey_myx/article/details/120536673

  5.7.3 API

set.prototype.size 返回Set实例的成员总数。
set.prototype.add(value) 添加某个值,返回Set结构本身
set.prototype.delete(value) 删除某个值,返回一个布尔值,表示删除是否成功。
set.prototype.has(value) 返回一个布尔值,表示该值是否为Set的成员。
set.prototype.clear() 清除所有成员,没有返回值。
set.prototype.keys() 返回键名的遍历器
set.prototype.values() 返回键值的遍历器
set.prototype.entries() 返回键值对的遍历器
set.prototype.forEach() 使用回调函数遍历每个成员

对set-API具体实现如下:

	//数组去重
	let arr= [1,2,3,5,4,3,2,1,3,1];
	let set = new Set(arr);
	//添加值
	set.add(100);
	//console.log(set);//未添加值前 Set(5) { 1, 2, 3, 5, 4 }
	console.log(Array.from(set));//[ 1, 2, 3, 5, 4 ,100]
	console.log(set.size); //6
	console.log(set.delete(1));//删除1
	console.log(set.has(1));//检测是否还有1
	// console.log(set.clear());//清除所有对象
	console.log(set);//Set(5) { 1, 2, 3, 5, 4 ,100}
	let keys =set.keys();
	let values =set.values();
	let entries =set.entries();
	//console.log(entries.next());//{ value: [ 2, 2 ], done: false }
	//这里的forEach保存在set.prototype原型中  ,数组中的保存在数组原型中
	set.forEach((value)=>{
	    console.log(value);
	})

5.8 Map集合

  5.8.1 定义

       类似于对象,key-value对应的集合。也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。Map 可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。

  5.8.2 特点

          key值不局限于字符串,可以是任意数据类型

  5.8.3 API

Map.prototype.size 返回 Map 结构的成员总数。
Map.prototype.set(key, value) set方法设置键名key对应的键值为value,然后返回整个map结构。如果key已经有值,则键值会被更新,否则就新生成该键。
Map.prototype.get(key) get方法读取key对应的键值,如果找不到key,返回undefined。
Map.prototype.has(key) has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
Map.prototype.delete(key)delete方法删除某个键,返回true。如果删除失败,返回false。
Map.prototype.clear() 清除所有成员,没有返回值
Map.prototype.keys() 返回键名的遍历器
Map.prototype.values() 返回键值的遍历器
Map.prototype.entries() 返回键值对的遍历器
Map.prototype.forEach() 使用回调函数遍历每个成员

对map-API的具体实现如下:

	let obj1 = {
	    name:'张三',
	    age:12,
	    gender:'male'
	}
	let map = new Map(Object.entries(obj1));
	map.set(true,0);  //true => 0,
	map.set({a:1,b:2},['tom','jacky']);//{ a: 1, b: 2 } => [ 'tom', 'jacky' ]
	console.log(map.size);//5
	console.log(map.get(true));//0
	console.log(map);//Map(3) { 'name' => '张三', 'age' => 12, 'gender' => 'male' )
	map.forEach((value,key)=>{
	    console.log(value,key);
	})

5.9 class类

  5.9.1 介绍

    ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。ES6 的class可以看作是构造函数或者一个语法糖。
语法糖:
    具有特殊功能的代码写法,内部封装了一些方法,让一些复杂代码的编写及其用法变得简单。

  5.9.2 构造器

        constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加

class Person{   }      =>         class Person{
                                      constructor(){}
                                  }
  5.9.3 实例方法、属性

        定义在类体中的方法称为实例方法。本质上该方法应该是声明在Person.prototype中,可供所有的实例调用,因此称为实例方法。
        以上概念的具体实现:

	// 定义一个类
	class Person{
	    //静态属性  使用static关键字修饰
	    static weight = "50KG"
	    // 类的默认方法constructor  显式添加  调用添加的构造器
	    constructor(name,age,gender){
	        // 维护实例的私有属性
	        this.name=name;
	        this.age=age;
	        this.gender=gender;
	    }
	    // 其实是存放在构造器函数的原型对象当中的
	    // 公有方法--供每个方法去使用
	    // 对于实例方法  不需要任何关键字修饰
	    sayName(){
	        //this.name  实例来调用sayName
	        console.log('my name is',this.name);
	    }
	    //静态方法  使用static关键字修饰
	    static sayWeight(){
	        console.log('my weight is',this.weight);
	    }
	}
	// 实例化  传递实例的属性值
	let tom = new Person('tom',20,'男');
	console.log(tom);//Person { name: 'tom', age: 20, gender: '男' }
	tom.sayName();//my name is tom
	//通过class类  调用静态属性和方法
	console.log(Person.weight);//50KG
	Person.sayWeight();//my weight is 50KG
  5.9.4 静态方法、属性

        通过static关键字来定义静态属性和静态方法。静态属性和静态方法是定义在类【构造函数】上的,所以可以通过类【构造函数】直接访问。在静态方法中,this指向当前类【构造函数】。

	// 实例方法实例属性写在哪
	    // 实例方法和属性可以由类构造函数创建的实例调用呀
	// 静态属性和静态方法写在哪
	    // 类构造函数调用
	class Person{
	    // 实例属性  实例方法
	    constructor(name){
	         // 维护实例的私有属性
	         this.name=name;
    	}	
	    // 实例的私有属性
	    test=['hello'];
	    sayName(){
	        console.log(this.name);
	    }
	   // 静态属性
	    static personAttr='hello';
	    // 静态方法
	    static personMethod(){
	        console.log('我是静态方法');
	    }
	}
	let p=new Person();
	let p1=new Person();
	p.test.push('hello');//私有的  只能给p添加
	console.log(p);
	console.log(p1,'-------------');
	// 静态属性和静态方法只能有类属性来调用
	console.log(Person.personAttr);
	console.log(Person.personMethod());
  5.9.5 继承(★)
      ①ES5继承
	实例使用属性和方法
	  1.从实例对象本身查找属性或者方法
	  2.如果实例没有,从构造函数的原型对象中找
	  3.如果还没有,从父构造函数的原型对象中找
	1.经典继承又称构造函数继承
	function Animal(type,age,weight){
	    this.type=type;
	    this.age=age;
	    this.weight=weight;
	}
	Animal.prototype={
	    constructor:Animal,
	    sayType:function(){
	        console.log(this.type);
	    }
	}
	function Dog(type,age,weight,name,color){
	        // 经典继承又称为构造函数继承
	        Animal.call(this,type,age,weight);
	        this.name=name;
	        this.color=color;
	}
	处理完构造函数处理原型对象
	2.原型链继承
	//子构造函数的原型指向父构造函数的原型对象
	Dog.prototype=new Animal();
	Dog.prototype.constructor=Dog;
	Dog.prototype.sayColor=function(){
	    console.log(this.color);
	}
	var d1=new Dog('狗',1,'10kg','40cm','可乐','white');
	console.log(d1);//Dog {type:'狗', age:1, weight:'10kg', length:'40cm', name:'可乐', color:'white'}
	d1.sayType();
	d1.sayColor();
       ②ES6继承

        class可以通过extends关键字实现继承,子类可以没有构造函数,系统会默认分配。子类提供了构造函数则必须要显式调用super

	// 类是一个对象  父类构造函数
	class Animal{
	    // 约束静态属性
	    static animalAttr = 'Animal静态属性';
	    constructor(name,age){
	        this.name =name;
	        this.age=age;  
	        // console.log('这是父构造器');
	    }
	    animalFun(){
	        console.log('Animal实例方法');
	    }
	    static animalStaFun(){
	        console.log('Animal静态方法');
	    }
	}	
	// 子类构造函数继承自Animal
	class Dog extends Animal{
	    constructor(name,age,color,weight){
	        super(name,age);//传继承属性
	        this.color=color;
	        this.weight=weight;
	        // console.log('这是子类构造器');
	    }
	}
	//1.继承Animal类的实例属性和实例方法   原型链继承
	let dog = new Dog('二狗',1,'black','10kg');
	console.log(dog); //Dog { name: '二狗', age: 1, color: 'black', weight: '10kg' }
	// 1.继承  子类的原型对象继承自父类的原型对象
	dog.animalFun(); //Animal实例方法
	
	// 调用静态方法  --只能由类构造函数去调用
	// 2.继承  子类的对象指向父类的对象
	// 2.继承Animal类的静态属性和静态方法  构造函数继承
	console.log(Dog.animalAttr);//Animal静态属性  Animal静态方法
	Dog.animalStaFun();
	
	// 验证
	// 子类的原型对象继承自父类的原型对象
	console.log(Dog.prototype.__proto__ === Animal.prototype);//true
	console.log(dog.__proto__.__proto__ === Animal.prototype);//true
	// 类的对象指向父类的对象
	console.log(Dog.__proto__ === Animal);//true

5.10 Symbol

  5.10.1 介绍

        ES6 引入的一种新的原始数据类型Symbol,表示独一无二的值。Symbol函数可以接受参数,表示对于这个唯一值的描述。

  5.10.2 使用
	Symbol()函数会返回symbol类型(基本数据类型)的值
	    let s = Symbol()
	    typeof s ;	//’symbol’
	    symbol类型的值是独一无二的
	  在对象中使用symbol
	    用于对象的属性名,就能保证不会出现同名的属性。
	    这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖
	    let sy1 = Symbol();
	    obj[sy1] = 'hello'
	    let obj2 = {
	      ...obj1,
	      // key为变量时,需要用[]包裹
	      [sy1]: 'world'
	    }

具体实现:

	// Symbol用于对象的属性名,就能保证不会出现同名的属性,symbol值代表独一无二的值
	//传的参数是对结果的描述
	let sy1 =Symbol("sy1");
	let sy2 =Symbol("sy2");
	console.log(sy1,sy2);//Symbol(sy1) Symbol(sy2)
	console.log(sy1 ===sy2);//false
	console.log(typeof sy1);//symbol 基本数据类型
	let obj1={
	    name:'zs',
	    age:12,
	    gender:'male',
	    //解决key值冲突,可以使用symbol值,作为一个唯一的值   对key需要加[] 
	    [sy1]:'zhangsan'
	}
	console.log(obj1[sy1]);//zhangsan
  5.10.3 Symbol.for(key)
Symbol()不同的是,用Symbol.for()方法创建的symbol会被放入一个全局symbol注
册表中。并不是每次都会创建一个新的symbol,它会首先检查给定的 key 是否已经在注册表中了。
假如是,则会直接返回上次存储的那个。否则,它会再新建一个。
     比如:调用Symbol.for("cat")30次,每次都会返回同一个Symbol值,但是如果调用
Symbol("cat")30 次,会返回 30 个不同的 Symbol 值。如果想要用同一个变量,可以使用
Symbol.for('name')注册一个全局的,下次如果要获取该symbol值,则再次Symbol.for
('name')
  5.10.4 Symbol.keyFor(sy1)

        检测symbol值是否在全局登记过,返回key或者undefined。
        返回一个已登记的Symbol类型值的key,用来检测该字符串参数作为名称的Symbol值是否已被登记。

	//1.Symbol()
	let sy1= Symbol('one');
	let sy2= Symbol('one');
	console.log(sy1,sy2);//Symbol(one) Symbol(one)
	console.log(sy1 === sy2);//false
	//2.Symbol.for()
	let sy3 = Symbol.for('two');//第一次查找没有直接创建
	let sy4 = Symbol.for('two');//第二次查找直接获取
	console.log(sy3,sy4);//Symbol(two) Symbol(two)
	console.log(sy3 == sy4);//true
	//3.Symbol.keyfor  
	console.log(Symbol.keyFor(sy1));//undefined
	//undefiend  --》表示并不是在全局中注册
	console.log(Symbol.keyFor(sy2));//undefined
	console.log(Symbol.keyFor(sy3));//two
	console.log(Symbol.keyFor(sy4));//two
	
 eg:
	// 1.根据Symbol值去拿key
	let key = Symbol.keyFor(sy3);
	//2.根据key去找值
	let value  =Symbol.for(key);
	//3.判断是否相等
	console.log(value == sy3);//true
  5.10.5 应用:消除魔术字符串:

        魔术字符串指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。
        风格良好的代码,应该尽量消除魔术字符串,改由含义清晰的变量代替。

	//将字符串全部都提到一起  
	let shapes = {
	    // 这里必须保证每一项的value值不一样,所以使用到了Symbol
	    SJX:Symbol("三角形"),
	    JX:Symbol("矩形"),
	    YX:Symbol("圆形")
	}
	function computedArea(shape,options) {
	    let result = 0;
	    switch (shape) {
	        case shapes.SJX:
	            result = .5*options.width*options.height;
	            break;
	        case shapes.JX:
	            result = options.width * options.height;
	            break;
	        case shapes.YX:
	            result = Math.PI * options.r * options.r;
	            break;
	        default:
	            result = -1;
	            break;
	    }
	    return result;  
	}
	console.log(computedArea(shapes.SJX,{width:10,height:10}));

6 Js严格模式

6.1 严格模式的优缺点

    优点
        提高代码解析和运行速度;
        禁用了一些不合理的语法,减少了代码的怪异行为;
        消除代码运行的一些不安全之处,保证代码运行的安全;
        为未来新版本的Javascript做好铺垫。
    缺点
        某些代码在严格模式下会报错,尤其引入公用与第三方模块的时候需要注意;
        有些严格模式的特性在不同浏览器的支持情况不同,需要注意兼容问题;

6.2 严格模式与非严格模式区别

        区别参考1
        区别参考2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值