类(Class)
目录
类的语法
为什么引入Class?
为了方便原型和原型链的编程书写方式更加像面向对象的方式,使其JavaScript更加完善了构造函数
类与构造函数对比
// ES6以前的构造函数
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.eat = function(){
return '('+ this.age + '岁的' + this.name +'正在吃饭...'+')';
}
var p1 = new Person('张三',3);
p1.eat();
// ES6的构造函数(类)
class Person{
constructor(name, age){
this.name = name;
this.age = age;
}
eat(){
return '('+ this.age + '岁的' + this.name +'正在吃饭...'+')';
}
}
let p2 = new Person('张三',3);
p1.eat();
- 可以是类在某种意义上就是构造函数的升级版
- constructor:指向的就是Person类的构造函数(就算你不写,JavaScript引擎也会自动添加一个空的)
- 在Person类里面编写的方法就是相当于在Person类的原型上编写
- 类的内部的所有定义的方法,都是不可枚举的
- 类必须通过new关键字调用,否则会报错
回到顶部 目录
类的取值函数(getter)和存值函数(setter)
class MyClass {
get name() {
return 'getter';
}
set name(value) {
console.log('setter: '+value);
}
}
var descriptor = Object.getOwnPropertyDescriptor(
CustomHTMLElement.prototype, "name"
);
- 类的get和set和以前的构造函数的是一样的
- 存值函数和取值函数是设置在属性的 Descriptor 对象上的
类的奇葩写法(直接法)
// 1.
const MyClass = class My {
getClassName() {
return My.name;
}
};
let my = new MyClass();
// 2.
const person = new class My {
getClassName() {
return My.name;
}
};
person.getClassName();
- 外部调用用
MyClass
类名,内部调用用My
类名
类注意点
- 类的内部默认就是严格模式
use strict
- 类不存在声明提前,有临时性死区
- this指向会随着调用者改变的
回到顶部 目录
静态方法和静态属性
语法:static 方法/属性
class Person{
static a = 20;
static fn(){
return 'hello';
}
}
Person.fn();
Person.a;
- 静态方法/属性的调用:静态方法是写着原型上面的,但是不能被继承
调用是直接调用:Person.fn();/Person.a;
- 静态方法的this:指向类
- 静态方法可以和非静态方法重名
- 静态方法可以在子类的super对象中调用
私有方法和私有属性
私有方法和私有属性:只能在内部访问,外部不能访问。遗憾的是es6没有面向对象中的私有方法和私有属性
- 第一种方法:在编程界内部人为规定一个,私有的用"_"开头
- 第二种方法:Symbol数据类型(但是Reflect.ownKeys可以查看)
const a = Symbol('a'); const b = Symbol('b'); class myClass{ // 公有方法 foo(baz) { this[a](baz); } // 私有方法 [a](baz) { return this[b] = baz; } }; var c = new myClass(); Reflect.ownKeys(myClass.prototype)
- 第三种方法:
#
前缀代表私有属性(还没有出来)
回到顶部 目录
保证构造函数是通过new调用的
ES6为new命令引入了一个new.target属性,该属性一般用在构造函数之中,返回new命令作用于的那个构造函数
如果构造函数不是通过new命令或Reflect.construct()调用的,new.target会返回undefined
function Person(name) {
if (new.target === Person) {
this.name = name;
} else {
throw new Error('必须使用 new 命令生成实例');
}
}
该方法也可以判断类,毕竟二者区别不大
修饰
- 类修饰:target(类本身)
- 方法修饰:
- target(类的原型对象)
- name(修饰的属性名)
- descriptor(该属性的描述对象)
回到顶部 目录