参考链接:https://www.jianshu.com/p/87008f4f8513,

https://www.cnblogs.com/20gg-com/p/6687443.html?utm_source=itdadao&utm_medium=referral

参考内容:妙味课堂

let、const

let 定义的变量不会被变量提升,const 定义的常量不能被修改,let const 都是块级作用域

ES6前,是var命名变量,有“预编译”功能(变量会先赋值为undefined),js 是没有块级作用域 {} 的概念的。(有函数作用域、全局作用域、eval作用域)

ES6后,let 和 const 的出现,js 也有了块级作用域的概念,前端的知识是日新月异的~

变量提升:在ES6以前,var关键字声明变量。无论声明在何处,都会被视为声明在函数的最顶部;不在函数内即在全局作用域的最顶部。这样就会引起一些误解。例如:

<script>console.log(a); // undefinedvar a = 'hello1';// 上面的代码相当于,即预编译var a;console.log(a);  //hello1a = 'hello1';// 而 let 就不会被变量提升;且不能重复对同一变量声明赋值,可以写成 a='hello',但不能let声明console.log(a); // hello1//报错,SyntaxError: Identifier 'a' has already been declareda = 'hello2';let a = 'hello2';
</script>
<script>console.log(a);    //undefinedvar a = 1;a = 1000;var a = 300;console.log(a);    //300{var a = 1;}console.log(a)        //1
</script>
<script>{let b = 100;console.log(b);  //100}console.log(b)    //b is not defined
</script>
<script>    console.log(b);//ReferenceError: Cannot access 'b' before initializationlet b = 2;let b = 200;// Identifier 'b' has already been declaredconsole.log(b);
</script>

const 定义的常量不能被修改

<script>var name = "bai";name = "ming1";console.log(name); // ming1const name = "bai";name = "ming2"; // Assignment to constant variable.console.log(name);
</script>
<script>
//var 可以重复对同一变量修改赋值,  let则不可以var x = 10;x = 30;console.log(x);//const可以重复对同一变量修改赋值const c = 3.14;c = 10;console.log( c )// Assignment to constant variable.//不可以直接对对象赋值,但可以对它声明属性并赋值const obj = {};// obj = 1obj.name = "kimoo";console.log( obj )       //{name: "kimoo"}
</script>

importexport

import导入模块、export导出模块

<script>// 全部导入import people from './example'// 将整个模块当作单一对象进行导入,该模块的所有导出都会作为对象的属性存在import * as example from "./example.js"console.log(example.name)console.log(example.getName())// 导入部分,引入非 default 时,使用花括号import {name, age} from './example'// 导出默认, 有且只有一个默认export default App// 部分导出export class App extend Component {};</script>

classextendssuper

ES5中最令人头疼的的几个部分:原型、构造函数,继承,有了ES6我们不再烦恼!

ES6引入了Class(类)这个概念。

<script>class Animal {constructor() {this.type = 'animal';}says(say) {console.log(this.type + ' says ' + say);}}let animal = new Animal();animal.says('hello'); //animal says helloclass Cat extends Animal {constructor() {super();this.type = 'cat';}}let cat = new Cat();cat.says('hello'); //cat says helloclass Person{constructor(name,age){this.name = name;this.age = age;}say(){console.log( "我叫"+this.name+"今年,"+this.age )}eat(){console.log( "eat...." )}}var p1 = new Person( "kimoo",27 );console.log( Person.prototype ); //{constructor: ƒ, say: ƒ, eat: ƒ}
//      Person("kimoo",27)//出错</script>
<script>class Person{constructor(name,age){this.name = name;this.age = age;}//加上static将变成静态方法或静态属性,必须用 父类. 来调用,如(Person.sex,Person.isHuman(1))static isHuman( obj ){return obj instanceof Person}static sex = 'man';say(){console.log( "我叫"+this.name+"今年,"+this.age )}eat(){console.log( "eat...." )}}//添加静态属性Person.staticProps = "miaov";console.log( Person.sex );                //manconsole.log( Person.staticProps )      //miaovvar p1 = new Person( "kimoo",27 );    // p1.say();// p1.isHuman();// 静态方法,报错console.log( Person.isHuman( 1 ) );        //falseconsole.log( Person.isHuman( p1 ) ); //true// var str = "妙";// console.log( str.charCodeAt(0) ) //22937// console.log( String.fromCharCode( 22937 ) ) </script>
<script>class Person{constructor(name,age){this.name = name;this.age = age;}static isHuman( obj ){// console.log( "isHuman" )return obj instanceof Person}say(){console.log( "我叫"+this.name+"今年,"+this.age );}eat(){console.log( "eat...." );}}//继承必须加super()继承父级属性,class Coder extends Person{constructor(name,age,money){super(name,age);this.money = money;}say(){console.log( "我叫"+this.name+"今年,"+this.age+",一月赚"+this.money );}}var c1 = new Coder("zm",30,30000);console.log( c1 );      //Coderc1.say();                //我叫zm今年,30,一月赚30000console.log( Coder.isHuman( c1 ) );     //true//继承不会改写原先父级的方法var p1 = new Person("momo",20);console.log( p1 );       //Personp1.say();               //我叫momo今年,20
</script>

上面代码首先用class定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。简单地说,constructor内定义的方法和属性是实例对象自己的,而constructor外定义的方法和属性则是所有实力对象可以共享的。Class之间可以通过extends关键字实现继承,这比ES5的通过修改原型链实现继承,要清晰和方便很多。上面定义了一个Cat类,该类通过extends关键字,继承了Animal类的所有属性和方法。super关键字,它指代父类的实例(即父类的this对象)。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。ES6的继承机制,实质是先创造父类的实例对象this(所以必须先调用super方法,写在第一行),然后再用子类的构造函数修改this。

<script>// ES5var Shape = function(id, x, y) {this.id = id,this.move(x, y);};Shape.prototype.move = function(x, y) {this.x = x;this.y = y;};var Rectangle = function id(ix, x, y, width, height) {Shape.call(this, id, x, y);this.width = width;this.height = height;};Rectangle.prototype = Object.create(Shape.prototype);Rectangle.prototype.constructor = Rectangle;var Circle = function(id, x, y, radius) {Shape.call(this, id, x, y);this.radius = radius;};Circle.prototype = Object.create(Shape.prototype);Circle.prototype.constructor = Circle;// ES6class Shape {constructor(id, x, y) {this.id = id;this.move(x, y);}move(x, y) {this.x = x;this.y = y;}}class Rectangle extends Shape {constructor(id, x, y, width, height) {super(id, x, y) this.width = width this.height = height;}}class Circle extends Shape {constructor(id, x, y, radius) {super(id, x, y) this.radius = radius;}}</script>

解构赋值

<script>var obj = {name: "kim",age: 28,c:undefined,a: 1,b: 2};var {a,b,...r} = obj;console.log(r)/*Objectage: 28c: undefinedname: "kim"*///r 可以任意写,表示从除了a,b以外其他的属性值//普通取值var name = obj.name;var age = obj.age;console.log( name,age );     //kim 28//对对象里的属性取值,但以下方式取出来的属性名仍然是对象里的属性名var {name, age} = obj;console.log( name,age );        //kim 28var name = "";({name} = obj);console.log( name );       //kim//以下方式可以赋值改名字var { name: str } = obj;console.log( str,name ); //kim kimconsole.log( typeof str ); //string//以下方式给默认值,即对象中没有或undefined,则使用默认值var {c=100} = obj;console.log(c); //100//赋值并给默认值var {gender:g="male"} = obj;console.log(g);   //male//数组也与上面json一样var arr = "miaov".split("");var f = arr[0];var s = arr[1];console.log(f,s);  //m i//不取值可以写逗号var [f,s,,fouth] = arr; console.log(f,s,fouth); //m i oarr[0] = undefined;console.log(arr);        // [undefined, "i", "a", "o", "v"]//数组同样可以用默认值var [ a="123456",b,c ] = arr;console.log(a,b,c);  //123456 i avar [a="879",b,c,...r] = arr;console.log( a,b,c,r ) //879 i a ["o", "v"]</script>

函数

<script>
/*   function add( a,b ){||前面出现0与undefined时,会跳到后面// var _b = b || 100;var _b = b === undefined ? 100 : b;return a+_b;}*/function add( a,b=100 ){return a+b;}console.log( add( 10 ) ) // 110console.log( add( 10,5 ) ) // 15console.log( add( 10,0 ) ) // 10console.log( add( 10,undefined ) ) // 110//----------------------------------------------function fn( a,b, ...r ){
//      console.log( a,arguments );console.log( r );        // [3, 4, 5]}fn(1,2,3,4,5)/*function add(a,b){return a+b}*///箭头函数省略function,若是return输出,则可以省略return和{}// var add = (a,b)=>{return a+b}//若是return输出,则可以省略return和{}// var add = (a,b)=>a+b//         若想输出对象,则需加()var add = (a,b)=>({miaov: 3})console.log( add );      //(a,b)=>({miaov: 3})//若没有加(),则会变成表达式标签var add = (a,b)=>{miaov: for( var i = 0;i<10;i++ ){console.log( i )if( i==3 ){break miaov;}}}//若只有一个参数时,可以把(a)写成a,省略()。但如果没有传参数时,必须写()var add = a=> a*100console.log( add(2) )//.filter => 过滤var arr = [10,2,31,48,15,6];// var res = arr.filter( function(item){//    return item > 20// } );var res = arr.filter( item=>item > 20 )console.log( res )//----------------------------------------------//箭头函数可以用...var fn = (...r)=>{console.log( this )   //Window
//      console.log( arguments );//arguments is not definedconsole.log( r );    //[MouseEvent]}//箭头函数,this在编写时已确定指向,不会因为谁调用而指向谁
/*   var fn = function(){console.log( this )}*/
/*   var fn = () =>{console.log( this );}fn(1,2,3) fn.bind({a:1});   .bind()依然无法修改this指向*/document.onclick = fn;//箭头函数不能new,没有arguments// var obj = new fn();
</script>

arrow functions (箭头函数)

函数的快捷写法。不需要 function 关键字来创建函数,省略 return 关键字,继承当前上下文的 this 关键字

<script>// ES5var arr1 = [1, 2, 3];var newArr1 = arr1.map(function(x) {return x + 1;});// ES6let arr2 = [1, 2, 3];let newArr2 = arr2.map((x) => {x + 1});
</script>

箭头函数小细节:当你的函数有且仅有一个参数的时候,是可以省略掉括号的;当你函数中有且仅有一个表达式的时候可以省略{}

<script>let arr2 = [1, 2, 3];let newArr2 = arr2.map(x => x + 1);
</script>

JavaScript语言的this对象一直是一个令人头痛的问题,如setTimeout中的this指向的是全局对象。

<script>class Animal {constructor() {this.type = 'animal';}says(say) {setTimeout(function() {console.log(this.type + ' says ' + say);}, 1000);}}     var animal = new Animal();animal.says('hi'); //undefined says hi
</script>

解决办法:

<script>class Animal {constructor() {this.type = 'animal';}// 传统方法1: 将this传给self,再用self来指代thissays(say) {var self = this;setTimeout(function() {console.log(self.type + ' says ' + say);}, 1000);}// 传统方法2: 用bind(this),修改this指向,即says(say) {setTimeout(function() {console.log(this.type + ' says ' + say);}.bind(this), 1000);}// ES6: 箭头函数// 当我们使用箭头函数时,函数体内的this对象,就是定义时所在的对象says(say) {setTimeout(() => {console.log(this.type + ' says ' + say);}, 1000);}}var animal = new Animal();animal.says('hi');</script>

字符串

<script>var str = "miaovketang";console.log( str.indexOf("ke") !== -1 );    //true//includes() => 检查字符串中是否包括console.log( str.includes("zzz") );       //false//startsWith() => 以()开头console.log( str.startsWith("miao") );        //trueconsole.log( str.startsWith("iao") );       //false//endsWith => 以()结尾console.log( str.endsWith("tang") );      //trueconsole.log( str.endsWith("tan") );     //false//repeat() => 重复打印()遍var str = "miaovketang |";console.log( str.repeat(3) );        //miaovketang |miaovketang |miaovketang |console.log( str );                //miaovketang |//``超级运算符,里面可传参${},可以回车,空格不会报错;还可以三目运算,调用函数var classStr = "yellow"var html = `<ul><li class="red"></li>
<li class='green'></li>
<li class='${classStr}'></li></ul>`console.log( html )var n = 2;var m = 3;console.log( "n+m="+(n+m) )  console.log( `n+m=${n+m}` )var isRaining = falseconsole.log( `今天天气是 ${ isRaining?"雨天":"晴天" }` )function fn(){return "miaov"}console.log( `fn执行结果是 : ${ fn() }` )
</script>

template string (模板字符串)

解决了 ES5 在字符串功能上的痛点。

第一个用途:字符串拼接。将表达式嵌入字符串中进行拼接,用 ` 和${}`来界定。

<script>// es5var name1 = "bai";console.log('hello' + name1);    //hellobai// es6const name2 = "ming";console.log(`hello${name2}`); //helloming
</script>

第二个用途:在ES5时我们通过反斜杠来做多行字符串拼接。ES6反引号 `` 直接搞定。

<script>// es5var msg = "Hi \man!";// es6const template = `<div><span>hello world</span></div>`;console.log(msg);        //Hi man!console.log(template); /*<div><span>hello world</span></div>*/
</script>

另外:includes repeat

<script>// includes:判断是否包含然后直接返回布尔值let str = 'hahah';console.log(str.includes('y')); // false// repeat: 获取字符串重复n次let s = 'he';console.log(s.repeat(3)); // 'hehehe'
</script>

destructuring (解构)

简化数组和对象中信息的提取。

ES6前,我们一个一个获取对象信息;

ES6后,解构能让我们从对象或者数组里取出数据存为变量

<script>// ES5var people1 = {name: 'bai',age: 20,color: ['red', 'blue']};var myName = people1.name;var myAge = people1.age;var myColor = people1.color[0];console.log(myName + '----' + myAge + '----' + myColor);//bai----20----red// ES6let people2 = {name: 'ming',age: 20,color: ['red', 'blue']}//解构let { name, age } = people2;let [first, second] = people2.color;console.log(`${name}----${age}----${first}`);//ming----20----red
</script>

default 函数默认参数

<script>// ES5 给函数定义参数默认值function foo(num) {num = num || 200;return num;}// ES6function foo(num = 200) {return num;}
</script>

rest arguments rest参数)

解决了 es5 复杂的 arguments 问题

<script>//继承也可以用...function foo(x, y, ...rest) {console.log((x + y) * rest.length)return ((x + y) * rest.length);}foo(1, 2, 'hello', true, 7); // 9
</script>

Spread Operator (展开运算符)

第一个用途:组装数组

<script>let color = ['red', 'yellow'];let colorful = [...color, 'green', 'blue'];console.log(colorful); // ["red", "yellow", "green", "blue"]
</script>

第二个用途:获取数组除了某几项的其他项

<script>let num = [1, 3, 5, 7, 9];//解构let [first, second, ...rest] = num;console.log(rest); // [5, 7, 9]
</script>

对象

对象初始化简写

<script>// ES5function people(name, age) {return {name: name,age: age};}// ES6function people(name, age) {return {//当键名与键值相同时,可省略name,age};}
</script>

对象字面量简写(省略冒号与 function 关键字)

<script>// ES5var people1 = {name: 'bai',getName: function () {console.log(this.name);}};// ES6let people2 = {name: 'bai',getName () {console.log(this.name);}};
</script>

另外:Object.assign()

ES6 对象提供了Object.assign()这个方法来实现浅复制。Object.assign()可以把任意多个源对象自身可枚举的属性拷贝给目标对象,然后返回目标对象。第一参数即为目标对象。在实际项目中,我们为了不改变源对象。一般会把目标对象传为{}

<script>objA = {a:1}objB = {b:2}const obj = Object.assign({}, objA, objB) console.log(obj)  //{a: 1, b: 2}// 给对象添加属性this.seller = Object.assign({}, this.seller, response.data)
</script>

Promise

用同步的方式去写异步代码

<script>// 发起异步请求fetch('/api/todos').then(res => res.json()).then(data => ({data})).catch(err => ({err}));//Promise 封装异步请求demoexport default function getMethods (url){return new Promise(function(resolve, reject){axios.get(url).then(res => {resolve(res)}).catch(err =>{reject(err)})})}getMethods('/api/xxx').then(res => {console.log(res)}, err => {console.log(err)})
</script>
<script>   // 异步编程解决方案var p = new Promise( ( resolve,reject )=>{console.log( "实例化..." );        //实例化...return resolve("成功!");reject();console.log( "222" );} );console.log( p )        //Promise {<resolved>: "成功!"}/*  __proto__: Promise[[PromiseStatus]]: "resolved"[[PromiseValue]]: "成功!"*/p.then( ( data )=>{console.log( "then: ",data )   //then:  成功!} )//主任务,隐式任务,队列     console.log( 1 );setTimeout( ()=>{console.log( 3 );} )setTimeout( ()=>{console.log( 4 );} )var p = new Promise( (res,rej)=>{console.log( 5 )res()} )p.then( ()=>{ console.log( 6 )} )console.log( 2 );
//打印顺序:1,5,2   6   3,4</script>
<script>var p = new Promise( (res,rej)=>{res("成功")
//               rej();} )p.then( (data)=>{console.log( data + "这里" )        //res表成功,会传递数据 =>成功这里},()=>{console.log( "失败" + "走这里" ) //rej表失败,不会传递数据 =>失败走这里} )//         .catch是then的第二个参数,表失败p.catch( ()=>{console.log( "失败" + "来吧")        //rej表失败,不会传递数据 =>失败走这里} )var p2 = p.then( (data)=>{console.log( data + "在哪呢")   //es表成功,会传递数据 =>成功在哪呢} )console.log( p2 === p )       //false
</script>
<script>var p = new Promise( (res,rej)=>{res("成功")} )var p2 = p.then( ()=>{ return new Promise( (res,rej)=>{rej(111)} ) } );//Uncaught (in promise) 111//返回状态为rejected,值为222,但报错,应用.catch方法var p2 = p.catch( ()=>{ return new Promise( (res,rej)=>{rej(222)} ) } );//返回状态为resolved,值为"成功",不是222var p2 = p.then( ()=>{ return new Promise( (res,rej)=>{res(333)} ) } )//返回状态为resolved,值为333console.log( p2 )p2.then( data=>{console.log( "p2 then: ",data )} )
</script>
<script>var p = new Promise( (res,rej)=>{res("成功")} )   var res =  p.then( ()=>{console.log( 1 )} ).then( ()=>{console.log( 2 )//a//不注释a此处出错,不会执行下个then,即不会打印出3} ).then( ()=>{console.log( 3 )b} )//捕获异常,不会报错.catch( (err)=>{console.log( err )   //ReferenceError: b is not defined} )//.finally结束语句.finally( ()=>{console.log( "执行完了..." )    //finally是无论程序对错,一定会走这里} )           console.log( 333 )/*    输出结果为:333123ReferenceError: b is not defined执行完了...*/
</script>
<script>var p = new Promise( (res,rej)=>{res()} )p.then( ()=>{ console.log(1) } ).then( ()=>{ return new Promise( (res,rej)=>{res(200)} ) } ).then( (data)=>{ return Promise.resolve( data) })    //调用.resolve可省略new Promise( (res,rej)=>{res(...)} ),要么res,要么rej.then( ()=>{ return Promise.reject( "失败!" ) }) //调用.reject可省略new Promise( (res,rej)=>{rej(...)} ).then( (data)=>{ console.log(data+"跑这里了") } )   .catch( (err)=>{ console.log( err+"这里这里" ) } )/* 打印结果:1 200跑这里打开Promise.reject("失败:")会覆盖.resolve这一状态,结果变成了1 失败!这里这里*/
</script>
<script>var p1 = new Promise( (res,rej)=>{setTimeout( ()=>{res("a")},1000 )} )var p2 = new Promise( (res,rej)=>{setTimeout( ()=>{res("b")},1500 )} )var p3 = new Promise( (res,rej)=>{setTimeout( ()=>{res("c")},500 )} )//   var p = Promise.all( [p1,p2,p3] ); //all()一起执行完再打印 ["a", "b", "c"]var p = Promise.race( [p1,p2,p3] );       //.race()时间最快的  cconsole.log( p )       //Promise {<pending>}p.then( data=>console.log( data ) )
</script>
//promise运动实例
<script>/* function move( obj,attr,target,duration,callback ){var b = parseInt(getComputedStyle(obj)[attr]);var c = target - b; var d = duration;var temp = new Date().getTime();var timer = setInterval( function(){var t = new Date().getTime()-temp;if( t >= d ){clearInterval( timer );t = d;}var v = c/d*t+b ;obj.style[attr] = v + "px";if( t === d ){typeof callback === "function" && callback();}},20 )}move( box,"width",200,500,()=>{move( box,"height",300,500,()=>{move( box,"left",300,500,()=>{move( box,"top",200,500)})})} )*/var box = document.getElementById( 'box' );function movePromise( obj,attr,target,duration ){return new Promise( (res,rej)=>{var b = parseInt(getComputedStyle(obj)[attr]);var c = target - b; var d = duration;var temp = new Date().getTime();var timer = setInterval( function(){var t = new Date().getTime()-temp;            var v = c/d*t+b ;obj.style[attr] = v + "px";if( t >= d ){clearInterval( timer );res();}},20 )} )}movePromise( box,"width",200,500 ).then( ()=>movePromise( box,"height",300,1000 ) ).then( ()=>movePromise( box,"left",300,1000 ) ).then( ()=>movePromise( box,"top",200,1000 ) ).then( ()=>console.log( "done" ) )
</script>

Generators

生成器( generator)是能返回一个迭代器的函数。

生成器函数也是一种函数,最直观的表现就是比普通的function多了个星号*,在其函数体内可以使用yield关键字,有意思的是函数会在每个yield后暂停。这里生活中有一个比较形象的例子。咱们到银行办理业务时候都得向大厅的机器取一张排队号。你拿到你的排队号,机器并不会自动为你再出下一张票。也就是说取票机“暂停”住了,直到下一个人再次唤起才会继续吐票。

迭代器:当你调用一个generator时,它将返回一个迭代器对象。这个迭代器对象拥有一个叫做next的方法来帮助你重启generator函数并得到下一个值。next方法不仅返回值,它返回的对象具有两个属性:done和value。value是你获得的值,done用来表明你的generator是否已经停止提供值。继续用刚刚取票的例子,每张排队号就是这里的value,打印票的纸是否用完就这是这里的done。

<script>// 生成器function *createIterator() {yield 1;yield 2;yield 3;}// 生成器能像正规函数那样被调用,但会返回一个迭代器let iterator = createIterator();console.log(iterator.next().value); // 1console.log(iterator.next().value); // 2console.log(iterator.next().value); // 3
</script>

迭代器对异步编程作用很大,异步调用对于我们来说是很困难的事,我们的函数并不会等待异步调用完再执行,你可能会想到用回调函数,(当然还有其他方案比如Promise比如Async/await)。生成器可以让我们的代码进行等待。就不用嵌套的回调函数。使用generator可以确保当异步调用在我们的generator函数运行一下行代码之前完成时暂停函数的执行。

那么问题来了,咱们也不能手动一直调用next()方法,你需要一个能够调用生成器并启动迭代器的方法。就像这样子的:

<script>function run(taskDef) {// taskDef 即一个生成器函数// 创建迭代器,让它在别处可用let task = taskDef();// 启动任务let result = task.next();// 递归使用函数来保持对 next() 的调用function step() {// 如果还有更多要做的if (!result.done) {result = task.next();step();}}     // 开始处理过程step();}
</script>

js 中 Map/Set 集合

Map(一)

Map是一组键值对的结构,具有极快的查找速度。

举个例子,假设要根据同学的名字查找对应的成绩,如果用Array实现,需要两个Array

var names = ['Michael', 'Bob', 'Tracy'];
var scores = [95, 75, 85]; 

给定一个名字,要查找对应的成绩,就先要在names中找到对应的位置,再从scores取出对应的成绩,Array越长,耗时越长。

如果用Map实现,只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢。用JavaScript写一个Map如下:

var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
m.get('Michael'); // 95 

初始化Map需要一个二维数组,或者直接初始化一个空MapMap具有以下方法:

var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined

由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉:

var m = new Map();
m.set('Adam', 67);
m.set('Adam', 88);
m.get('Adam'); // 88 

Set(一)

SetMap类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set中,没有重复的key。

要创建一个Set,需要提供一个Array作为输入,或者直接创建一个空Set

var s1 = new Set(); // 空Set
var s2 = new Set([1, 2, 3]); // 含1, 2, 3 

重复元素在Set中自动被过滤:

var s = new Set([1, 2, 3, 3, '3']);
s; // Set {1, 2, 3, "3"} 

注意数字3和字符串'3'是不同的元素。

通过add(key)方法可以添加元素到Set中,可以重复添加,但不会有效果:

<script>var s = new Set([1, 2, 3, 3, '3']);s.add(4)console.log( s )
/*  0: 11: 22: 33: "3"4: 4length: 5*/s.add(4)console.log( s )//Set(5) {1, 2, 3, "3", 4}
</script>

通过delete(key)方法可以删除元素

Map(二)

<script>var obj = {name: "miaov"};var momo = {name: "m"};console.log(momo.toString())    //[object Object]obj[momo] = 1;console.log( obj )      //Object   /* [object Object]: 1name: "miaov"*/
</script>
<script>var m = new Map([ ["name","miaov"],["aaa",200] ]);console.log( m.size );                //2console.log( m.get( "name" ) )     //miaovm.set( "age",100 );var momo = { name: "m" };m.set( momo,1 );console.log( m );   //Map(4) {"name" => "miaov", "aaa" => 200, "age" => 100, {…} => 1}var res = m.delete( momo );var res = m.delete( "z" );console.log( m );        //Map(3) {"name" => "miaov", "aaa" => 200, "age" => 100}console.log( m.has( momo ) );       //falseconsole.log( m.has( "z" ) );       //falsem.forEach( function( item,key,map ){console.log(item,key,map)} )/*miaov name Map(3) {"name" => "miaov", "aaa" => 200, "age" => 100}200 "aaa" Map(3) {"name" => "miaov", "aaa" => 200, "age" => 100}100 "age" Map(3) {"name" => "miaov", "aaa" => 200, "age" => 100}*/var res = m.keys();console.log( res.next() );      //{value: "name", done: false}console.log( res.next() );      //{value: "aaa", done: false}console.log( res.next() );       //{value: "age", done: false}console.log( res.next() );       //{value: undefined, done: true}var res = m.values();console.log( res.next() );        //{value: "miaov", done: false}console.log( res.next() );     //{value: 200, done: false}console.log( res.next() );       //{value: 100, done: false}console.log( res.next() );       //{value: undefined, done: true}var res = m.entries();console.log( res.next() );       //{value: Array(2), done: false}console.log( res.next() );      //{value: Array(2), done: false}console.log( res.next() );      //{value: Array(2), done: false}console.log( res.next() );      //{value: undefined, done: true}//两个不同的对象{}m.set( {},2 );m.set( {},3 );console.log( m.get( {} ) );  //undefined//后者会覆盖前者var obj = {};m.set( obj,2 );m.set( obj,3 );console.log( m.get( obj ) );    //3</script>

set(二)

<script>var s = new Set(["a","b","c"]);
/*  console.log(s.size);             //=> 对象的长度s.add( 1 ).add( 2 ).add( 1 );    // => 不会添加相同的元素//尽管 NaN === NaN 为false,还是不能重复添加NaNs.add( NaN ).add( NaN );console.log(s)//删除元素var res = s.delete( "b" );//var res = s.delete( "z" );    //falseconsole.log( res );      //trueconsole.log( s ); //Set(2) {"a", "c"}//判断是否存在某元素// console.log(s.has("a"))// console.log(s.has("x"))//清除对象的元素s.clear();console.log( s );  //Set(0) {}*///forEach遍历对象里的key,value,整个对象
/*  s.forEach( function(item,index,set){console.log( item,index,set )a a Set(3) {"a", "b", "c"}b b Set(3) {"a", "b", "c"}c c Set(3) {"a", "b", "c"}} )*///此处keys与values相同/*   var keys = s.keys();console.log( keys );console.log( keys.next() ) //{value: "a", done: false}console.log( keys.next() ) //{value: "b", done: false}console.log( keys.next() ) //{value: "c", done: false}console.log( keys.next() ) //{value: undefined, done: true}*//*var values = s.values();console.log( values.next() )   //{value: "a", done: false}console.log( values.next() )   //{value: "b", done: false}console.log( values.next() )   //{value: "c", done: false}console.log( values.next() )   //{value: undefined, done: true}*///整一个对象
/*  var entries = s.entries();console.log( entries.next() )    //{value: Array(2), done: false}console.log( entries.next() )   //{value: Array(2), done: false}console.log( entries.next() )   //{value: Array(2), done: false}console.log( entries.next() )   //{value: undefined, done: true}console.log( s );   //Set(3) {"a", "b", "c"}*/var arr = [1,2,3,2,3,5,4,"1",NaN,NaN];var s = new Set(arr);console.log( s );
/*  0: 11: 22: 33: 54: 45: "1"6: NaNlength: 7*///用以上方法去重
</script>

Synbol

<script>//symbol => 加标记,独一无二,不会被覆盖var s = Symbol( "a" );console.log( typeof s ) //"symbol"console.log( s ) // Symbol(a)var s2 = Symbol( "b" );console.log( s2 ) // Symbol(b)console.log( s === s2 );  //falsevar s3 = new Symbol();      //出错//Symbol is not a constructor//下面方法会覆盖原来的值var obj = {a: 1}obj.b = 2;obj.a = 3;console.log( obj );        //{a: 3, b: 2}          //Symbol("a") => 括号里的"a"只是标记            var a = Symbol("a");obj[ a ] = "sa";console.log( obj );       //{a: 3, b: 2, Symbol(a): "sa"}   var b = Symbol("a"); obj[ b ] = "sb";console.log( obj )//{a: 3, b: 2, Symbol(a): "sa", Symbol(a): "sb"}for( var attr in obj ){console.log( obj[attr] )//3 2}//获取symbol值console.log( Object.getOwnPropertySymbols( obj ) )// [Symbol(a), Symbol(a)]var s = Symbol();
//  console.log( s + 1 );//Cannot convert a Symbol value to a number
//  console.log( s + "a" );// Cannot convert a Symbol value to a string// !! => 转布尔值console.log( !!s );      //trueconsole.log( Boolean( s ) );  //true
</script>

遍历接口

<script>/* var els = document.getElementsByTagName("*");遍历所有    for( var attr of ele )for( var attr of els ){console.log( attr )}*/var arr = [10,20,30];/*console.log( arr[Symbol.iterator] );ƒ values() { [native code] }*/var k = arr.keys();console.log( k.next() );   //{value: 0, done: false}console.log( k.next() );   //{value: 1, done: false}console.log( k.next() );   //{value: 2, done: false}console.log( k.next() );   //{value: undefined, done: true}//模拟.keys()及.next()/*var k = i( arr );console.log( k.next() ); //{value: 0, done: false}console.log( k.next() );   //{value: 1, done: false}console.log( k.next() );   //{value: 2, done: false}console.log( k.next() );   //{value: undefined, done: true}function i( obj ){var index = -1;return {next: function(){index ++return  index < obj.length ? {value: index,done: false}:{value: undefined,done: true} }}}*/
</script>

对象

<script>var a = 1;var obj = {a: a,fn: function(){console.log( "fn" )}}
//-------------------------------------------------var obj = { a,  //此处为a:a省略,原因是属性值与外部变量相同时,可简写 fn(){console.log( "fn执行了" )},b: 100};console.log( obj )       //{a: 1, fn: ƒ, b: 100}obj.fn();                //fn执行了//-------------------------------------------------var attrname = "width";var attrname = "height";var attrObj = {};var attrFn = "fn";var obj = {//解决键名可变问题[attrname]: 100,//对象不可以作为键名[attrObj]: "hello",//[attrFn]相当于fn[attrFn](){console.log( "attrFn执行了" )}}console.log( obj )      //{height: 100, [object Object]: "hello", fn: ƒ}obj.fn()      //attrFn执行了
//-------------------------------------------------console.log( 1 == "1" )//trueconsole.log( NaN === NaN )//falseconsole.log( NaN == NaN )//falseconsole.log( Object.is( 1,1 ) )//trueconsole.log( Object.is( 1,"1" ) )//falseconsole.log( Object.is( NaN,NaN ) )//true,解决了NaN不能判断的情况console.log( Object.is( {},{} ) )//false,两个{}各自创建了新的空间var obj = {};console.log( Object.is( obj,obj ) )//true,同一对象obj
//--------------------------------------------------//新的值传入改变默认值,旧方法function move(obj){var defaultObj = {ease: "linear",duration: 1000}
/*       var para = {ease: obj.ease || defaultObj.ease,duration: obj.duration || defaultObj.duration}*///新的值传入改变默认值,新方法,Object.assign(),括号里的值越后面,等级越高,可以替换掉前面相同的属性值var para = {}Object.assign( para,defaultObj,obj )console.log( para )}move({duration: 2000})
//-----------------------------------------------------
//  for( var attr of Object.keys(obj) ) => 遍历对象键名。values => 键值,entries => 键值+键名var obj = {a: 1,b: 2}console.log( Object.keys(obj) )        // ["a", "b"]console.log( Object.values(obj) )      // [1, 2]console.log( Object.entries(obj) )     // [Array(2), Array(2)]//    for( var attr of Object.values(obj) ){
//      [key,val] => 解构赋值for( var [key,val] of Object.entries(obj) ){console.log( key,val )/*a 1b 2*/}
//-------------------------------------------------------var obj = {a: 1,b: 2}var res = {
//              类似继承    ......obj,c: 3}console.log( res )       //{a: 1, b: 2, c: 3}var arr = [1,2,3,4];   console.log( arr ); // [1, 2, 3, 4]// console.log( 1,2,3,4 );// ...可将数组值变成参数console.log( ...arr );  //1 2 3 4var arr = [1,23,4,5];//=> 求数组的最大值console.log( Math.max( 1,23,4,5 ) ); //23console.log( Math.max( ...arr ) );    //23var arr = [1,1,12,2,3,2,1,2];//去重 => 先转化为Set对象,再用...将其转化为参数,然后在[]变为数组var res = [...new Set(arr)];console.log( res );      //[1, 12, 2, 3]</script>

弱引用

<script>var m = new Map();var wm = new WeakMap();var zm = {name: "zmouse",age: 30};var reci = {name: "reci",age: 20}//对象作为键值m.set( zm,"miaov" );m.set( reci,"miaov2" );m.set( 1,"miao3" );for( var v of m ){console.log(v)//[{…}, "miaov"]  [{…}, "miaov2"]  [1, "miao3"]}wm.set( zm,"miaov1" );wm.set( reci,"miaov3" );console.log( wm ); //WeakMap {{…} => "miaov3", {…} => "miaov1"}//Map()为强引用,null清不了里面存进去的对象,m(a,b)中a可以不为对象。//WeakMap()为弱引用不能使用for-of方法,可以用null清除对象,且wm(a,b)中a必须为对象。
/*  for( var v of wm ){console.log(v)//wm is not iterable}*/
</script>

数组

<script>// new Array(10) => 创建长度为10的数组; Array.of(10) => 是添加元素为10/* var arr = new Array(10,20,30) //(3) [10, 20, 30]var arr = new Array(10)     //[empty × 10]var arr = Array.of(10,20,30)    //(3) [10, 20, 30]var arr = Array.of(10)       //[10]console.log( arr );//document.all <=> document.getElementsByTagName("*")var els = document.allvar els = document.getElementsByTagName("*")console.log( els )//HTMLCollection(6) [html, head, meta, title, body, script]//Array.from => 转化为数组,Array.isArray() => 检查()是否为数组 var arrEls = Array.from( els );console.log( Array.isArray( els ) )       //falseconsole.log( Array.isArray( arrEls ) )       //true  */var arr = [10,20,60,30,40,50];var res = arr.find( function( item ){console.log(item)return item > 50//.find => 当item>50时,跳出循环,返回对应值} )console.log( res ) //10 20 60 60var res = arr.findIndex( function( item ){console.log(item)return item > 50//.findIndex => 当item>50时,跳出循环,返回对应下标} )console.log( res ) //10 20 60 2
</script>

javascript_ES6新特性相关推荐

  1. 我要学ASP.NET MVC 3.0(一): MVC 3.0 的新特性

    摘要 MVC经过其1.0和2.0版本的发展,现在已经到了3.0的领军时代,随着技术的不断改进,MVC也越来越成熟.使开发也变得简洁人性化艺术化. 园子里有很多大鸟都对MVC了如指掌,面对问题犹同孙悟空 ...

  2. .NET 4.0 Interop新特性ICustomQueryInterface (转载)

    .NET 4.0 Interop新特性ICustomQueryInterface 在.NET Framework v4.0发布的新功能中,在名字空间System.Runtime.InteropServ ...

  3. oracle如何查询虚拟列,Oracle11g新特性之--虚拟列(VirtualColumn)

    Oracle 11g新特性之--虚拟列(Virtual Column) Oracle 11G虚拟列Virtual Column介绍 在老的 Oracle 版本,当我们需要使用表达式或者一些计算公式时, ...

  4. mysql8导入 psc 没有数据_新特性解读 | MySQL 8.0.22 任意格式数据导入

    作者:杨涛涛 资深数据库专家,专研 MySQL 十余年.擅长 MySQL.PostgreSQL.MongoDB 等开源数据库相关的备份恢复.SQL 调优.监控运维.高可用架构设计等.目前任职于爱可生, ...

  5. mysql query browswer_MySQL数据库新特性之存储过程入门教程

    MySQL数据库新特性之存储过程入门教程 在MySQL 5中,终于引入了存储过程这一新特性,这将大大增强MYSQL的数据库处理能力.在本文中将指导读者快速掌握MySQL 5的存储过程的基本知识,带领用 ...

  6. windows无法配置此无线连接_Kubernetes 1.18功能详解:OIDC发现、Windows节点支持,还有哪些新特性值得期待?...

    Kubernetes 1.18发布,一些对社区产生影响的新特性日渐完善,如 KSA(Kubernetes Service Account) tokens的OIDC发现和对Windows节点的支持.在A ...

  7. java字符串去重复_Java 8新特性:字符串去重

    本文首发与InfoQ. 8月19日,Oracle发布了JDK 8u20,JDK 8u20包含很多新特性,比如Java编译器更新.支持在运行时通过API来修改MinHeapFreeRatio和MaxHe ...

  8. Oracle 11g 新特性 -- Transparent Data Encryption (透明数据加密TDE) 增强 说明

    一.TransparentData Encryption (TDE:透明数据加密) 说明 Orace TDE 是Orcle 10R2中的一个新特性,其可以用来加密数据文件里的数据,保护从操作系统层面上 ...

  9. .NET Framework 4.0的新特性

    本文将揭示.NET 4.0中的3个新特性:图表控件.SEO支持以及ASP.NET 4可扩展的输出缓存. 图表控件 微软向开发者提供了大量可免费下载的图表控件,可以在.NET 3.5 ASP.NET或W ...

最新文章

  1. elasticsearch多表关联查询_Mybatis【15】 Mybatis如何实现一对一的情况多表关联查询?...
  2. Linux中yum和apt-get
  3. 判断任意控制台输入的十进制数是否为水仙花数
  4. python脚本语言采用声音作为手段_LKJ自动化测试脚本定义及生成技术研究
  5. Magento 获取当前店铺信息(首页,类别,地址等)
  6. 苹果将允许iPhone直接使用NFC接受信用卡付款
  7. 在gns3中搭建VTP演示实验
  8. teradata 数据定义
  9. 成为数据分析师需要具备的知识体系
  10. Java滑动窗口的最大值
  11. 倒立摆源码 旋转倒立摆 完整全功能 程序 倒立摆 pid算法 程序使用时可根据硬件需要自行调节
  12. AirTest进行自动化测试
  13. android定义圆角layout,Android布局切圆角
  14. 2021.02.17 GDKOI2021 好题记 第一记
  15. [Python] 开发植物大战僵尸游戏
  16. html首页问候语,每日一条问候语
  17. jsp+ssm计算机毕业设计宠物寻回系统【附源码】
  18. 精华文稿|用于无监督双目立体匹配学习的视差注意力机制
  19. java面经——基础篇(1)
  20. 通过Office 2007发布Blog

热门文章

  1. 最近穷疯了只好吃馒头
  2. docker swarm实践爆心肝总结全在这里,火速收藏!!!
  3. データファイルのアップロードとダウンロード
  4. 一个在图片上写字的方法
  5. 树莓派如何重新装Linux系统,如何给树莓派Raspberry重新安装修复操作系统
  6. 什么是天气预报 API 接口?如何获取天气预报 API?
  7. 苹果开发者账户续费 支付授权失败(终极解决方案)
  8. 韩乔生最牛的一次解说 (超级搞笑)
  9. 0.96寸OLED(SSD1306)屏幕显示(三)——屏幕垂直水平滚动
  10. oracle10g 学习笔记上