【js】类(Class)
JavaScript中的Class
- 类的基本语法
- 类的继承
- 修饰器
1.1 定义一个类
ES5
function Student(name,age){
this.name = name
this.age = age
}
Student.prototype = {
constructor:Student,
showName(){
return this.name
}
}
Class
class Student {
constructor(name, age) {
this.name = name
this.age = age
}
showName() {
return this.name
}
}
console.log(Student.prototype);
//{constuctor showName}
class的方法constructor与showName都是定义在原型上的,每个方法之间不用逗号隔开1.2 constructor方法
class默认的方法,没有定义就默认加一个空的方法,在用
new
生成实例时自动调用该方法class Student {
constructor(name, age) {
this.name = name
this.age = age
}
showName() {
return this.name
}
}
const std1 = new Student("张三")
console.log(std1);
//{name:"张三",age:undefined}
与ES5不同的是,定义类不存在变量提升,就是实例化一定要在定义之后1.3 私有方法和私有属性
只在类的内部调用和使用的方法与属性
私有方法
const private1 = Symbol('private1')
const prop1 = Symbol('prop1')
class Studnet {
//公有方法
foo(parm1, parm2) {
//内部使用私有方法
this[private1](parm1)
private2.call(this, parm2)
}
//私有方法
[private1](parm) {
return this[prop1] = parm
}
}
//私有方法
function private2(parm) {
return this.prop2 = parm
}
使用Symbol或者外部的构造函数的方式,可以实现方法内部的私有,实例化的对象不能访问到这些方法私有属性
class Studnet {
#a = 'private'
constructor(a) {
this.a = this.#a
}
get() {
return this.#a
}
}
用#来标识私有属性,在外部不能直接访问这个属性,仅供内部使用1.4 静态方法和静态属性
不能被实例继承的方法与属性
静态方法
class Foo {
static fn1() {
this.fn2()
}
static fn2() {
console.log("Hello");
}
fn2() {
console.log("World");
}
}
Foo.fn1() //"Hello"
let foo = new Foo()
foo.fn2() //"World"
静态方法可以和实例方法重名,静态方法只能在类上调用
class Foo1 extends Foo {
}
Foo1.fn2()// "Hello"
子类可以继承父类的静态方法【【js】类(Class)】静态属性
与静态方法相同,在实例属性前加static即可
class Foo {
static _name = "a"
_name = "b"
}console.log(Foo._name);
//"a"
let foo = new Foo()
console.log(foo._name);
//"b"
静态方法可以与实例方法重名,实例不能继承到静态方法,它属于构造器,不属于原型对象1.5 new.target属性
同样静态方法可以被子类继承
在类中指向该类,父类被继承时指向子类
class Foo {
constructor() {
console.log(new.target);
}
}
class Foo1 extends Foo { }
let foo = new Foo() //Foo
let foo1 = new Foo1()//Foo1
- 用该方法可以控制一些类必须在继承后才能使用
class Foo { constructor() { if (new.target === Foo) { throw new Error("需要先继承") } else { console.log(new.target); } } } class Foo1 extends Foo { } let foo = new Foo() //Error 需要先继承 let foo1 = new Foo1() //Foo1
2.1 super关键字
- 类继承的实质是先创建父类的实例对象this,再用子类的构造函数修改this
- super就为子类提供了父类的this对象,相当于Parent.prototype.constructor.call(this),执行父类构造函数并修改this
class Parent { constructor(x, y) { this.x = x this.y = y } getX() { console.log(this.x); } } class Child extends Parent { constructor(x, y, z) { super(x, y) this.z = z } getY() { console.log(this.y); } } let obj1 = new Child(1, 2, 3) console.log(obj1); //{x:1,y:2,z:3} obj1.getX()//1 obj1.getY()//2
- super指向父类的原型,可以作为一个对象去调用原型上的方法,并修改this指向子类
class Parent { constructor(x) { this.x = x this.y = "a" } getY() { console.log(this.y); } } class Child extends Parent { constructor(x, y) { super(x) this.y = y } runner() { super.getY() } } let obj1 = new Child(1, 2) obj1.runner()//2
super.getY()相当于 Parent.prototype.getY.call(this)
如果Child上没有y属性,则返回父类的y值为"a"
如果Child上有y属性,但实例化的时候没有传值,则返回undefined,不会去原型链上找
class A { }
class B extends A { }
const a1 = new A()
const b1 = new B()//子类的__proto__指向父类
B.__proto__ === A//true
//父类的原型对象是子类原型对象的原型
B.prototype.__proto__ === A.prototype//true
//父类实例的原型是子类实例的原型的原型就
b1.__proto__.__proto__ === a1.__proto__
关键还是在于第二个示例,父类的原型对象是子类原型对象的原型2.3混入(Minxin)
因为类的原型对象就是实例对象的__proto__指向的对象,可以推出第三个示例
实现继承多个类,先将多个类混入到一个类中,再继承
Minxin的实现
//混入
function mix(...mixins) {
class Mix { }
for (let mixin of mixins) {
copyProperties(Max, mixin)
copyProperties(Max.prototype, mixin.prototype)
}
return Mix
}
//拷贝属性
function copyProperties(target, source) {
for (let key of Reflect.ownKeys(source)) {
if (key !== "constructor"
&& ket !== "prototype"
&& key !== "name"
) {
let desc = Object.getOwnPropertyDescriptor(source, key);
Object.defineProperty(target, key, desc)
}
}
}
ES6标准 阮一峰
如果只是
方法的追加则使用
Object.assign(target,source)
即可
3 修饰器(Decorator)
修饰器可以用来修饰类的行为修饰器还在提案中,但是babel转码器已经支持修饰器
可以安装babel的模块去编译 使用了修饰器的写法,转码成向下兼容的ES5写法,这样就可以得到想要的结果
- 这里仅举一个类修饰器的例子
@addStatic class A{}function addStatic(target){ target.hello = "Hello" }
target就是类A, @ + 修饰函数 相当于给类A添加一个静态属性hello
属性修饰器以及其他内容不再举例
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 宽容谁
- 我要做大厨
- 增长黑客的海盗法则
- 画画吗()
- 2019-02-13——今天谈梦想()
- 远去的风筝
- 为什么你的路演总会超时()
- 三十年后的广场舞大爷
- 叙述作文