ES6中的变量 字符串 函数对象

变量 字符串 函数 对象


变量:

let 声明变量:

  • 解决全局污染问题,let 声明的变量不会挂载到全局变量。
  • let 声明的变量,不允许在一个作用域范围内(全局作用域,函数作用域,块级作用域)重复声明 。
  • 块级作用域:{},在块级作用域中定义的变量,在外部无法访问。
  • let 变量不会变量提升,不能在定义之前使用该变量。
  • 在循环中,用 let 声明的变量会进行特殊处理,每次进入循环体,都会开启一个新的作用域,并且将循环变- 量绑定到该作用域(每次循环使用的是一个全新的变量)。
  • 用 let 声明的循环变量在循环结束时会自动销毁。

const 声明常量:

  • const 和 let 完全相同,仅在于 const 声明的变量,必须在变量声明时赋值,而且不可以重新赋值。
  • 多使用 const 避免犯错。
  • const 声明一个对象时,对象里面的属性是可以更改的,仅仅是对象的名不能重新赋值。
  • 在 for 循环中循环变量不能使用 const 常量,在 for in 循环中可以使用。

字符串:

字符串 API(以下全为实例方法):

  • includes(子字符串,开始查找的索引值(可省略,默认从 0 开始)):判断字符串是否包含指定的子字符串。
  • startWith(子字符串,开始查找的索引值(可省略,默认从 0 开始)):是否以指定字符串开头。
  • endWith(子字符串,字符串的长度(可省略,默认为字符串 长度)):是否以指定字符串结尾。
  • repeat(count):将字符串重复指定的次数,重新返回一个新的字符串。

模板字符串:

写在 `` 里面,
要拼接字符串,将要拼接的字符串加在${}里。

1
2
3
4
var level1 = "谢永强";
var level2 = "帅";
var txt = `我感觉${level1}${level2}`;
console.log(txt);

在模板字符串前面加上标记 : String.raw ,可以将模板字符串里面的特殊字符直接输出。

1
2
var text1 = String.raw`谢永强\t真帅!`;
console.log(text1);

函数:

参数默认值:

参数默认值,在定义函数时直接给形参赋值,如果调用函数时不传递参数(或传递 undefined),则使用默认值。
在严格模式下(“use strict”)下形参和 arguments 是脱离的(不再满足一一映射关系),只要给函数加上了参数默认值,该函数会自动变成严格模式下的规则(形参和 arguments 是脱离的)

1
2
3
function test(a, b = 4) {
console.log(a + b);
}

剩余参数:

函数名.length :可得到函数形参的个数
解决参数数量不确定情况下的问题。
实现方法:在函数是形参中加上 (…数组名)就可以了,用一个数组收集剩下的所有参数。
一个函数只能有一个剩余参数。
一个函数如果有剩余参数,剩余参数必须是最后一个参数。

1
2
3
4
5
6
7
8
function sum(a, b, ...args) {
let sum = 0;
sum = sum + a + b;
for (let i = 0; i < args.length; i++) {
sum += args[i];
}
return sum;
}

展开运算符:

作用:将数组的每一项分别提取出来。
语法:在要展开的数组和对象前面加上(…数组名 / …对象名)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let arr = [1, 2, 3, 4, 5, 6, 7, 8];
console.log(...arr);
// 输出结果:1 2 3 4 5 6 7 8

const obj = {
name: "xyq",
age: 20,
sex: "male",
};
const obj1 = {
...obj,
};
console.log(obj1, obj === obj1);

// 输出:
// {name: 'xyq', age: 20, sex: 'male'} false

new.target :可用来判断函数是否用 new 来调用函数。

this 指向:

  1. 通过对象调用函数,this 指向对象
  2. 直接调用函数,this 指向全局对象
  3. 如果通过 new 调用函数,this 指向新创建的对象
  4. 如果通过 apply、call、bind 等调用函数,this 指向指定的数据
  5. 如果是 dom 对象,this 指向事件源

箭头函数:

使用语法

箭头函数是一个函数表达式,理论上,任何使用函数表达式的场景都可以使用箭头函数

1
2
3
4
5
6
7
8
9
10
11
12
// 完整语法:
(参数1, 参数2, ...)=>{
//函数体
}

// 如果参数只有一个,可以省略小括号
参数 => {

}

// 如果箭头函数只有一条返回语句,可以省略大括号,和return关键字
参数 => 返回值

注意细节

  • 箭头函数中,不存在 this、arguments、new.target,如果使用了,则使用的是函数外层的对应的 this、arguments、new.target
  • 箭头函数没有原型
  • 箭头函数不能作用构造函数使用

应用场景

临时性使用的函数,并不会可以调用它,比如:

  • 事件处理函数
  • 异步处理函数
  • 其他临时性的函数
  • 为了绑定外层 this 的函数
  • 在不影响其他代码的情况下,保持代码的简洁,最常见的,数组方法中的回调函数

对象:

变量字面量语法:

成员速写:

如果对象字面量初始化时,成员的名称来自于一个变量,并且和变量的名称相同,则可以进行简写,可将 变量名:变量名 简写成 变量名

方法速写:

可以将:function 省略。

1
2
3
4
5
6
7
8
9
10
function test(name, age, sex) {
return {
name,
age,
sex,
fuc() {
console.log(123);
},
};
}

计算属性名:

有的时候,初始化对象时,某些属性名可能来自于某个表达式的值,在 ES6,可以使用中括号来表示该属性名是通过计算得到的。

1
2
3
4
5
6
7
8
9
const prop1 = "name";
const prop2 = "age";
const prop3 = "sex";
const obj1 = {
[prop1]: "xyq",
[prop2]: 20,
[prop3]: "男",
};
console.log(obj1);

Object 的新增 API:

  • Object.is:
    判断两个对象是否相等,基本和 === 是一致的,除了 NaN 和 NaN 相等 、 +0 和-0 不相等
1
2
3
4
5
6
console.log(Object.is(NaN, NaN), NaN === NaN);
console.log(Object.is(+0, -0), +0 === -0);

// 输出:
// true false
// false true
  • Object.assign:
    用于混合对象(可以用展开运算符实现);
    缺陷:会更改原来的第一个对象,解决方案:第一个参数传递一个空对象
  • Object.getOwnPropertyNames:
    Object.getOwnPropertyNames 方法之前就存在,只不过,官方没有明确要求,对属性的顺序如何排序,如何排序,完全由浏览器厂商决定。
    ES6 规定了该方法返回的数组的排序方式如下:
    先排数字,并按照升序排序
    再排其他,按照书写顺序排序
  • Object.setPrototypeOf
    该函数用于设置某个对象的隐式原型
    比如: Object.setPrototypeOf(obj1, obj2), 相当于: obj1.__proto__ = obj2

类:

传统的构造函数的问题

  • 属性和原型方法定义分离,降低了可读性
  • 原型成员可以被枚举
  • 默认情况下,构造函数仍然可以被当作普通函数使用

类的特点

  • 类声明不会被提升,与 let 和 const 一样,存在暂时性死区
  • 类中的所有代码均在严格模式下执行
  • 类的所有方法都是不可枚举的
  • 类的所有方法都无法被当作构造函数使用
  • 类的构造器必须使用 new 来调用

类的语法:

1
2
3
4
5
6
7
8
class 类名{
constructor(参数){
属性值
}
方法名(){
方法体
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Animal {
// 构造函数,写属性
constructor(type, name, age, sex) {
this.type = type;
this.name = name;
this.age = age;
this.sex = sex;
} // 方法
print() {
console.log(`【种类】:${this.type}`);
console.log(`【名字】:${this.name}`);
console.log(`【年龄】:${this.age}`);
console.log(`【性别】:${this.sex}`);
}
}

类里面属性的获取和更改:

可达到像普通对象一样直接获取,设置属性又不保证安全。

获取:

可定义一个方法

1
2
3
get 属性名(){

}

更改:

定义一个方法

1
2
3
set 属性名(参数){

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Test {
constructor(name, age) {
this.name = name;
this.age = age;
}
set age(val) {
if (val < 0) {
val = 0;
}
this._age = val;
}
get age() {
return this._age;
}
print() {
console.log(this._age);
}
}

const test = new Test("xyq", 21);
console.log(test.age);
test.age = 22;
console.log(test.age);

// 输出结果:
// 21
// 22

静态成员:

直接定义在类上的属性或方法,在类中用关键字 static 定义,不用创建实例对象就可以访问的属性,创建的实例对象不可以访问这个属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Test {
static a = "123";
static b() {
console.log(this.a);
}
constructor(name, age) {
this.name = name;
this.age = age;
}
set age(val) {
if (val < 0) {
val = 0;
}
this._age = val;
}
get age() {
return this._age;
}
print() {
console.log(this.age);
}
}

字段初始化器:

可以将一些有固定值的属性直接写在构造函数外面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Test {
sex = "男";
static a = "123";
static b() {
console.log(this.a);
}
constructor(name, age) {
this.name = name;
this.age = age;
}
set age(val) {
if (val < 0) {
val = 0;
}
this._age = val;
}
get age() {
return this._age;
}
print() {
console.log(this.age);
}
}

类的继承

如果两个类 A 和 B,如果可以描述为:B 是 A,则,A 和 B 形成继承关系则:

  • B 继承自 A
  • A 派生 B
  • B 是 A 的子类
  • A 是 B 的父类

如果 A 是 B 的父类,则 B 会自动拥有 A 中的所有实例成员。

继承的关键字:

extends:继承,用于类的定义
super

  • 直接当作函数调用,表示父类构造函数
  • 如果当作对象使用,则表示父类的原型

注意:

  • ES6 要求,如果定义了 constructor,并且该类是子类,则必须在 constructor 的第一行手动调用父类的构造函数
  • 如果子类不写 constructor,则会有默认的构造器,该构造器需要的参数和父类一致,并且自动调用父类构造器

补充

用 JS 制作抽象类

抽象类:一般是父类,不能通过该类创建对象
正常情况下,this 的指向,this 始终指向具体的类的对象