目录
1、增强的对象属性
1-1、数组解构
可一次性初始化多个变量。
let [x,y] = [3,4];
console.log(x); // 3
console.log(y); // 4
上面的代码等同于:
let x = 3;
let y = 4;
我们也可以这么批量赋值/改值变量;
let x;
let y;
.....
[x,y] = [7,8];
console.log(x) // 7
console.log(y) // 8
数组解构还可以用于赋值互换。这么做的好处是不需要创建临时变量。
[x,y] = [y,x]
以上等同于:
const temp = x;
x = y;
y = temp;
1-2 、对象解构
和数组的解构差不多
const data = {x:'我是X'};
const {x} = data;
console.log(x); // 我是X
当外面定义的变量和对象里的属性名重名时,应该采取这种方法去解决:
const obj = {name:'123'}
const name = 'tom';
const {name :objName} = obj; // 因为重名,所以把值指向新变量objName
console.log(objName); //123
console.log(name); // tom
当被解构字段缺失时:
const obj = {
a: 1,
};
const { a, b } = obj;
console.log(a, b); // 1 undefined
此时可在解构时使用 = 指定默认值:
const obj = {
a: 1,
};
const { a, b = 2 } = obj;
console.log(a, b); // 1 2
1-3、属性简写
const x = 3;
const y = 4;
const obj = {x,y};
console.log(obj); // {x:3,y:4}
1-4、方法名简写
const test = {
name:'test',
printHi() {
console.log('hi')
}
}
console.log(test.printHi()); // hi
等同于:
const test = {
name:'test',
printHi: function() {
console.log('hi')
}
}
console.log(test.printHi()); // hi
温故知新:
以下代码会输出什么?
const test = {
name:'test',
printHi: function() {
console.log(this.name); // {1}
}
}
console.log(test.printHi()); // {2}
答案:
会返回'test'和undefined
思路:function函数的this随调用对象而指定,行{2}的test调用了printHi.那么此时this指向test对象。所以{1}输出了test.name。而{2}中,printHi无返回值,所以返回undefined
const test = {
name:'test',
printHi: function() {
console.log(this.name); // {1}
}
}
const testB = {name:'abc'}
console.log(test.printHi.call(testB)); // {2}
答案是返回abc和undefined。因为call改变了printHi的指定对象
const book = {
bookName:'test',
printHi: () => {
console.log(this.bookName); // {1}
}
}
book.printHi() // {2}
答案是undefined。箭头函数的this指向是该函数所在作用域(对象{}不是作用域,所以是全局作用域)所指向的对象(全局作用域指向window)
详见上节内容:
2、ES6的面向对象开发----类Class
在ES6之前,我们这样声明一个类:
function Book(title,pages) {
this.title = title;
this.pages = pages;
}
Book.prototype.printTitle= function() {
console.log(this.title)
}
ES6的class开发:
class Book {
constructor(title,pages) {
this.title = title;
this.pages = pages;
}
printTitle() {
console.log(this.title)
}
}
只需要使用class关键字,声明一个有constructor函数和诸如printTitle等其他函数的类。ES6的类是基于JS原型语法的语法糖。所以以上两种写法具有相同的效果和输出。
let book1 = new Book('钢铁',346);
console.log(book1.title); // 钢铁
2-1、继承
ES6中。类的继承由extends完成
class Book {
constructor(title,pages) {
this.title = title;
this.pages = pages;
}
printTitle() {
console.log(this.title)
}
}
class MagicBook extends Book {
constructor(title,pages,methods) {
super(title,pages)
this.methods = methods;
}
throwFire() {
console.log('发射火球,造成35点燃烧伤害')
}
}
使用:
let fireMagic = new MagicBook('古魔法书', 10, '双手结阿尔恩法印')
console.log(fireMagic.methods); // 双手结阿尔恩法印
fireMagic.throwFire(); // 发射火球,造成35点燃烧伤害
2-2、属性存取器
ES6还可以为类属性创建存取器函数。
class Hero {
constructor(name) {
this.name = name;
}
get name() {
return this._name
}
set name(value) {
this._name = value
}
}
const Hero1 = new Hero('奥特曼')
console.log(Hero1.name) // 奥特曼
要想声明get和set函数,我们只需要在我们要暴露和使用的函数名面前加上get或set关键字。
如果我们去掉constructor
class Hero {
get name() {
return this._name
}
set name(value) {
this._name = value
}
}
const Hero1 = new Hero('奥特曼')
console.log(Hero1.name) // undefined
还有一个要注意的点,get和set必须成对出现,如果只声明get不声明set则报错,如果只声明set不声明get则不会报错,但是无法正确读取属性值。
class Hero {
constructor(name) {
this.name = name;
}
get name() {
return `我爱${this._name}`
}
}
const Hero1 = new Hero('奥特曼')
console.log(Hero1.name)
class Hero {
constructor(name) {
this.name = name;
}
set name(value) {
this._name = `${value}不是一个英雄`
}
}
const Hero1 = new Hero('奥特曼')
console.log(Hero1.name)
返回undefined
我们可以看到,get和set其实是对constructor构造过程中的修饰。不信?我们看看:
class Hero {
constructor(name) {
this.name = name;
}
get name() {
return this._name + '是个英雄'
}
set name(value) {
this._name = value
}
}
const Hero1 = new Hero('奥特曼')
console.log(Hero1.name) // 奥特曼是个英雄
class Hero {
constructor(name) {
this.name = name;
}
get name() {
return this._name
}
set name(value) {
this._name = `${value}不是一个英雄`
}
}
const Hero1 = new Hero('奥特曼')
console.log(Hero1.name) // 奥特曼不是一个英雄
同时改变:
class Hero {
constructor(name) {
this.name = name;
}
get name() {
return `成年人都说${this._name}`
}
set name(value) {
this._name = `${value}不是一个英雄`
}
}
const Hero1 = new Hero('奥特曼')
console.log(Hero1.name) // 成年人都说奥特曼不是一个英雄
这里有人会问,为啥上面的例子里都使用_name(下划线加属性名)。
class Hero {
constructor(name) {
this.name = name;
}
get name() {
return this.name
}
set name(value) {
this.name = value
}
}
const Hero1 = new Hero('奥特曼')
console.log(Hero1.name)
这是因为,在构造函数中执行this.name=name的时候,就会去调用set name,在set name方法中,我们又执行this.name = name,进行无限递归,最后导致栈溢出(RangeError)。
3、乘方运算符
就是幂次方。
// ES6
const a = 3 ** 2
等同于
const a = Math.pow(3,2)