ES6常用知识点小结
Posted 艾涵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES6常用知识点小结相关的知识,希望对你有一定的参考价值。
ECMAScript 6(以下简称ES6)是javascript语言的下一代标准。
1. let 和 const
1 { 2 var a=5; 3 let b=10; 4 } 5 console.log(a); 6 console.log(b);
控制台就是这样输出:
也就是说,var声明的变量由于不存在块级作用域所以可以在全局环境中调用,而let声明的变量由于存在块级作用域所以不能在全局环境中调用。
再来看一个经典例子(闭包):
1 var a=[]; 2 //执行for循环 3 for(var i=0;i<10;i++){ 4 a[i]=function(){ //因为这个是定义,并没有调用方法,不会执行 5 console.log(i); 6 }; 7 } 8 //for循环之后,此时 i = 10;再次执行a[6]();因为 i 一直被引用,所以不会回收,进入到 a[i] 的方法里面, 打印的是 i ,也就是10 9 a[6](); //输出10
如果使用 let
1 var a=[]; 2 for(let i=0;i<10;i++){ 3 a[i]=function(){ 4 console.log(i); 5 }; 6 } 7 a[6](); //打印6
a[6]函数(闭包)这个执行环境中,它会首先寻找该执行环境中是否存在 i,没有找到,因为 i 是块级作用域,就沿着作用域链继续向上到了其所在的代码块执行环境,找到了i=6,于是输出了6,即a[6]();的结果为6。这时,闭包被调用,所以整个代码块中的变量i和函数a[6]()被销毁。
const 是定义常量:const a = 14; 此后变量 a 的值无法更改覆盖。
2. 字符串拼接
1 //传统字符串拼接 2 var s1 = \'生物膜系统组装又拆分,变幻莫测;\'; 3 var s2 = \'你的好多细胞在分裂,\'; 4 var str = \'孩子们:请听我说!\'+s2+\'有丝,减数,哪管白天和黑夜。\'+ 5 \'染色体,细胞核时隐时现,\'+s1+\'核糖体在mRNA上穿梭忙碌,\'+\'几千种酶各司其职,将活化能狠狠打折。\'; 6 console.log(str); 7 8 // 字符模板的写法 9 var s1 = \'染色体,细胞核时隐时现,\'; 10 var s2 = \'你的好多细胞在分裂,\'; 11 var str = `孩子们:请听我说!${s2}有丝,减数,哪管白天和黑夜。${s1}生物膜系统组装又拆分,变幻莫测;核糖体在mRNA上穿梭忙碌,几千种酶各司其职,将活化能狠狠打折。`; 12 console.log(str);
es6使用 ` ` 包裹字符串,即使断开,也可以用这个符号包裹起来合并成一个字符串。
3. 解构赋值
1 // 以前我们给变量赋值,只能直接指定值 2 var a = 1; 3 var b = 2; 4 var c = 3; 5 console.log(a,b,c); // 1 2 3 6 7 // 现在用解构赋值的写法就变得简单了,只要模式匹配上了就行了,如下 8 // 注意数组是有顺序的 9 var [a,b,c] = [11,22,33]; 10 console.log(a,b,c); // 11 22 33 11 12 var [b,a,c] = [11,22,33]; 13 console.log(a,b,c); // 22 11 33 14 15 // 当然解构赋值还有嵌套比较复杂的写法,如下 16 let [foo,[[bar],[baz]]] = [111,[[222],[333]]]; 17 console.log(foo,bar,baz); // 111 222 333 18 19 let [head,...foot] = [1,2,3,4]; 20 console.log(head,foot); // 1 [2,3,4] 21 22 // 如果解构不成功,变量的值就等于undefined,如下 23 var [bar3,foo3] = [1000]; 24 console.log(bar3,foo3); // 1000 undefined 25 26 // 另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功 27 let [x,y] = [10000,20000,30000]; 28 console.log(x,y); // 10000 20000 29 30 // 默认值可以引用解构赋值的其他变量,但该变量必须已经声明 31 let [a=1,b=a] = [2,3]; 32 console.log(a,b); // 2 3 33 34 // 对象的解构也可以指定默认值 35 var {x,y=5} = {x:1}; 36 console.log(x,y); // 1 5 37 38 //对象的解构赋值解构不仅可以用于数组,还可以用于对象(json) 39 //对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定; 40 //而对象的属性没有次序,变量必须与属性同名,才能取到正确的值 41 var {a,b} = {a:\'apple\',b:\'banana\'}; 42 console.log(a,b); // apple banana 43 var {b,a} = {a:\'apple\',b:\'banana\'}; 44 console.log(a,b); // apple banana 45 46 // 如果变量名与属性名不一致,必须写成下面这样 47 let obj = {first:\'hello\',last:\'world\'}; 48 // first ---> f,那么此时f就是first,而不是undefined了,有点类似别名的概念 49 let {first:f,last} = obj; 50 console.log(f,last); // hello world 51 52 //1.也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。 真正被赋值的是后者,而不是前者 53 //2.v是匹配的模式,n才是变量。真正被赋值的是变量n,而不是模式v。 54 //注意,采用这种写法时,变量的声明和赋值是一体的 55 // v ---> n,那么此时n就是vue,而不是undefined了 56 var {v:n} = {v:\'vue\',r:\'react\'}; 57 console.log(n); // vue 58 console.log(v); // Uncaught ReferenceError: v is not defined 59 console.log(r); // Uncaught ReferenceError: r is not defined
4. 复制数组
1 // 数组的浅拷贝,引用之间的拷贝,没有实现数组的真正复制 2 var arr1 = [1, 2, 3]; 3 var arr2 = arr1; 4 arr2.push(4); 5 console.log(arr1, arr2); //[1, 2, 3, 4] [1, 2, 3, 4] 6 7 // 复制数组深拷贝,传统做法 8 var arr1 = [1,2,3]; 9 var arr2 = []; 10 //通过for循环遍历之后将arr1数组的每一项赋值给arr2数组的每一项, 就实现了数组的深拷贝,这时候我再去操作arr2的数组的时候,arr1就不会受影响了 11 for(var i=0;i<arr1.length;i++){ 12 arr2[i] = arr1[i]; 13 } 14 // 数组尾部添加 15 arr2.push(4); 16 console.log(arr1,arr2); 17 18 // ES6实现的数组的深拷贝方法1 19 var arr1 = [1,2,3]; 20 var arr2 = Array.from(arr1); 21 // 数组尾部添加 22 arr2.push(100); 23 console.log(arr1,arr2); // [1, 2, 3] [1, 2, 3, 100] 24 25 // ES6实现的数组的深拷贝方法2 26 var arr1 = [1,2,3]; 27 // 超引用拷贝数组 28 var arr2 = [...arr1]; 29 // 数组尾部添加 30 arr2.push(1000); 31 console.log(arr1,arr2); // [1, 2, 3] [1, 2, 3, 1000] 32 33 function show(...args){ 34 // 此时这个形式参数就是一个数组,我们可以直接push东西进来,如下 35 args.push(5); 36 console.log(args); 37 } 38 // 调用 39 show(1,2,3,4); // [1, 2, 3, 4, 5]
5. 增加了Map对象,倾向于后台
1 var map = new Map(); 2 // 设置 3 // map.set(name,value); 4 map.set(\'a\',\'apple\'); 5 map.set(\'b\',\'banana\'); 6 // 获取 7 // map.get(name); 8 console.log(map.get(\'a\') + \' \' + map.get(\'b\')); 9 // 删除之前map对象 10 console.log(map); 11 // 删除 12 // map.delete(name); 13 map.delete(\'a\'); 14 // 删除之后map对象 15 console.log(map); 16 17 // 注意for..in是不能循环map对象的,不报错也无任何反应,所以下一代码无任何输出,稍微注意下 18 for(var name in map){ 19 console.log(name); 20 } 21 22 // 实体 map对象的循环输出 23 for(var name of map){ 24 //循环出来的结果就是:a,apple b,banana 循环key,value 25 console.log(name); 26 } 27 28 //循环出来的结果就是: a,apple b,banana 循环key,value 29 for(var [key,value] of map.entries()){ 30 console.log(key,value); 31 } 32 33 //只循环key 34 for(var key of map.keys()){ 35 console.log(key); 36 } 37 38 //只循环value 39 for(var val of map.values()){ 40 console.log(val); 41 }
6. for-of循环 ,上一例子也说到了for-of循环map对象输出
1 //for of一个arr对象 2 var arr = [\'红楼梦\',\'西游记\',\'三国演义\',\'水浒传\',\'火影\']; 3 //只循环key 0 1 2 3 4 输出key值,也就是下标索引 4 for(var key of arr.keys()){ 5 console.log(key); 6 } 7 //只循环value,注意数组是没有.values() 直接 var value of arr ,输出 红楼梦,西游记,三国演义,水浒传,火影 8 for(var value of arr){ 9 console.log(value); 10 } 11 //循环key,value 12 for(var [key,value] of arr.entries()){ 13 console.log(key,value); 14 } 15 16 //for in循环与for of循环的区别 17 var arr = [\'apple\',\'banana\',\'orange\',\'pear\']; 18 for(var i in arr){ 19 // i打印出来的就是arr数组对应的索引 20 // 0 1 2 3 21 console.log(i); 22 } 23 for(var i of arr){ 24 // i值打印出来的就是我们想要的数组具体的值 25 // apple banana orange pear 26 console.log(i); 27 } 28 29 //for of不能循环json 30 var json = {\'a\':\'apple\',\'b\':\'banana\',\'c\':\'orange\',\'d\':\'pear\'}; 31 for(var name in json){ 32 // a b c d 33 console.log(name); 34 // apple 35 console.log(json.a); 36 // pear 37 console.log(json[\'d\']); 38 } 39 // 注意for..of可以循环arr,但是不可以循环json,会报错,特别注意下 40 for(var name of json){ 41 Uncaught TypeError: undefined is not a function 42 console.log(json); 43 }
7. 箭头函数:引入箭头函数有两个方面的作用:更简短的函数并且不绑定this
。
箭头函数表达式的语法比函数表达式更短,并且不绑定自己的this,arguments,super或 new.target。这些函数表达式最适合用于非方法函数,并且它们不能用作构造函数,不能使用new。
箭头函数的写法 function(){ } 变成 ()=>{ }
1 var a = ()=>{ 2 return 1; 3 }
等价于
1 function a(){ 2 return 1; 3 }
如果函数体只有一条语句,可以这样写:
1 var fun = ()=>Math.random()*10 2 console.log(fun());
这样子调用这个箭头函数就会直接返回这条语句的值
箭头函数不绑定arguments,取而代之用rest参数…解决
1 function A(a){ 2 console.log(arguments); //[object Arguments] [1, 2, 3] 3 } 4 5 var B = (b)=>{ 6 console.log(arguments); //错误:ReferenceError: arguments is not defined 7 } 8 9 var C = (...c)=>{ //...c即为rest参数 10 console.log(c); //[3, 1, 2] 11 } 12 A(1,2,3); 13 B(2,1,3); 14 C(3,1,2);
箭头函数会捕获其所在上下文的 this 值,作为自己的 this 值
1 var obj = { 2 a: 10, 3 b: function(){ 4 console.log(this.a); //输出10 5 }, 6 c: function() { 7 return ()=>{ 8 console.log(this.a); //输出10,捕获了上面obj的this作为自己的this 9 } 10 } 11 } 12 obj.b(); 13 obj.c()();
所谓箭头函数的 this 捕获的是所在的上下文,比如下面这个例子:b
是一个箭头函数,然后它的 this
是指向window
,这是为什么呢,因为箭头函数捕获的是obj{}
这个对象的环境,然后这个环境的this
指向的是window
,就相当于上一条的例子:在c
方法里面return
的那个箭头函数捕获的是c:function(){}
这个环境的this
,而这个环境的this
是obj
1 var obj = { 2 a: 10, 3 b: () => { 4 console.log(this.a); //undefined 5 console.log(this); //window 6 }, 7 c: function() { 8 console.log(this.a); //10 9 console.log(this); //obj{...} 10 } 11 } 12 obj.b(); 13 obj.c();
对于函数的this
指向问题:
- 箭头函数的
this
永远指向其上下文的this
,任何方法都改变不了其指向,如call(), bind(), apply()
- 普通函数的
this
指向调用它的那个对象
8. 对象的简洁语法
1 //传统对象_单体模式写法 key-value模式 2 var person = { 3 name:\'krry\', 4 age:21, 5 showName:function(){ 6 return this.name; 7 }, 8 showAge:function(){ 9 return this.age; 10 } 11 }; 12 // 调用 13 console.log(person.showName()); // krry 14 console.log(person.showAge()); // 21 15 16 //ES6_单体模式写法 不需要写key 17 var name = \'krry\'; 18 var age = 21; 19 var person = { 20 name, 21 age, 22 showName(){ 23 return this.name; 24 }, 25 showAge(){ 26 return this.age; 27 } 28 }; 29 // 调用 30 console.log(person.showName()); // krry 31 console.log(person.showAge()); // 21
9. 类和继承(class和extends)
1. 传统面向对象的写法:
1 function Person(name,age){ // 类、构造函数 2 this.name = name; 3 this.age = age; 4 } 5 Person.prototype.showName = function(){ 6 return this.name; 7 }; 8 Person.prototype.showAge = function(){ 9 return this.age; 10 }; 11 var p1 = new Person(\'allen\',28); 12 var p2 = new Person(\'xiaoxiaoyou\',101); 13 console.log(p1.showName()); // allen 14 console.log(p2.showAge()); // 101 15 console.log(p1.showName == p2.showName); //true 注意不是调用方法,没有括号,所以才true 16 console.log(p1.constructor == Person); // true 构造方法相等
2. ES6面向对象写法:
1 class Person{ 2 // 构造器 3 constructor(name,age){ 4 this.name = name; 5 this.age = age; 6 } 7 showName(){ 8 return this.name; 9 } 10 showAge(){ 11 return this.age; 12 } 13 } 14 var p1 = new Person(\'aaa\',18); 15 var p2 = new Person(\'bbb\',20); 16 console.log(p1.name); // aaa 17 console.log(p1.showName()); // aaa 18 console.log(p2.showAge()); // 20 19 console.log(p1.showAge == p2.showAge); // true 20 console.log(p1.constructor == Person); // true
3. 面向对象给class赋值默认值:
1 class Person{ 2 // 构造器 3 constructor(name=\'default\',age=0){ 4 this.name = name; 5 this.age = age; 6 } 7 showName(){ 8 return this.name; 9 } 10 showAge(){ 11 return this.age; 12 } 13 } 14 15 var p1 = new Person(); 16 console.log(p1.name); // 构造器里面给的默认值 default 17 console.log(p1.age); // 构造器里面给的默认值 0
4. 传统写法原型继承extends
1 //传统写法原型继承 2 function Person(name,age){ // 类、构造函数 3 this.name = name; 4 this.age = age; 5 } 6 Person.prototype.showName = function(){ 7 return this.name; 8 }; 9 Person.prototype.showAge = function(){ 10 return this.age; 11 }; 12 // 工人类 13 function Worker(name,age){ 14 // 属性继承过来 15 Person.apply(this,arguments); 16 } 17 // 原型继承 18 Worker.prototype = new Person(); 19 var p1 = new Person(\'allen\',28); 20 var w1 = new Person(\'worker\',1000); 21 console.log(w1.showName()); // 确实继承过来了 result:worker
5. ES6中面向对象实现类继承
1 class Person{ 2 // 构造器 3 constructor(name,age){ 4 this.name = name; 5 this.age = age; 6 } 7 showName(){ 8 return this.name; 9 } 10 showAge(){ 11 return this.age; 12 } 13 } 14 class Worker extends Person{ 15 constructor(name,age,job=\'啦啦啦\'){ 16 // 继承超父类的属性 17 super(name,age); 18 this.job = job; 19 } 20 showJob(){ 21 return this.job; 22以上是关于ES6常用知识点小结的主要内容,如果未能解决你的问题,请参考以下文章