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

ECMAScript 6 新特性(一)

ECMAScript 6 新特性(一)

1. let、const

1.1 let 关键字

let 关键字用来声明变量,使用 let 声明的变量有几个特点

  1. 不允许重复声明
  2. 块级作用域
  3. 不存在变量提升
  4. 不影响作用域链

1.2 const 关键字

const 关键字用来声明常量,const 声明有以下特点

  1. 声明必须赋初始值
  2. 标识符一般为大写
  3. 值不允许修改
  4. 块级作用域
  5. 对数组和对象的元素修改,不算做对常量的修改

使用技巧:声明变量使用 let、声明对象类型使用 const。

2. 解构赋值

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

  1. 数组的解构赋值

    const F4 = ["刘德华", "张学友", "郭富城", "黎明"];
    
    const [B1, B2, B3, B4] = F4;
    console.log(B1); /* 刘德华 */
    console.log(B2); /* 张学友 */
    console.log(B3); /* 郭富城 */
    console.log(B4); /* 黎明 */
    
  2. 对象的解构赋值

    const obj = {
      name: "小周",
      age: 18,
      run() {
        console.log("小周正在奔跑...");
      },
    };
    const { name, age, run } = obj;
    console.log(name); /* 小周 */
    console.log(age); /* 18 */
    run();
    

频繁使用对象方法、数组元素,就可以使用解构赋值形式

3. 模板字符串

模板字符串(template string)是增强版的字符串,用反引号(``)标识

特点:

  1. 字符串中可以出现换行符
  2. 可以使用 ${xxx} 形式输出变量
// 模板字符串的声明
let str = `Hello`;
console.log(str, typeof str); /* Hello string */

// 1. 字符串中可以出现换行符
let str1 = `<ul>
                <li>Item 1</li>
                <li>Item 2</li>
            </ul>`;

// 2. 字符串中可以出现变量
let name = "John";
let str2 = `Hello ${name}`;
console.log(str2); /* Hello John */

// 3. 字符串中可以出现表达式
let age = 25;
let str3 = `I am ${age + 1} years old`;
console.log(str3); /* I am 26 years old */

// 4. 字符串中可以出现函数调用
let str4 = `The result is ${add(1, 2)}`;
function add(a, b) {
  return a + b;
}
console.log(str4); /* The result is 3 */

4. 箭头函数

ES6 允许使用「箭头」(=>)定义函数。

// 声明一个基本的函数
let fn1 = function (a, b) {
  return a + b;
};
fn1(1, 2); // 调用

// 声明一个箭头函数
let fn2 = (a, b) => {
  return a + b;
};
fn2(1, 2); // 调用

箭头函数的注意点:

  1. 如果形参只有一个,则小括号可以省略(不建议)

    let fn = a => { ... };
    
  2. 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果

    let fn = (a, b) => a + b; // qiu'h
    
  3. 箭头函数没有自己的 this(静态 this),它会捕获其所在作用域的 this 值 —— this 的静态特性

    function getName1() {
      console.log(this.name);
    }
    let getName2 = () => {
      console.log(this.name); 
    };
    window.name = "学院";
    let obj = {
      name: "xueyuan"
    };
    // 正常调用
    getName1(); // 学院
    getName2(); // 学院
    // call 方法调用
    getName1.call(obj); // xueyuan
    getName2.call(obj); // 学院,this 指向的是箭头函数所在作用域(window)的 this 值
    
  4. 不能作为构造函数,不能使用 new 关键字实例化对象

    let Person = (name, age) => {
      this.name = name;
      this.age = age;
    };
    //   let me = new Person("张三", 19); // 报错,Person 不能作为构造函数
    //   console.log(me);
    
  5. 不能使用 arguments 变量

    let fn3 = () => {
      console.log(arguments); // 报错,arguments 变量在箭头函数中不存在
    }
    fn3(1, 2, 3);
    

5. rest 参数

ES6 引入 rest 参数,用于获取函数的实参,代替 arguments

// ES5 获取实参的方式
function fn1() {
  console.log(arguments);
}
fn1("张三", "李四", "王五");

// ES6 使用 rest 参数
function fn2(...args) {
  console.log(args);
}
fn2("张三", "李四", "王五");

注意:无论函数的参数有多少个,只要使用了 rest 参数,则 rest 参数必须是最后一个形参。

function fn(a, b, ...., ...args) { ... }

rest 参数非常适合不定个数参数函数的场景

6. spread 扩展运算符

扩展运算符(spread)也是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包

const arr = [1, 2, 3];
function fn() {
  console.log(arguments);
}
fn(...arr);

6.1 扩展运算符的应用

  1. 数组的合并

    const arr1 = [1, 2];
    const arr2 = [3, 4];
    const arr3 = [...arr1, ...arr2]; // [1, 2, 3, 4]
    
  2. 数组的克隆

    const arr4 = [...arr3];
    console.log(arr4); // [1, 2, 3, 4]
    
  3. 将伪数组转为数组

    const divs = document.querySelectorAll("div");
    const arr5 = [...divs];
    console.log(arr5);
    
    let str = "Hello";
    let arr6 = [...str];
    console.log(arr6); // ['H', 'e', 'l', 'l', 'o']
    

7. Symbol

7.1 Symbol 基本使用

ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。

Symbol 特点

  1. Symbol 的值是唯一的,用来解决命名冲突的问题
  2. Symbol 值不能与其他数据进行运算
  3. Symbol 定义 的 对象属 性 不能 使 用 for…in 循 环遍 历 ,但 是可 以 使 用 Reflect.ownKeys 来获取对象的所有键名

创建 Symbol

  1. 基本创建(此时 Symbol 称为对象)

    let s = Symbol();
    console.log(s); // Symbol()
    console.log(typeof s); // symbol
    
    let s1 = Symbol("张三");
    let s2 = Symbol("张三");
    console.log(s1 == s2); // false
    console.log(s1 === s2); // false
    
  2. 使用 Symbol.for 创建(此时 Symbol 称为函数)—— 函数对象

    let s3 = Symbol.for('张三');
    let s4 = Symbol.for('张三');
    console.log(typeof s3); // symbol
    console.log(s3 == s4); // true
    console.log(s3 === s4); // true
    

JS 的七种数据类型:undefinedstringsymbolobjectnullnumberboolean

遇到唯一性的场景时要想到 Symbol,作用:给对象添加属性和方法

7.2 向对象中添加方法

  1. 在不清楚对象的内容、对象较为复杂时,可以使用Symbol向对象添加属性

    let obj = {
      up: function () {
        console.log("上升");
      },
      down: function () {
        console.log("下降");
      },
      ...
    };
    // 声明一个对象
    let methods = {
      up: Symbol(), down: Symbol()
    };
    // 添加方法
    obj[methods.up] = function () {
      console.log("up");
    };
    obj[methods.down] = function () {
      console.log("down");
    };
    
  2. 在对象内容较为简单时,可以使用Symbol作为属性名,来创建对象属性

    let youxi = {
      [Symbol("say")]: function () {
        console.log("发言");
      },
      [Symbol("zibao")]: function () {
        console.log("自爆");
      },
      ...
    };
    

7.3 内置值

除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。

  1. Symbol.hasInstance

    当其他对象使用 instanceof 运算符,判断是否为该对象的实例时,会先调用这个方法。

    class Person {
      static [Symbol.hasInstance](param) {
        console.log(param); // { name: "张三" }
        console.log("检测类型对象");
      }
    }
    let o = { name: "张三" };
    console.log(o instanceof Person); // false
    
  2. Symbol.isConcatSpreadable

    对象的属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat() 时,是否可以展开。

    const arr1 = [1, 2, 3];
    const arr2 = [4, 5, 6];
    arr2[Symbol.isConcatSpreadable] = false;
    console.log(arr1.concat(arr2)); // [1, 2, 3, [4, 5, 6]]
    // arr2[Symbol.isConcatSpreadable] = true;
    // console.log(arr1.concat(arr2)); // [1, 2, 3, 4, 5, 6]
    
  3. Symbol.species

    该属性用于在继承的时候指定一个类的类别。

  4. Symbol.match/replace/search/split

    这四个方法允许我们以对象的方式自定义 String 的 match、replace、search、split 方法,当该对象被 str.match/replace/search/split(myObject) 方法调用时,会返回该方法的返回值。

  5. Symbol.iterator

    对象进行 for…of 循环时,会调用该方法,返回该对象的默认遍历器。

  6. Symbol.toPrimitive

    该对象被转为原始类型的值时,会调该方法,返回该对象对应的原始类型值。

  7. Symbol.toStringTag

    在该对象上面调用 toString 方法时,返回该方法的返回值

  8. Symbol.unscopables

    该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除。

8. 迭代器

遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。

  1. ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费

    for…of 与 for…in 的区别:

    for (let v of arr) {
     console.log(v); // 输出数组元素
    }
    
    for (let v in arr) {
     console.log(v); // 输出索引
    }
    
  2. 原生具备 iterator 接口的数据(可用 for of 遍历)

    1. Array
    2. Arguments
    3. Set
    4. Map
    5. String
    6. TypedArray
    7. NodeList
  3. 工作原理

    1. 创建一个指针对象,指向当前数据结构的起始位置
    2. 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
    3. 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
    4. 每调用 next 方法返回一个包含 value 和 done 属性的对象
const xiyou = ["唐僧", "孙悟空", "猪八戒", "沙和尚"];

for (let v of xiyou) {
  console.log(v);
}
// console.log(xiyou); // 在原型对象上可以看到 Symbol(Symbol.iterator)

let iterator = xiyou[Symbol.iterator](); // 获取数组的迭代器
// 调用 next 方法
console.log(iterator.next()); // { value: "唐僧", done: false }
console.log(iterator.next()); // { value: "孙悟空", done: false }
console.log(iterator.next()); // { value: "猪八戒", done: false }
console.log(iterator.next()); // { value: "沙和尚", done: false }
console.log(iterator.next()); // { value: undefined, done: true }

注:需要自定义遍历数据的时候,要想到迭代器。

8.1 自定义迭代器

// 声明一个对象
let banji = {
  name: "终极一班",
  stus: ["小明", "小红", "小刚", "小李"],
  [Symbol.iterator]() {
    let index = 0; // 索引变量
    return {
      next: () => {
        if (index < this.stus.length) {
          let result =  { value: this.stus[index], done: false };
          index++;
          return result;
        } else {
          return { value: undefined, done: true };
        }
      },
    };
  },
};

// 遍历对象
for (let key of banji) {
  console.log(key);
}

相关文章:

  • 解锁基因密码之重测序(从测序到分析)
  • 快速幂fast_pow
  • [Redis]redis-windows下载安装与使用
  • AI模型多阶段调用进度追踪系统设计文档
  • spark运行架构
  • 神舟平板电脑怎么样?平板电脑能当电脑用吗?
  • DB2数据库专用python库--ibm_db
  • 计算机控制系统:HX1838红外遥控器解码
  • # 深度学习中的优化算法详解
  • 利用高阶函数实现AOP
  • 蓝桥杯第十五届C++B组省赛真题解析
  • Appium工作原理及环境的搭建(1)
  • 系统性能核心指标:QPS、TPS、RT、并发量详解
  • NVIDIA PhysX 和 Flow 现已完全开源
  • 《Sqoop 快速上手:安装 + 测试实战》
  • 绿电直供零碳园区:如何用清洁能源重塑企业竞争力?
  • 力扣刷题day1(java自用)
  • Cursor编程-从入门到精通__0409
  • Java常用工具算法-6--秘钥托管云服务AWS KMS
  • 西门子S7-1200PLC 工艺指令PID_Temp进行控温
  • 网站开发建设流程图/百度业务范围
  • 盐湖网站制作/高端网站优化公司
  • 毕业设计用PHP做旅游网站/windows优化大师是什么
  • 2019做网站需要营业执照吗/网络整合营销4i原则是指
  • 用vue做商城网站常用的js/济南seo培训
  • 网站建设做的人多吗/潍坊seo排名