当前位置: 首页 > news >正文

教你快速入门ES6

什么是ES6?

ECMAScript 6.0 (下面简称ES6)是继ECMAScript5.1之后,javascript语言的下一代标准,发布于2015年6月。它的目标,是使得javascript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。下面将介绍ES6的一些新语法,使其在开发中更加语法简洁,效率更高。

1、变量声明const和let

在ES6之前,我们都是用var关键字声明变量。无论声明在何处,因为函数变量的提升,都会被视为声明在函数的最顶部(不在函数内即在全局作用域的最顶部)。例如:

        function f(){
            var flag=""
            if(flag){
                var test = "hello,world";
            }else{
                console.log(test);  
            }
        }
        f();
复制代码

以上代码实际是:

        function f(){
            var flag="";
            var test;  //变量提升到函数最顶部
            if(flag){
                var test = "hello,world";
            }else{
                console.log(test); //这里访问的test,值为undefined 
            }
        }
        f();
复制代码

所以不用关心flag是否为 true还是false。实际上,无论如何 test 都会被创建声明。

ES6出现后,我们一般用 letconst 来声明,let 表示变量、const 表示常量。letconst 都是块级作用域。怎么理解这个块级作用域?

说白了只要在{}花括号内的代码块即可以认为 let 和 const 的作用域。

看下面代码:

        function f(){
            var flag="";
            if(flag){
                let test = "hello,world";
            }else{
                console.log(test); //这里访问不到test,打印出test is not defined
            }
        }
      f();
复制代码

let 的作用域是在它所在当前代码块,但不会被提升到当前函数的最顶部。

const 声明的变量必须提供一个值,而且会被认为是常量,意思就是它的值被设置完成后就不能再修改了。

const a=1;
a=2; //就会报这样的错误:Assignment to constant variable.
复制代码

还有一点,如果 const的是一个对象,对象所包含的值是可以被修改的。也就是说,对象所指向的地址不能改变,而变量成员是可以修改的。如下面代码:

const obj = {name:"xiaoqinag"}
obj.name = "wangcai"
console.log(obj.name); //wangcai
复制代码

2、解构赋值

按照一定模式,从数组和对象中提取,对变量进行赋值,称为解构。

2.1、数组的解构赋值

//一般赋值
var a=1,b=2,c=3;
var [a,b,c] = [1,2,3];
console.log([a,b,c]);
复制代码
//解构赋值
var [a, b, c] = [1, 2, 3];
console.log([a, b, c]);
复制代码

当然不仅仅是var,let和const也可以

let arr = [1, 2, 3];
const [a,b,c] = arr;
console.log([a, b, c]);
复制代码

解构赋值允许指定默认值

看下面代码:

let [a,b,c=666] = [1, 2, 3];
console.log(a);  //1
console.log(b);  //2
console.log(c);  //3
复制代码

也就是说解构赋值的值级别高于自身的值。

let [a=1,b,c=3] = [];
console.log(a);  //1
console.log(b);  //undefined
console.log(c);  //3
复制代码

上面代码说明了:数组解构赋值时,会先找解构赋值的值,然后再找自身的值,如果前两者都没有,会返回undefined.

2.2对象的解构赋值

解构可以用于数组,同样也可以用于对象。对象的解构与数组有一个重要的不同,数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

// 变量名与属性名一致的情况下
 let{name,age} = {name:"wangcai",age:25}
 console.log(name);  //wangcai
 console.log(age);   //25
 //变量名与属性名不一致的情况下,必须这样写
 let {a : name, b : age} = {a : 'xiaoqinag', b : 30};
 console.log(name); //xiaoqinag
 console.log(age);  //30
复制代码

这实际上说明,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。

 let {a : name} = {a : 'xiaoqinag'};
 console.log(name); //xiaoqinag
 console.log(a);  //a is not defined
复制代码

上面代码中,a是匹配的模式,name才是变量。真正被赋值的是变量name,而不是模式a。

数组本质是特殊的对象,因此可以对数组进行对象属性的解构。

 let arr=["laifu","wnagcai","xiaoqiang"];
 let {0:first,1:center,[arr.length - 1]:last} = arr
 console.log(first); //laifu
 console.log(center); //wnagcai
 console.log(last);  //xiaoqiang
复制代码

3、数组的扩展

3.1 Array.from()

Array.from方法用于将两类对象转为真正的数组:类似数组的对象和可遍历的对象。

        let obj={
           "name":"wangcai",
           "age":34,
           "sex":"man"
       }
       let arr=Array.from(obj)      
       console.log(Array.isArray(arr));  //true
复制代码

3.2 Array.of()

作用:将一组值转换为数组。与Array.from功能相似,理解用来创建数组。主要目的是弥补构造器 Array()的不足。

之前使用new创建数组的痛点:

var arr1=[];
var arr2 = new Array(3);
var arr3 = new Array("3");
console.log(arr1,arr2,arr3); //[] [empty × 3]  ["3"]
复制代码

使用Array.of来改造,如下:

var arr1 = Array.of(3);
var arr2 = Array.of("3");
console.log(arr1,arr2); //[3]  ["3"]
复制代码

3.3 find()和findIndex()

find:用于找出第一个符合条件的数组元素。找不到则是undefined。注意,它是不会返回多个,只找一个,找到了就返回。

findIndex:返回第一个符合条件的数组元素的索引。找不到则是-1;

        let arr=[
            {name:"xiaoqiang",age:23},
            {name:"wangcai",age:25},
            {name:"laifu",age:34}
        ]
        let rs = arr.find(function(item){
            return item.name =="laifu";
        })
        console.log(rs);  //{name: "laifu", age: 34}
        
        let res = arr.findIndex(function(item){
            return item.name =="wangcai";
        })
        console.log(res);   //1
复制代码

3.4 includes()

作用:判断元素是否在数组中存在。返回值是 true | false

代码如下:

        let arr = [1, 2, 3];
        console.log(arr.includes(3));  //true
        console.log(arr.includes(6));  //false
复制代码

indexOf也可以做类似的工作,如下:

        let arr = [1, 2, 3];
        console.log(arr.indexOf(3));  //2
        console.log(arr.indexOf(6));  //-1
复制代码

但是,indexOf 对 NaN的判断是错误的,如下:

        let arr = [NaN, 2, 3];
        console.log(arr.indexOf(NaN));  //-1
复制代码

上面代码可以得到indexOf对NaN的判断是错误的,而includes()则没有这个问题。

3.5 fill()

作用:给数组填充指定值。fill方法用于空数组的初始化非常方便。已有数据会被覆盖。fill 方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。 代码如下:

        let arr = new Array(5);
        arr.fill("*");
        console.log(arr); //["*", "*", "*", "*", "*"]  //["*", "*", "*", "*", "*"]
复制代码

使用fill()会覆盖之前的元素,代码如下:

        let arr =[1,2,3,4];
        arr.fill("*");
        console.log(arr); //["*", "*", "*", "*"]
复制代码

fill()还可以指定填充位置,如下:

        let arr = [1,2,3,4,5,6]
        arr.fill("*",2,4);
        console.log(arr); //[1, 2, "*", "*", 5, 6]
复制代码

2 和 4表示下标,包括起点,不包括终点。

4、数组的扩展运算符

功能:把数据结构转成数组。

        let arr = [1,2,3,4,5,6]
        let arr2 = [...arr]
        console.log(arr2); // [1, 2, 3, 4, 5, 6]
复制代码

可以这样理解:

var arr2 = [ ...arr ];

  • [ ]表示一个数组。即 arr2 是一个数组。
  • ...arr :把数组 arr 展开。理解分解起一个一个的元素
  • 相当于实现了,数组的复制---这里是浅拷贝

还可以利用扩展运算符,把类数组转成数组,如下:

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>
<script>
    var lis = document.getElementsByTagName("li");
    var arr = [...lis];
    console.log(Array.isArray(arr));  //true
</script>
复制代码

把一个类数组转成数组有如下几种方式:

  • Array.prototype.slice.call();
  • Array.from();
  • [...类数组对象]

把字符串转成数组,如下:

    var str = "hello";
    var arr =[...str];
    console.log(arr); //["h", "e", "l", "l", "o"]
复制代码

还可以利用扩展运算符来合并数组,如下:

    var arr1 = [1,2];
    var arr2 = [3,4];
    var arr =[arr1,...arr2];
    console.log(arr);  //
复制代码

5、箭头函数

ES6可以使用“箭头”(=>)定义函数,注意是函数,不要使用这种方式定义类(构造器)。

5.1 语法

之前的函数写法:

    function f(x){
        return x*x;
    }
    let rs = f(2)
    console.log(rs);  //4
复制代码

箭头函数如下:

    var f=(x)=>{
        return x*x;
    }
    let rs = f(2)
    console.log(rs);  //4
复制代码

再改进,如果箭头函数中只有一个形参,那么()可以不写,如下:

    var f=x=>{
        return x*x;
    }
    let rs = f(2)
    console.log(rs);  //4
复制代码

如果函数体只有一条语句(非return语句),那么{}也可以不写,如下:

    var f=()=>
    console.log("hello world");  //hello world
    f()
复制代码

如果有return 语句,把{}和reutrn 都可以省略了,如下:

     var f=x=>x*x;
    console.log(f(2));  //4
复制代码

5.2 注意点

1、this固定,不再善变

    obj = {
       data: ['wangcai', 'xiaoqiang'],
       init: function () {
           document.onclick = ev => {
              console.log(this.data); // ['wangcai', 'xiaoqiang']
           }
           // 非箭头函数
           // document.onclick = function(ev) {
           //     console.log(this.data) // undefined
           // }
       }
   }
   obj.init()
复制代码

2、箭头函数不能用new

var Person = (name, age) => {
this.name = name
this.age = age
}
var p = new Person('wangcai', 33) //Person is not a constructor
复制代码

3、不能使用argument

var func = () => {
   console.log(arguments)
}
func(55) //arguments is not defined
复制代码

4、instanceof也返回true,表明也是Function的实例

var func = () => {}
console.log(func instanceof Function);  //true
复制代码

6、模板字符串

ES5中采用 + 进行拼接,着实麻烦,ES6解决了ES5在字符串功能上的痛点,简直是开发者的福音。

1、基本的字符串格式化。将表达式嵌入字符串中进行拼接。用${}来界定。

//es5语法
var name = "wangcai";
console.log("hello"+name);  //hellowangcai
//es6语法
var  name = "xiaoqiang";
console.log(`hello ${name}`); //hello xiaoqiang
复制代码

2、如果使用模版字符串表示多行字符串,所有的空格和缩进都会被保存在输出中。

console.log(`It's       raining 
today`);
//It's       raining 
// today
复制代码

3、在${}中的大括号里可以放入任意的JavaScript表达式,还可以进行运算,以及引用对象属性。

let a = 12;
let b = 22;
let c = "";
console.log(`c=a+b=${a+b}`); //c=a+b=34
复制代码

4、更强大的是:模版字符串还可以调用函数。

function string(){
    return "Learning ES6!!";
}
console.log(`你今天在做什么? 
            ${string()}`);  //你今天在做什么? 
            //Learning ES6!!
复制代码

7、Set 和 Map 数据结构

7.1 Set

ES6 提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。 代码如下:

var arr=[1,2,3,1,5,2];
var s = new Set(arr);
console.log(s);   //{1, 2, 3, 5}
复制代码

使用add()来添加,如下:

var s = new Set();
s.add(1);
s.add(2);
s.add(3);
s.add(4);
console.log(s);  //{1, 2, 3, 4}
复制代码

可以使用forEach遍历s,如下:

var s = new Set();
s.add(1);
s.add(2);
s.add(3);
s.add(4);
s.forEach(item=>console.log(item)  //1  2  3  4
)
复制代码

set不是数组,是一个像对象的数组,是一个伪数组,使用Array.isArray测试如下:

var s = new Set();
s.add(1);
s.add(2);
s.add(3);
s.add(4);
console.log(Array.isArray(s));  //false
复制代码

删除set其中的一个元素,如下:

var s = new Set();
s.add(1);
s.add(2);
s.add(3);
s.add(4);
s.delete(2)
console.log(s); //{1, 3, 4}
复制代码

可以使用Set实现数组的去重的问题,简洁明了,代码如下:

var arr = [1,2,7,9,2,7];
var arr1 = [...(new Set(arr))];
console.log(arr1);  //[1, 2, 7, 9]
复制代码

7.2 Map

Map类似于对象,里面存放也是键值对,区别在于:对象中的键名只能是字符串,如果使用map,它里面的键可以是任意值。 创建Map,如下:

var m = new Map([
    ["a","hello"],
    ["1","123"]
]);
console.log(m);  //{"a" => "hello", "1" => "123"}
复制代码

使用set进行添加,如下:

var m = new Map([
    ["a","hello"],
    ["1","123"]
]);
m.set(false,"abc");
m.set([1,2,3],{name:"wangcai"})
console.log(m);  
//{"a" => "hello", "1" => "123", false => "abc", Array(3) => {…}}
复制代码

还可以获取,通过get(键),如下:

var m = new Map([
    ["a","hello"],
    ["1","123"]
]);
m.set(false,"abc");
m.set([1,2,3],{name:"wangcai"})
console.log(m.get("a"));  //hello
复制代码

但是,使用m.get([1,2,3]),获取不到值,原因是get()是要比较栈区中的地址,而不是堆区中的数据,可以使用下面这个方法使m.get([1,2,3]),获取到值。

var m = new Map([
    ["a","hello"],
    ["1","123"]
]);
m.set(false,"abc");
console.log(m.get("a"));  //hello
let a=[1,2,3];
m.set(a,{name:"wangcai"})
console.log(m.get(a));  //{name: "wangcai"}
复制代码

重复的键会覆盖,如下:

var m=new Map();
m.set(1,"aaa");
m.set(1,"bbb");
console.log(m);  //Map(1){1 => "bbb"}
复制代码

8、Class 的基本语法

ES6 提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。

8.1class创建对象

在ES6中,可以使用class来声明一个类了,如下:

    class Person{
        constructor(name,age,height){
            this.name = name;
            this.age = age;
            this.height = height;
        }
        say(){
            console.log(`我叫${this.name},今年${this.age}岁,身高为${this.height}`);  
        }
    }
    var p = new Person("旺财","23","187");
    console.log(p.say());  //我叫旺财,今年23岁,身高为187
复制代码

注意:

  • class 是关键字,后面紧跟类名,类名首字母大写,采取的是大驼峰命名法则。类名之后是{}。
  • 在{}中,不能直接写语句,只能写方法,方法不需要使用关键字
  • 方法和方法之间没有逗号,不是键值对。

8.2 类的静态方法 static

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。

    class Person{
       static say(){
            console.log("hello world");  
        }
    }
    var p = new Person();
   Person.say()  //hello world
   p.say();  //p.say is not a function
复制代码

上面代码中,Person类的classMethod方法前有static关键字,表明该方法是一个静态方法,可以直接在Person类上调用(Person.classMethod()),而不是在Person类的实例上调用。如果在实例上调用静态方法,会出现一个错误,表示不存在该方法。

8.3 使用extends实现继承

使用ES6中的extends来实现继承,代码如下:

    class Person{
        constructor(name,age,height){
            this.name = name;
            this.age = age;
            this.height = height;
        }
       say(){
            console.log(`我叫${this.name},今年${this.age}岁,身高为${this.height}`);  
        }
    }
    class Student extends Person{
        constructor(name,age,height,profession){
            super(name,age,height)
            this.profession = profession;
        }
        showProfession(){
            console.log(`我叫${this.name},是一个${this.profession}`);
            
        }
    }
    var s = new Student("旺财","23","187","学生");
    s.say()             //我叫旺财,今年23岁,身高为187
    s.showProfession()  //我叫旺财,是一个学生
复制代码

注意:

  • 使用 extends 关键字来实现继承。
  • 在子类中的构造器 constructor 中,必须要显式调用父类的 super。 方法,如果不调用,则 this 不可用。

总结

ES6新特性远不止于此,本文列举的是一些常见的特性,在日常开发中,能算得上是使用率较高的了,能够正确的使用这些新特性,可以使你的开发事半功倍。

转载于:https://juejin.im/post/5b6e3a1ee51d45190d55a436

相关文章:

  • tranform知多少
  • Android酷炫实用的开源框架(UI框架)
  • Binder总结篇1-Binder原理
  • malloc()函数(Linux程序员手册)及函数的正确使用【转】
  • ListBean 排序
  • HYPER-V的安装和双机调试的配置(一)
  • java核心技术读书笔记
  • Android 9.0新特性
  • JS中逻辑运算符中 == 的问题
  • Apache2.2.x版本不支持PFS,无法通过ATS的问题
  • 惰性计算辨析
  • 洛谷P4016 负载平衡问题(费用流)
  • JavaWeb-JSPELJSTL
  • list、dict、str虽然是Iterable,却不是Iterator
  • jQuery(一)
  • 【个人向】《HTTP图解》阅后小结
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • git 常用命令
  • JavaScript设计模式之工厂模式
  • MQ框架的比较
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • mysql innodb 索引使用指南
  • PhantomJS 安装
  • Python打包系统简单入门
  • uva 10370 Above Average
  • 安装python包到指定虚拟环境
  • 给初学者:JavaScript 中数组操作注意点
  • 关于 Cirru Editor 存储格式
  • 观察者模式实现非直接耦合
  • 记录一下第一次使用npm
  • 使用common-codec进行md5加密
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • 如何在招聘中考核.NET架构师
  • #define与typedef区别
  • #Linux(权限管理)
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (09)Hive——CTE 公共表达式
  • (1)虚拟机的安装与使用,linux系统安装
  • (12)Hive调优——count distinct去重优化
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (分布式缓存)Redis持久化
  • (附源码)ssm码农论坛 毕业设计 231126
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • (转)德国人的记事本
  • ***通过什么方式***网吧
  • .Family_物联网
  • .htaccess配置重写url引擎
  • .Net IE10 _doPostBack 未定义
  • .net 发送邮件
  • .NET 依赖注入和配置系统
  • .net 怎么循环得到数组里的值_关于js数组
  • .NET 中让 Task 支持带超时的异步等待