欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ES6 常用特性总结

程序员文章站 2022-07-10 21:27:39
一、ES6 基本认识 1、什么是 ES6? ES6 指的是 ECMAScript 6.0,是JavaScript 语言的一个标准。其目标是使JavaScript 可以用来编写复杂的大型的应用程序,成为企业级开发的语言。 2、ES6 与 JavaScript 的区别? ES6 是 JavaScript ......

一、es6 基本认识

1、什么是 es6?

  es6 指的是 ecmascript 6.0,是javascript 语言的一个标准。其目标是使javascript 可以用来编写复杂的大型的应用程序,成为企业级开发的语言。

2、es6 与 javascript 的区别?

  es6 是 javascript 的一个标准,javascript 是 es6 的具体实现。

3、babel 转码器?

  babel 是一个被广泛使用的 es6 转码器,其可以将 es6 代码转为 es5 代码,从而在现有环境下执行,即使用 es6 编写代码而无需担心不能运行。
  简单的讲就是 一些 浏览器 不支持 es6 部分语法,可以使用 babel 转码器将 es6 语法 转为 es5 语法,从而被 浏览器 识别。
  比如:

    es6 可以使用 箭头函数来 替代 普通函数,通过 babel 转码器,可以将 箭头函数 转为 普通函数。这样就不需要去担心浏览器是否支持这种语法。

【es6】
    input.map(item => item + 1);

【es5】
    input.map(function (item) {
        return item + 1;
    });

 

二、常用特性

1、let 命令

(1)基本内容
  let 命令通常用来声明局部变量。
  特性:局部有效、不存在变量提升、暂时性死区、不允许重复声明。

(2)特性一:局部有效。
  let 命令类似于 var,用来声明变量,但是 var 是全局有效,let 只在其所在的代码块内生效,出了代码块就获取不到该值。

如下例:(看的可能有点绕,多瞅两遍)
  var 定义的是全局变量,对于 for 循环来说,整个循环都只对一个 变量进行操作。看下面例子的第一个循环,在循环体内操作 i 会对循环有影响。由于进行了两次 i++,所以数组有部分值为 空,且只进行了部分循环。

  let 定义的是局部变量,对于 for 循环来说,每次循环都是不同的作用域,且 let 只对当前作用域有效。更有趣的是,循环语句内部是一个子作用域(即 在内部定义一个同名的 let 变量,不会影响外部的 let 变量)。看下面例子的第二个循环,每次循环操作,j 都是不同的值,且 循环内部 定义了 同名的 let 变量 j ,由于作用域的问题,其并不会影响循环语句中的 j,所以执行了全部循环。

【举例:】

var a = [];             // 用来记录每次循环需要打印的初始值
var b = [];             // 用来记录每次循环的初始值
var count = 0;          // 用来记录循环的次数

for(var i = 0; i < 10; i++, count++) {
    a[i] = function() {
        console.log("当前循环的值 i 为:  " + i);
    };
    b[i] = i++; 
}
console.log("当前循环执行次数为:  " + count);           // 由于 i 为全局变量,每次循环都会进行两次 i++,所以真实循环次数小于 10,所以输出为 5
a[6]();                                                // 由于操作的都是同一变量,所以函数调用的是 最后一次修改的 i 值,所以输出为 10
console.log("每次循环的初始值 i 为:  " + b);            // 用于只进行了部分循环,所有数组有些并没有赋值,即为空值。所以输出为 0,,2,,4,,6,,8
console.log("循环执行后的 i 值:  " + i);                // i = 10 时退出循环, i 为全局变量,所以输出 为 10


var c = [];            // 用来记录每次循环需要打印的初始值
var d = [];            // 用来记录每次循环的初始值
var count = 0;         // 用来记录循环的次数
for(let j = 0; j < 10; j++, count++) {
    let j = 5;
    c[j] = function() {
        console.log("当前循环的值 j 为:  " + j);
    };
    d[j] = j++; 
}
console.log("当前循环执行次数为:  " + count);           // 由于 j 为 局部变量,循环内部定义的 let 同名变量 j (子作用域)不会影响 循环语句的 j,真实循环执行 10 次,所以输出为 10 
c[5]();                                                // 每次操作都是不同的变量,且执行了 j++ 操作,所以输出为 6
console.log("每次循环的初始值 j 为:  " + d);            // 由于内部每次都给 d[5] 赋值,其余元素均为空值,所以输出为  ,,,,,5
console.log("循环执行后的 j 值:  " + j);                // 由于 j 为局部变量,只能存在于 for 循环代码块中, 所以此处会报错,输出 referenceerror: j is not defined

ES6 常用特性总结

 

 

 

(3)特性二:不存在变量提升
  变量提升指的是 变量可以在声明前使用。
  let 不存在变量提升,即声明变量后,才可以使用该变量,不能在声明前使用,否则会报错。

【举例:】

console.log(a);     // 不报错,输出 undefined
console.log(b);     // 报错,输出 referenceerror: b is not defined
var a = 10;
let b = 20;

ES6 常用特性总结

 

 

 

(4)特性三:暂时性死区
  暂时性死区指的是 刚开始进入当前作用域,所要使用的变量就已经存在了,但是不可获取,当变量被声明后,才可以获取该变量。

【举例:】

var tmp = 123;
console.log(tmp); //不报错,输出 123
if (true) {
    console.log(tmp); // 报错,referenceerror: cannot access 'tmp' before initialization
    let tmp;
}

第一次定义 tmp 为 var 型,所以可以正常输出 123,
进入 if 语句后,由于存在 let 定义的 tmp,系统判定 tmp 为局部变量而非全局变量。
导致 console.log(tmp) 中 tmp 出现在 变量声明前(变量提升失败), 从而报错,此处即为暂时性死区。

ES6 常用特性总结

 

 

 

(5)特性四:不重复声明
  在同一块 let 作用域中,若使用 let 声明一个变量,则不能再重复声明同一个变量。

【举例:】
// 报错,identifier 'a' has already been declared
{
    let a = 1;
    var a = 2;
}

// 不报错,undefined
{
    var a = 1;
    var a = 2;
}

// 报错,identifier 'a' has already been declared
{
    let a = 1;
    let a = 2;
}

 

2、const 命令

(1)基本内容
  const 通常用来声明一个只读的常量,一旦声明,常量的值不能被修改,且声明时必须初始化。
  用法类似于 let,局部有效、不存在变量提升、不重复声明。

【举例:(常量值不可被修改)】

const pi = 3.1415926
console.log(pi);   // 输出 3.1415926
pi = 3.14          // 报错,输出 assignment to constant variable.

【举例:(常量声明时需要初始化)】

const a           // 报错,输出 missing initializer in const declaration

【举例:局部有效】
{
    const pi = 3.1415926;
}
console.log(pi);   // 报错,输出 pi is not defined

【举例:不存在变量提升】
{
    console.log(pi);    // 报错,输出 cannot access 'pi' before initialization
    const pi = 3.1415926;
}

【举例:不重复声明】
{
    var pi = 3.14
    const pi = 3.1415926;  // 报错,输出 syntaxerror: identifier 'pi' has already been declared
}

  

(2)若 const 声明的是对象,那么 其不变的是 指向对象的地址,对象的值仍可以改变。可以通过object.freeze() 方法冻结对象(即对象不可修改)。

【举例:var,对象可被修改】
{
    var f = {name : 'tom', age : '12'};
    console.log(f.name + ", " + f.age);   // tom, 12
    f.name = 'jarry';
    f.age = 44;
    console.log(f.name + ", " + f.age);  // jarry, 44
    f = {name : 'rick', age : '22'};
    console.log(f.name + ", " + f.age);  // rick, 22
}

【举例:const,对象内容可被修改,但是对象不可被修改】
{
    const f = {name : 'tom', age : '12'};
    console.log(f.name + ", " + f.age);   // tom, 12
    f.name = 'jarry';
    f.age = 44;
    console.log(f.name + ", " + f.age);  // jarry, 44
    f = {name : 'rick', age : '22'};  // typeerror: assignment to constant variable.
}

【举例:freeze,对象不可被修改,对象内容不可被修改】
{
    const f = object.freeze({name : 'tom', age : '12'});
    console.log(f.name + ", " + f.age);  // tom, 12
    f.name = 'jarry';
    f.age = 44;
    console.log(f.name + ", " + f.age);  // tom, 12
    f = {name : 'rick', age : '22'};  // typeerror: assignment to constant variable.
}

ES6 常用特性总结

 

 

 

3、解构表达式

(1)什么是解构?
  解构指的是 es6 支持按照一定的模式,从数组或者对象中提取值,并将提取的值 对变量进行赋值。

(2)数组的解构赋值
  一般情况下,只要 = 左右两侧 的模式相同,左边的变量 就会赋值 上 右边对应的值。

【未使用解构表达式给赋值:】
let a = 10;
let b = 20;
let c = 30;
console.log(a, b, c);

【使用 解构表达式赋值:】
let [a, b, c] = [100, 200, 300];
console.log(a, b, c);

ES6 常用特性总结

 

 

 

  解构不成功时,对应的数据为 undefined。
  允许解构赋值指定默认值,默认值可以为一个函数(惰性,用到时才调用)。

【嵌套数组赋值:】

let [a, [b, [c, d]]] =  [1, [2, [3, 4]]];
console.log(a, b, c, d);         // 输出 1 2 3 4

let [head, ...tail] = [1, 2, 3, 4];
console.log(head);    // 输出 1
console.log(tail);    // 输出 (3) [2, 3, 4]

let [x, y, ...z] = [1];
console.log(x);        // 输出 1
console.log(y);        // 输出 undefined
console.log(z);        // 输出 []

【部分解构:(给匹配上的变量赋值)】

let [x, y, z] = [1, 2];
console.log(x);       // 输出 1
console.log(y);       // 输出 2
console.log(z);       // 输出 undefined

let [a, [b], c] = [1, [2, 3], 4];
console.log(a);       // 输出 1
console.log(b);       // 输出 2
console.log(c);       // 输出 4

【解构时使用默认值:(即若赋值失败,可以使用默认值)】

function hello() {
    return "hello";
}

let [x=hello(), y=hello(), z=100] = [1, 2, 3];
console.log(x);               // 输出 1
console.log(y);               // 输出 2
console.log(z);               // 输出 3

let [x2=hello(), y2=hello(), z2=100] = [, 2, ];
console.log(x2);              // 输出 hello
console.log(y2);              // 输出 2
console.log(z2);              // 输出 100

 

(3)对象的解构赋值
  对象同样可以进行解构。与数组解构不同的是,对象解构时根据属性名进行匹配,不需要注意顺序。
  属性名不匹配时,值为 undefined。
  可以自定义属性名,使用 : 去指定。
如下例:
  let {name, age} 等价于 let {name: name, age: age}

【根据属性名匹配:】

let {name, age} = {name: "tom", age: 22};
console.log(name);               // 输出 tom
console.log(age);                // 输出 22

【属性名匹配不成功,返回 undefined:】
let {name2, age2} = {name: "tom", age: 22};
console.log(name2);               // 输出 undefined
console.log(age2);                // 输出 undefined

【自定义属性名匹配:】
let {name: name3, age: age3} = {name: "tom", age: 22};
console.log(name3);               // 输出 tom
console.log(age3);                // 输出 22

ES6 常用特性总结

 

 

 

4、字符串拓展

  即加强了字符串处理功能。
(1)字符的 unicode 表示
  javascript 允许使用使用 \uxxxx 的形式表示一个字符,其中 xxxx 表示 unicode 值。但是这种写法只支持 \u0000 ~ \uffff,超出这个限制需要使用 双字节 进行表示。
比如:

  \u1f680 会解析成 \u1f68 和 0。若想正常显示,需使用双字节 \ud83d\ude80 表示。

【举例:】

console.log("\u0061");       // 输出 a
console.log("\u00614");      // 输出 a4

ES6 常用特性总结

 

 

 

  es6 可以使用 大括号将 xxxxx 括起来,从而正确解读。

【举例:】

console.log("\u{0061}");
console.log("\u{1f680}");
console.log("\ud83d\ude80");

ES6 常用特性总结

 

 

 

(2)新增方法 -- includes()、startswith()、endswith()
  javascript 中通过 indexof() 可以确定某个字符串中是否包含另外一个字符串。
  es6 新增三个方法用于判断字符串中是否包含另一个字符串。
    includes() 返回布尔值,true 表示当前字符串中存在另一个字符串,false 表示不存在。
    startswith() 返回布尔值,true 表示当前字符串的头部存在另一个字符串,false 表示不存在。
    endswith() 返回布尔值,true 表示当前字符串的尾部存在另一个字符串,false 表示不存在。

【举例:】

let test = "hello world";
console.log(test.includes("wo"));          // 输出 true
console.log(test.startswith("he"));        // 输出 true
console.log(test.endswith("ld"));          // 输出 true
console.log(test.includes("helloworld"));  // 输出 false 

ES6 常用特性总结

 

 

 

(3)模板字符串(``)
  模板字符串是增强版的字符串,使用 反引号(``) 标识字符串,可以作为普通字符串使用,可以定义多行字符串,内部使用 ${} 可以嵌入变量、函数、表达式等并解析。

【举例:】

let [name, age] = ["tom", 32];
function fun() {
    return "helloworld";
}
let test2 = `${name}, 
            age = ${age - 10}, 
            say ${fun()}`;
console.log(test2);

ES6 常用特性总结

 

 

 

5、对象的拓展

  拓展对象的用法。
(1)属性简写
  es6 允许在 对象中 直接写变量,此时 属性为 变量名,属性值为 变量值。即 {a} 等价于 {a: a}

【举例:】

let a = "hello";
let b = {a};
console.log(b);      // 输出 {a: "hello"}

let c = {a: a};
console.log(c);      // 输出 {a: "hello"}

let d = {g: "hello"};
console.log(d);      // 输出 {g: "hello"}

ES6 常用特性总结

 

 

 

  对象中的方法也可以简写。

【举例:】

let [name, age] = ["tom", 32];

let person = {
    name,
    age,
    hello() {
        console.log(`${name}, ${age}`);
    },
    hello2: function() {
        console.log(`${name}, ${age}`);
    }
};

person.hello();
person.hello2();

ES6 常用特性总结

 

 

 

(2)新增方法 -- assign()
  object.assign() 方法用于对象的合并。
  其实现的是浅拷贝,即若 源对象中的某个属性值 仍是一个对象,那么目标对象 中拷贝得到的是这个对象的引用,即对源对象中这个对象进行修改,会影响到目标对象。

【格式:】
    object.assign(target, source1, ...source2);
注:
    target 为目标对象,source1, ...source2 等都是源对象。
    该方法是将 源对象 的值 复制 到 目标对象 中。
    若出现同名属性,则后者会覆盖前者。
    即 target、source1、source2 中存在同名属性,则最后 target 的那个同名属性为 source2 的属性。
    
【举例:】

let tom = {
    name: "tom",
    age: 32,
    teacher: {
        chinese: "rose",
        english: "jack"
    }
};

let jarry = {
    name: "jarry",
    age: 33,
    email: "jarry@163.com"
};

let people = object.assign({}, tom, jarry);

console.log(people);

tom.teacher.chinese = "rick";

console.log(people);

ES6 常用特性总结

 

 

 

如何实现深拷贝嘞:
  有一种解决办法:(具体原因没有仔细深究)
    先将对象转为 json 字符串,再将 字符串转为对象。

将上例
    let people = object.assign({}, tom, jarry);
改为
    let people = object.assign({}, json.parse(json.stringify(tom)), jarry);

ES6 常用特性总结

 

 

 

(3)新增对象遍历方法 -- keys()、values()、entries()
  object.keys() 获取对象 key 形成的数组。
  object.values() 获取对象 value 形成的数组。
  object.entries() 获取对象 key - value 形成的 二维数组。

【举例:】

let people = {
    name: "tom",
    age: 22
};

console.log(object.keys(people));      
console.log(object.values(people));
console.log(object.entries(people));

ES6 常用特性总结

 

 

 

(4)扩展运算符(...)
  用于取出对象、数组的参数并拷贝到当前对象中。
  若数据重复,会覆盖,等同于 object.assign()。

【举例:】

let people = {
    name: "tom",
    age: 22
};

let people2 = {
    name: "jarry",
    age: 33
};

console.log({people, people2});
console.log({...people, ...people2});


let a = [3, 1, 2];
console.log(a);
console.log(...a);

ES6 常用特性总结

 

 

 

6、函数的拓展

(1)函数参数默认值
  可以在定义函数的同时,指定函数的默认值,调用时,若未传递参数,则使用默认值。

【举例:】

function test (x, y) {
    y = y || "hello";
    console.log(x + "======" + y);
}

test("tom");                      // 输出 tom======hello
test("tom", "helloworld");        // 输出 tom======helloworld


function test2 (x, y = "hello") {
    console.log(x + "======" + y);
}

test2("tom");                     // 输出 tom======hello
test2("tom", "helloworld");       // 输出 tom======helloworld

ES6 常用特性总结

 

 

 

(2)rest 参数
  rest 参数 ,形式为 ...变量名, 用于接收多个参数,保存在数组中。
  若有多个参数,则 rest 必须放在最后,否则会报错。

【举例:】

function test (...values) {
    // for of 每次获取的是数组的值
    for (let j of values) {
        console.log(j);
    }
}

test(8, 7, 9);

function test2 (...values) {
    // for in 每次获取的是数组的下标
    for (let j in values) {
        console.log(values[j]);
    }
}
test2(8, 7, 9);

function test3 (...values, y) {            // 报错,syntaxerror: rest parameter must be last formal parameter
    for (let j in values) {
        console.log(values[j]);
    }
}

ES6 常用特性总结

 

 

 

(3)箭头函数
  es6 支持 使用 箭头 => 定义函数。

【使用箭头函数定义 函数:】

var f = v => v;
console.log(f(3));   // 3

// 等价于
var f = function(v){
    return v;
}
console.log(f(3)); // 3

ES6 常用特性总结

 

 

 

  如果没有参数、或者有多个参数,需使用圆括号 () 代替参数部分。
  如果方法体(代码块)只有一条语句,则 return 可以省略。

【使用 () 代替参数:】

var f = () => 5;
// 等价于
var f = function () {
    return 5 
};


var sum = (num1, num2) => num1 + num2;
// 等价于
var sum = function(num1, num2) {
    return num1 + num2;
};

 

  如果方法体(代码块)存在多条语句,则需要使用大括号 {} 括起来,并使用 return 返回值。

【举例:】

var fun = () => {
    let num = 7;
    let num2 = num + 3;
    return num + num2;
};
console.log(fun());  // 17

// 等价于
var fun = function() {
    let num = 7;
    let num2 = num + 3;
    return num + num2;
};
console.log(fun());   // 17

ES6 常用特性总结

 

 

 

  若返回的是一个对象,则必须在对象外面加上圆括号 (),否则 {} 会被当成代码块被解析。

【举例:】

var getpeopleitem = id => ({ id: id, name: "temp" });
console.log(getpeopleitem(3));   // {id: 3, name: "temp"}

var getpeopleitem = id => { id: id, name: "temp" };
console.log(getpeopleitem(3)); //  syntaxerror: unexpected token :

ES6 常用特性总结

 

 

   

  解构与箭头函数可以一起使用:

【举例:】

let people = {
    name: "tom",
    age: 22
};

let fun = (param) => {
    console.log(param.name + "==========" + param.age);
};
fun(people);

let fun2 = ({name, age}) => {
    console.log(name + "==========" + age);
};
fun2(people);

ES6 常用特性总结

 

 

 

7、数组常用方法

  参考:https://www.cnblogs.com/l-y-h/p/12150578.html
(1)新增方法 -- reduce()
  array.reduce(callback[, initialvalue]) 用于给数组的每一个元素执行一个回调函数。
其中 :
  initialvalue 为第一次执行 callback 时的参数值,可以省略。
  callback 有四个参数,callback(previousvalue, currentvalue, index, array).
  previousvalue 指上一次执行回调的函数值,或者初始值。
  currentvalue 指数组当前被处理的元素
  index 指当前数组元素的下标
  array 指当前的数组

【举例:】

let arr = [4, 6, 5];

let newarr = arr.reduce((previousvalue, currentvalue, index, array) => {
    console.log("上一次处理的值为: " + previousvalue);
    console.log("当前处理的值为: " + currentvalue);
    console.log("当前元素下标为: " + index);
    console.log("当前数组元素为: " + array[index]);
    return currentvalue * 2;
});

console.log(newarr);

ES6 常用特性总结

 

 

8、promise 对象

(1)什么是 promise ?
  promise 是一个异步编程的一种解决方案。可以理解为一个容器,里面保存着未来才会结束的某个操作(异步操作)的结果,通过 promise 对象可以获取异步操作的消息。

(2)promise 特点
特点一:对象的状态不受外界影响。
 promise 有三种状态,pending (进行中)、resolved (解决)、rejected (失败)。只有异步操作的结果能决定 promise 处于哪种状态,其余操作无法改变该状态,无法中途取消操作。

特点二:状态改变后,不再变化。
  状态改变的情况,pending -> resolved 、 pending -> rejected。
  一旦状态改变,其不会再改变。

(3)promise 缺点
  无法取消promise,一旦新建便会执行,无法中途取消。
  如果不设置回调函数,promise内部的错误不会向外抛出。
  处于pending时,无法判断该操作是刚开始还是即将完成。

(4)如何使用?
  需要使用 new 去实例化一个 promise 对象,参数为 一个函数。
  函数的参数为 resolve、reject ,参数为两个函数,由 javascript 引擎提供。
  resolve 函数是改变状态, pending -> resolved ,即异步操作成功后调用,并将异步操作的成功结果作为参数向外传递。
  reject 函数也是改变状态, pending -> rejected,即异步操作失败后调用,并将异步操作的失败结果作为参数向外传递。
  使用 then 方法可以处理 resolve、reject 传递出来的结果。其接受两个回调函数作为参数。第一个回调函数用来处理 resolve 传递的结果,第二个回调函数用来处理 reject 传递的结果。第二个回调函数可选。
  一般情况下,使用 catch 方法处理 reject 传递出来的结果。其作用等价于 then 方法中的第二个回调函数。

【格式:】

var promise = new promise((resolve, reject) => {
    if(异步操作成功) {
        resolve(data);
    } else {
        reject(error);
    }
});

promise.then((data) => {
    // 成功的操作
}).catch((error) => {
    // 失败的操作
});

 

9、模块化

(1)什么是模块化?

  模块化就是把代码进行拆分,方便重复利用。类似于 java 中的各种 jar 包。
  模块化两个主要命令:export、import。
    export:用于规定模块的对外接口,即通过 export 可以获取模块的内容。
    import:用于导入模块,即通过 import 可以与其他模块建立起联系。

(2)export 命令
  通常一个模块就是一个文件,该文件内部的变量、数组、对象 等外界都不能获取。需要使用 export 将其导出。
  export 可以导出 基本类型变量、函数、数组、对象等。

【导出方式一:】

export var test = "hello";
    
【导出方式二:】

var a = "hello";
var b = [1, 2, 3];
export {a, b};

导出方式一、导出方式二 对外暴露的接口名 为 变量名、函数名等。
使用 import 要填写正确的接口名,才能正常引用模块,否则会出错。

【导出方式三:(使用 as 自定义接口名)】

var a = "hello";
var b = [1, 2, 3];
export {
    a as aa,
    b as bb
};

【导出方式四:(使用 default 可以忽略接口名,此时 import 可以自定义接口名)】

export default {
    var a = "hello";
    var b = [1, 2, 3];
}

 

(3)import 命令
  export 定义了模块对外的接口后,可以使用 import 导入相应的模块功能。

【导入方式一:(使用 {} 可以一次接受多个模块接口名)】

import {a, b} from 'xx/xx.js';

【导入方式二:(使用 as 取名)】

import {a as aa, b as bb} from 'xx/xx.js';

【导入方式三:(对于 export default 的模块,可以任意取名)】

import test from 'xx/xx.js';

 

未完待续...