ES6的新语法(语法糖)

ES6引入了许多新的语法用过很多了,但是总没有区分开,哪些是es6新加的,最近面试有问到,所以这里整理一下,算是比较全的,这里只涉及到了语法相关的

一、箭头函数:

  • 使用箭头函数可以更简洁地定义函数,并且在函数体内的 this 绑定更符合直觉
  • 如果箭头函数体内只有一个表达式,无需使用 return 关键字,传参只有一个,也可以省略()。
  • 箭头函数的上下文(this 的值)在定义时就已经确定,并且无法通过 callapplybind 来改变
  • 不能作为构造函数使用,不能通过 new 关键字实例化,否则会抛出错误。
  • 箭头函数没有自己的 arguments 对象,它会继承外围函数的 arguments 对象(如果有的话)。
// 传统函数
function add(a, b) {
  return a + b;
}

// 箭头函数
const add = (a, b) => a + b;

二、解构赋值:

解构赋值使得从数据结构中提取和使用值变得更加简洁和方便,同时提高了代码的可读性。

(一)使用方法
  • 可以从数组对象中提取值,并赋给变量。
// 数组解构
const [a, b] = [1, 2];

// 对象解构
const { name, age } = { name: 'John', age: 30 };
  • 函数参数解构:

function printPersonInfo({ name, age }) {
  console.log(`Name: ${name}, Age: ${age}`);
}

const person = { name: 'John', age: 30 };

printPersonInfo(person); // 输出 Name: John, Age: 30
  • 嵌套解构:
const person = {
  name: 'John',
  age: 30,
  address: {
    city: 'New York',
    zip: '10001'
  }
};

const { name, address: { city, zip } } = person;
//注意这里的addres是不能解出的
console.log(name, city, zip); // 输出 John New York 10001
(二)常用场景:
  • 交换变量的值:
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b); // 输出 2 1
  • 提取函数返回的对象的值:
function getPerson() {
  return { name: 'John', age: 30 };
}

const { name, age } = getPerson();
console.log(name, age); // 输出 John 30
  • 从正则表达式匹配中提取值:
const url = 'https://example.com/user/123';

const [, , userID] = url.match(/\/user\/(\d+)/);

console.log(userID); // 输出 123

三、let 和 const:

(一)作用域:

let 声明的变量具有块级作用域,即变量在 {} 内部声明的话,只在该块内部可见
const 声明的变量同样具有块级作用域

(二)变量重新赋值

let 声明的变量可以被重新赋值。
const 声明的变量必须进行初始化,并且不能被重新赋值。一旦赋值,就不能再次更改。

(三)变量提升

letconst不会进行变量提升(hoisting),变量在声明之前是不可用的。

(四)全局对象属性

在全局作用域中使用 let 声明的变量不会成为全局对象的属性。
let 不同,const 在全局作用域中声明的变量会成为全局对象的属性。

const pi = 3.14;
// pi = 3.14159; // 错误:Assignment to constant variable.
console.log(pi); //输出 3.14

if (true) {
  let x = 10;
  console.log(x); // 输出 10
  const y = 20;
  console.log(y); // 输出 20
}

// console.log(x); // 错误:x is not defined
// console.log(y); // 错误:y is not defined

四、模板字符串:

  • 使用 ${}创建多行字符串,可以插入变量。
  • 允许直接换行
  • 模板字符串中还可以包含任意的 JavaScript 表达式
  • 模板字符串可以嵌套在其他模板字符串中
const name = 'John';
const greeting = `Hello, ${name}!`;

五、默认参数值:

  • 可以为函数参数设置默认值,默认值可以使常量,也可以是表达式。
function greet(name = 'Guest') {
  console.log(`Hello, ${name}!`);
}

六、展开运算符(Spread Operator):

(一)展开数组:
1.基本用法:
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];

console.log(arr2); // 输出: [1, 2, 3, 4, 5]
2.复制数组–浅拷贝:
const originalArray = [1, 2, 3];
const copiedArray = [...originalArray];

console.log(copiedArray); // 输出: [1, 2, 3]
console.log(originalArray === copiedArray); // 输出: false,两个数组是独立的
3.合并数组–浅拷贝:
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const mergedArray = [...arr1, ...arr2];

console.log(mergedArray); // 输出: [1, 2, 3, 4, 5, 6]
(二)展开对象:
1.基本用法:
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3, d: 4 };

console.log(obj2); // 输出: { a: 1, b: 2, c: 3, d: 4 }
2.复制对象–浅拷贝
const originalObject = { x: 1, y: 2 };
const copiedObject = { ...originalObject };

console.log(copiedObject); // 输出: { x: 1, y: 2 }
console.log(originalObject === copiedObject); // 输出: false,两个对象是独立的
(三)函数调用中的应用:

将数组作为参数:

function sum(a, b, c) {
  return a + b + c;
}

const numbers = [1, 2, 3];
const result = sum(...numbers);

console.log(result); // 输出: 6
(四)字符串展开:
const str = 'hello';
const letters = [...str];

console.log(letters); // 输出: ['h', 'e', 'l', 'l', 'o']
(五)与 rest 参数结合:

展开运算符可以与 rest 参数结合使用,以更灵活地处理函数的参数。

function example(...args) {
  console.log(args);
}

const numbers = [1, 2, 3, 4, 5];
example(...numbers); // 输出: [1, 2, 3, 4, 5]

七、Rest 参数:

(一)基本用法:
function sum(...numbers) {
  return numbers.reduce((acc, num) => acc + num, 0);
}

console.log(sum(1, 2, 3, 4, 5)); // 输出: 15

…numbers 表示将传递给 sum 函数的所有参数收集到一个名为 numbers 的数组中。

(二)与其他参数结合使用:

Rest 参数可以与其他参数一同使用,但要注意 Rest 参数必须是最后一个参数。

function example(a, b, ...rest) {
  console.log(a, b, rest);
}

example(1, 2, 3, 4, 5); // 输出: 1 2 [3, 4, 5]
(三)Rest 参数的默认值:

Rest 参数可以设置默认值,就像普通参数一样。

function example(a, b, ...rest = []) {
  console.log(a, b, rest);
}

example(1, 2, 3, 4, 5); // 输出: 1 2 [3, 4, 5]
example(1, 2); // 输出: 1 2 []
(四)Rest 参数与解构赋值结合:

Rest 参数可以与解构赋值结合使用,以便更灵活地处理参数。

function example({ a, b, ...rest }) {
  console.log(a, b, rest);
}

example({ a: 1, b: 2, c: 3, d: 4 }); // 输出: 1 2 { c: 3, d: 4 }

八、Promise:

特点:
1、处理异步操作;
2、避免了回调地狱(Callback Hell)和层层嵌套的问题;

(一)Promise 的基本结构:
const myPromise = new Promise((resolve, reject) => {
  // 异步操作,比如从服务器获取数据

  // 如果操作成功,调用 resolve 并传递结果
  resolve(result);

  // 如果操作失败,调用 reject 并传递错误信息
  // reject(error);
});

myPromise
  .then(result => {
    // 处理成功的结果
  })
  .catch(error => {
    // 处理失败的情况
  });
(二)状态(State):
  • Pending(进行中): 初始状态,即操作尚未完成,也没有失败。
  • Fulfilled(已成功): 操作成功完成。
  • Rejected(已失败): 操作失败。
(三)then 方法:

then 方法用于处理 Promise 对象的成功状态,接收一个回调函数,该回调函数在 Promise 状态变为成功时被调用。

myPromise
  .then(result => {
    // 处理成功的结果
  })
  .catch(error => {
    // 处理失败的情况
  });
(四)catch 方法:

catch 方法用于处理 Promise 对象的失败状态,接收一个回调函数,该回调函数在 Promise 状态变为失败时被调用。

myPromise
  .then(result => {
    // 处理成功的结果
  })
  .catch(error => {
    // 处理失败的情况
  });
(五)finally 方法:

finally 方法用于在 Promise 对象的状态变为成功或失败时执行某些操作,无论最终结果是什么都被调用。

myPromise
  .then(result => {
    // 处理成功的结果
  })
  .catch(error => {
    // 处理失败的情况
  })
  .finally(() => {
    // 无论成功或失败都会执行的操作
  });
(六)链式调用:

thencatch 方法可以链式调用,使代码更加清晰。

myPromise
  .then(result => {
    // 处理成功的结果
    return anotherPromise;
  })
  .then(anotherResult => {
    // 处理另一个异步操作的成功结果
  })
  .catch(error => {
    // 处理失败的情况
  });
(七)Promise.all

Promise.all 方法用于等待多个 Promise 对象全部完成,然后返回一个包含所有结果的数组,如果其中任何一个 Promise 失败,则整个操作失败。

const promises = [promise1, promise2, promise3];

Promise.all(promises)
  .then(results => {
    // 处理所有成功的结果
  })
  .catch(error => {
    // 处理失败的情况
  });
(八)Promise.race

Promise.race 方法用于等待多个 Promise 对象中的任何一个完成,然后返回第一个完成的结果,无论是成功还是失败。

const promises = [promise1, promise2, promise3];

Promise.race(promises)
  .then(result => {
    // 处理第一个完成的成功结果
  })
  .catch(error => {
    // 处理第一个完成的失败情况
  });
(九)创建已解决或已拒绝的 Promise:

有时候,我们希望立即创建一个已解决(fulfilled)或已拒绝(rejected)的 Promise 对象,可以使用 Promise.resolvePromise.reject

const resolvedPromise = Promise.resolve('Resolved value');
const rejectedPromise = Promise.reject('Rejected reason');

九、类和继承:

(一)类的基本语法:

使用 class 关键字可以声明一个类。类可以包含构造函数和类方法。

class Animal {
  // 构造函数
  constructor(name) {
    this.name = name;
  }
  // 类方法
  sayName() {
    console.log(`My name is ${this.name}`);
  }
}
// 创建类的实例
const cat = new Animal('Fluffy');
cat.sayName(); // 输出: My name is Fluffy
(二)构造函数和实例属性:

构造函数通过 constructor 方法定义,实例属性直接在构造函数中用 this 关键字声明。

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  sayHello() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  }
}

const john = new Person('John', 30);
john.sayHello(); // 输出: Hello, my name is John and I am 30 years old.
(三)类方法:

类方法是在类的原型上定义的,可以通过实例调用。

class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  // 类方法
  calculateArea() {
    return this.width * this.height;
  }
}

const rectangle = new Rectangle(5, 10);
console.log(rectangle.calculateArea()); // 输出: 50
(四)继承:

使用 extends 关键字可以实现类的继承。子类可以通过 super 关键字调用父类的构造函数和方法。

class Dog extends Animal {
  // 子类构造函数
  constructor(name, breed) {
    // 调用父类构造函数
    super(name);
    this.breed = breed;
  }

  // 子类方法
  bark() {
    console.log('Woof, woof!');
  }

  // 覆盖父类方法
  sayName() {
    console.log(`My name is ${this.name} and I am a ${this.breed}`);
  }
}

const dog = new Dog('Buddy', 'Golden Retriever');
dog.sayName(); // 输出: My name is Buddy and I am a Golden Retriever
dog.bark(); // 输出: Woof, woof!
(五)静态方法:

使用 static 关键字可以定义类的静态方法,静态方法是类的方法而不是实例的方法,可以直接通过类名调用。

class MathUtils {
  static add(x, y) {
    return x + y;
  }

  static subtract(x, y) {
    return x - y;
  }
}

console.log(MathUtils.add(5, 3)); // 输出: 8
console.log(MathUtils.subtract(5, 3)); // 输出: 2
(六)getter 和 setter:

可以使用 getset 关键字定义类的 getter 和 setter 方法。

class Circle {
  constructor(radius) {
    this._radius = radius; // 使用下划线约定表示私有属性
  }

  get radius() {
    return this._radius;
  }

  set radius(value) {
    if (value < 0) {
      throw new Error('Radius cannot be negative');
    }
    this._radius = value;
  }

  get area() {
    return Math.PI * this._radius ** 2;
  }
}

const circle = new Circle(5);
console.log(circle.radius); // 输出: 5
circle.radius = 7;
console.log(circle.area); // 输出: 153.93804002589985
(七)类的继承与构造函数的继承对比:

与构造函数的继承相比,ES6 中的类的继承更为直观和易读。它引入了更多面向对象编程的概念,提供了更丰富的语法糖。

// 构造函数的继承
function Animal(name) {
  this.name = name;
}

Animal.prototype.sayName = function() {
  console.log(`My name is ${this.name}`);
};

function Dog(name, breed) {
  Animal.call(this, name);
  this.breed = breed;
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
  console.log('Woof, woof!');
};

// ES6 类的继承
class Animal {
  constructor(name) {
    this.name = name;
  }

  sayName() {
    console.log(`My name is ${this.name}`);
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }

  bark() {
    console.log('Woof, woof!');
  }
}

十、模块化(import 和 export):

模块化是一种将程序拆分为独立、可维护的模块的编程范式。在 JavaScript 中,模块化的实现主要依赖于 importexport 语法。

(一)导出(Export):

在模块中,可以使用 export 关键字将变量、函数、类或其他代码导出,使其在其他模块中可用。

导出变量:

// math.js
export const pi = 3.14;
export const square = x => x * x;

导出函数:

// utils.js
export function add(a, b) {
  return a + b;
}

export function subtract(a, b) {
  return a - b;
}

导出类:

// shapes.js
export class Circle {
  constructor(radius) {
    this.radius = radius;
  }

  area() {
    return Math.PI * this.radius ** 2;
  }
}

导出默认值:

// main.js
const message = 'Hello, world!';
export default message;
(二)导入(Import):

在其他模块中,可以使用 import 关键字导入导出的变量、函数、类或默认值。

导入具名导出:

// main.js
import { pi, square } from './math';

console.log(pi); // 输出: 3.14
console.log(square(5)); // 输出: 25

导入所有导出:

// main.js
import * as math from './math';

console.log(math.pi); // 输出: 3.14
console.log(math.square(5)); // 输出: 25

导入默认值:

// main.js
import message from './main';

console.log(message); // 输出: Hello, world!

重命名导入:

// main.js
import { pi as circlePi, square as squareFn } from './math';

console.log(circlePi); // 输出: 3.14
console.log(squareFn(5)); // 输出: 25
(三)模块的相对路径:

模块的路径可以是相对路径或绝对路径,相对路径是相对于当前模块的文件路径。

// main.js
import { pi } from './utils/math';

console.log(pi); // 输出: 3.14
(四)导入导出的综合例子:
// math.js
export const pi = 3.14;

export function square(x) {
  return x * x;
}

// shapes.js
export class Circle {
  constructor(radius) {
    this.radius = radius;
  }

  area() {
    return Math.PI * this.radius ** 2;
  }
}

// main.js
import { pi, square } from './math';
import { Circle } from './shapes';

console.log(pi); // 输出: 3.14
console.log(square(5)); // 输出: 25

const myCircle = new Circle(3);
console.log(myCircle.area()); // 输出: 28.26
(五)动态导入:

ES6 还引入了动态导入,可以在运行时根据条件来决定加载哪个模块。

const moduleName = 'math';

import(moduleName)
  .then(mathModule => {
    console.log(mathModule.pi);
  })
  .catch(error => {
    console.error('Failed to load module:', error);
  });

总结:复习一遍后,感觉大部分还是有经常用到的,也确实忘掉了一些,感觉又可以了,冲冲冲!!

  • 31
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值