ES6(一)基础语法

本文介绍了ES6中的新特性,包括let和const声明变量的方式,它们的块级作用域以及不允许重复声明。还讲解了模板字符串的使用,解构赋值在数组和对象中的应用,以及扩展运算符在合并数组和对象、解包和接收剩余参数中的作用。此外,还讨论了类的定义、继承、公有/私有属性和静态属性,以及箭头函数的简洁语法和作用域特点。
摘要由CSDN通过智能技术生成

1. let

使用let进行变量的声明,可以确保该变量只在块级作用域( b l o c k block block s c o p e scope scope)内有效。块级作用域指一个大花括号包裹的作用域,例如functionifwhilefor等语句包含的区域。在块级作用域内使用let定义一个变量,在该作用域外是无法访问的。

{
	let blockScopeVariable = 6;
}
// blockScopeVariable is undefined.

此外,如果当前作用域下已经声明了该变量,也无法再用let重新声明。

var a = 6;
let a = 7;  // error, identifer 'a' has been declared.
var a = 7;  // ok

2. const

使用const可以定义常量。常量一旦定义,就无法更改,并且在同一个作用域下也无法重新定义。const常量同样也只在块级作用域内有效。当然,如果你在全局作用域下定义它,它会成为一个全局常量,在任何地方都无法更改或重新定义。

3. 模版字符串

使用反引号 `` 包裹的字符串被称为模版字符串。其中可以使用${}符号包含一些变量或常量用于填充该字符串。

let age = 18;
console.log(`我今年${age}岁了.`)
// expected output is 我今年18岁了

如果填充的类型不为字符串,将会调用该对象的toString方法进行转化。

4. 解构赋值

4.1 数组解构

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

4.2 对象解构

let { name, age as Age} = {
	name: "吴彦祖",
	age:  40
}
console.log(name);// "吴彦祖"
console.log(Age); // 40
console.log(age); // undefined

5. 数组与对象的扩展

5.1 扩展运算符 ...

扩展运算符...有诸多作用,以下是主要应用场景:

1. 解构赋值

在上面的解构赋值中,可以使用扩展运算符来接收所有剩余数值。

// 数组
let [a, b, ...c] = [1, 2, 3, 4, 5];
console.log(c); // [3, 4, 5]
// 对象
let {name, age, ...privateInfo} = {
	name: "吴彦祖",
	age: 40,
	balance: 10000,
	houseNum: 20
};
console.log(privateInfo); // {"balance": 10000, "houseNum": 20}

2. 解包数组

扩展运算符还可以用来解包可迭代对象,例如数组。基于这种特性,我们可以合并两个数组。

let arr1 = [1, 2, 3]
let arr2 = [4, 5, 6]
let arr3 = [...arr1, ...arr2]; //[1, 2, 3, 4, 5, 6]

如果我们直接将一个数组A赋值给另一个数组B的话,这将会是一个引用赋值。B改变,A也会随之变化。若只想按值进行拷贝赋值的话,可以使用扩展运算符将A中的元素解包出来,再进行赋值。

let arr4 = [...arr3];
arr4[0] = 10;
console.log(arr3); //[1, 2, 3, 4, 5, 6]
console.log(arr4); //[10, 2, 3, 4, 5, 6]

3. 合并对象

与数组合并类似,扩展运算符也可以用来合并对象。

let obj1 = {name: "吴彦祖"};
let obj2 = {age: 40};
let obj3 = {...obj1, ...obj2};
console.log(obj3); // {name: '吴彦祖', age: 40}

4. Rest参数

考虑变长参数的场景。无论形参如何定义,所有传入函数的参数都可以被函数作用域内一名为arguments的类数组对象接收。如果不加形参只使用arguments,我们在函数内部访问传入的参数会变得十分麻烦(遍历截取arguments)。可是如果指定形参,变长参数的处理似乎还得通过arguments。为了解决这一困扰,可以使用扩展运算符来指定Rest参数,该参数必须位于参数列表的最后,可以按数组类型将剩余参数全部接收。

function func(arg1, arg2, ...arg3){
    console.log(arg3)
    console.log(typeof arg3)
}

func(1, 2, 3, 4, 5)
// [3, 4, 5]
// object / arg3是一个数组.

5.2 Array.from()方法

“类数组” (或者称之为可迭代对象)是指一些具有 length 属性并且数值索引从零开始,但是没有Array的内置方法,比如forEach()map(),的一些对象。函数内的参数对象arguments就是一个类数组对象。如果我们想对其使用一些数组专有的方法,可以使用Array.from()将其转化为数组对象。

function func2(){
   let argArray = Array.from(arguments);
   argArray.forEach(function(obj){
       console.log(obj);
   })
}
func2(1, 2, 3);
//expect output: 
// 1 
// 2
// 3

5.3 Object.assign()方法

MDN文档上的介绍是:将一个或者多个源对象中所有可枚举的自有属性复制到目标对象,并返回修改后的目标对象。

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const returnedTarget = Object.assign(target, source);

console.log(target);
// Expected output: Object { a: 1, b: 4, c: 5 }

console.log(returnedTarget === target);
// Expected output: true

returnedTarget.c = 2;
console.log(source)
// Expected output: Object { b: 4, c: 5 }

可以看到,该方法返回的对象与源对象为同一个对象引用,并且,源对象会覆盖目标对象同名属性的值。

6. 类

ES6中的class被用于快速构建大量对象。这种任务在ES5中我们通常借助构造函数来完成,虽然class只是对上述过程提供的一种语法糖,但是使用class的确会让这一过程变得更加优雅自然。

6.1 类定义

使用class关键字可以完成类的定义。在类中,有一种特殊的函数称之为构造方法constructor,可以在类实例被创建时调用。类定义中,只能有一个constructor存在。我们可以为构造方法指定形参,以便在创建实例时传入参数。

// 类属性和类方法定义都无需`function`、`var`、`let`、`const`等关键字
class Animal{
	name; // 声明类属性
	contructor(name, age){
		this.name = name;
		this.age = age; //对象属性赋值
	}
	speak(){ 
		console.log(`${this.name}说话了.`);
	}
}

在上面的例子里,我们创建了一个名为Animal的类,并为其指定了构造方法和speak方法,在构造方法中,我们通过this为其将来的实例创建了两个属性。
与ES5中的构造函数语法相似,class也可以通过new关键字进行实例化。

let animal = new Animal('狗', 10);
animal.speak(); // 狗说话了.

除此之外,我们还可以通过类表达式来创建类。

let Animal = class {};
// let class1 = class Animal {}; // 可创建匿名类,也可创建命名类.

但是请注意,在同一个作用域下,同一个类名只能被声明一次。

6.2 类继承

可以使用extends属性完成类继承。子类会自动获取父类的方法,但是通过this定义的对象属性却不会直接继承,可以在子类的构造函数中,通过super()方法调用父类构造函数来继承父类的对象属性。

class Dog extends Animal{
	constructor(age){
		super('狗', age);
	}
}

let dog = new Dog(10);
dog.speak(); // 狗说话了.

6.3 公有/私有属性

类中定义的属性,默认为公有属性,类外可以自由访问。而在类名之前添加#符号定义的属性,皆为私有属性,只能在类内方法中进行访问。当然可以由类内方法将私有变量与方法暴露给外界访问。

class Cat extends Animal{
	#PRIVATE_VARIABLE; // 私有变量声明
	constructor(age){
		this.age = age;
	}
	#PRIVATE_METHOD(){
		console.log('这是私有方法.');
	}
	expose(){
		this.#PRIVATE_VARIABLE = 6;
		return this.#PRIVATE_METHOD;
	}
}

let cat = new Cat(10);
cat.#PRIVATE_METHOD();
// Private field '#PRIVATE_METHOD' must be 
// declared in an enclosing class.
cat.expose()(); // Expected Output: 这是私有方法.

此外,私有属性可以在子类调用super()方法时被顺利继承。

class FlowerCat extends Cat{
	constructor(age){
		super(10);
	}
}
let a = new FlowerCat(10);
a.expose();
console.log(a);
// {name: '猫', age: 10, #PRIVATE_VARIABLE: 6}

6.4 静态属性

在类中,可以通过static定义静态属性。该类的所有实例共享同一个静态属性引用,并且外界可以通过类名去调用该类的公有静态方法与变量。

class Person{
	static STATIC_VARIABLE;
	static speak(){
		console.log('人说话了.');
	}
}
console.log(Person.STATIC_VARIABLE);
Person.speak();
//Expected Output: 
// 10 
// 人说话了.

此外,一个类的静态变量只能被静态方法所访问,而不能通过该类实例借助非静态方法所访问。

class Person{
	static speak(){
		console.log('人说话了.');
	}
	func(){
		this.speak();
	}
}
let person = new Person;
person.func(); // TypeError: this.speak is not a function

7. 箭头函数

在ES6中,可以用以下方法定义一个匿名函数:

let func = (a, b) => a + b;

这种定义就等价于:

let func = function(a, b){
	return a + b;
}

好处在于,可以不写function关键字,并且如果函数体只有一个return语句的话,可以省略函数体花括号和return关键字,但是形参列表那个括号不可以省略。
需要注意,如果函数体语句较多,或者只有一条非return语句时,请加上花括号,花括号内的return语句无法省略return关键字。

let func = (a, b)=>{
	a += 10;
	b += 12;
	return a+b;
}

let func1 =()=> {
	console.log('666.');	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值