Javascript:Class构造函数
为什么需要class
在其他语言中class已经是一个早就被实现的功能,在JavaScript中一直到ES6被实现。在class没有实现之前我们是这样写的(如下代码)
function Person(name,sex){
this.name = ''
this.sex='
}
Person.prototype.say=function(){
alert('hello')
}
有了class我们就这么写的,是不是看起来更简洁。甚至对于初学者来说都不需要了解什么是prototype
class Person {
constructor (name,sex) {
this.name = name;
this.sex = sex;
}
say() {
alert('hello')
}
}
个人认为的是:在没有class这个声明之前,可以使用es5来模拟。但是在一定程度上并不是规范。如果新手或者通过其他语言学习者看到这个prototype什么的就比较懵。有了这个class关键字让js做面向对象的设计更完善了
class是什么
定义:类关键字Class 和 constructor 构造函数
类是用于创建对象的模板。 用 class 关键字来创建一个类,类体在一对大括号 {} 中,我们可以在大括号 {} 中定义类成员的位置,如方法或构造函数。 每个类中包含了一个特殊的方法 constructor(),它是类的构造函数,这种方法用于创建和初始化一个由 class 创建的对象。
class ClassName {
constructor() { ... }
}
//定义好类后,我们就可以使用 new 关键字来创建对象:
let site = new ClassName();
创建对象时会自动调用构造函数方法 constructor()。还可以这样创建对象
// 未命名/匿名类
let Runoob = class {
constructor(name, url) {
this.name = name;
this.url = url;
}
};
console.log(Runoob.name);
// output: "Runoob"
// 命名类
let Runoob = class Runoob2 {
constructor(name, url) {
this.name = name;
this.url = url;
}
};
console.log(Runoob.name);
// 输出: "Runoob2"
// 自执行的类
let Runoob =new class {
constructor(name, url) {
this.name = name;
this.url = url;
}
}('name','111');
console.log(Runoob)
constructor 构造方法
构造方法是一种特殊的方法:
- 构造方法名为 constructor()。
- 构造方法在创建新对象时会自动执行。
- 构造方法用于初始化对象属性。
- 如果不定义构造方法,JavaScript 会自动添加一个空的构造方法。
static 静态方法
类(class)通过static
关键字定义静态方法。
静态方法调用直接在类上进行,不能在类的实例上调用。但是父类的静态属性和静态方法,会被子类继承。
静态方法通常用于创建实用程序函数。
class A {
static foo = 100;
static hello() {
console.log('hello world');
console.log(A.foo)
}
}
A.hello()
const a=new A(); // typeError: a.hello is not a function
a.hello()
class B extends A {
}
B.hello() // hello world
注意,静态属性是通过软拷贝实现继承的。
class A { static foo = 100; }
class B extends A {
constructor() {
super();
B.foo--;
}
}
const b = new B();
B.foo // 99
A.foo // 100
上面示例中,foo
是 A 类的静态属性,B 类继承了 A 类,因此也继承了这个属性。但是,在 B 类内部操作B.foo
这个静态属性,影响不到A.foo
,原因就是 B 类继承静态属性时,会采用浅拷贝,拷贝父类静态属性的值,因此A.foo
和B.foo
是两个彼此独立的属性。
但是,由于这种拷贝是浅拷贝,如果父类的静态属性的值是一个对象,那么子类的静态属性也会指向这个对象,因为浅拷贝只会拷贝对象的内存地址。
class A {
static foo = { n: 100 };
}
class B extends A {
constructor() {
super();
B.foo.n--;
}
}
const b = new B();
B.foo.n // 99
A.foo.n // 99
上面示例中,A.foo
的值是一个对象,浅拷贝导致B.foo
和A.foo
指向同一个对象。所以,子类B
修改这个对象的属性值,会影响到父类A
。
私有方法和属性
目前 class 的私有属性特性已经进入了 Stage3 实验阶段,通过 Babel 已经可以使用,并且 Node v12,chrome 中也增加了对私有属性的支持,但这并不妨碍我们用 JS 的现有功能实现一个私有属性特性,以加深对这一概念的理解。
class Person {
_count = 100
// 私有属性外部不可直接设置值,直接访问
// 变量污染,不能设置同名属性 #userName
#user_Name; // 实例上的私有属性,不能直接修改值,不能遍历
static #userName; // 类的静态私有属性,不可继承,无法直接修改,只能通过类内部方法修改
static names = []
get value() {
return this._count
}
set value(num) {
this._count = num
}
constructor(name) {
this.name = name
this.#user_Name = name
Person.#userName = '1111'
Person.names.push(name)
}
userName() {
console.log(Person.#userName)
console.log(this.#user_Name)
}
setUserName(name) {
Person.#userName = name
this.#user_Name = name
Person.names.push(name)
}
sayHi() {
console.log(`我是可以直接设置的名字${this.name}`)
}
}
//
const myPerson = new Person('用户1')
// Object.setPrototypeOf(myPerson,null)
myPerson.sayHi()
console.log('Person', myPerson)
const myPerson2 = new Person('用户2')
// Object.setPrototypeOf(myPerson,null)
myPerson2.sayHi()
console.log('Person', myPerson2)
- 私有属性外部不可直接设置值,直接访问
- 变量污染,不能设置同名属性 #userName
- #user_Name; // 实例上的私有属性,不能直接修改值,不能遍历
- static #userName; // 类的静态私有属性,不可继承,无法直接修改,只能通过类内部方法修改
继承extends和super
- 关键字用于创建一个类,该类是另一个类的子类。
- 子类继承了另一个类的所有方法。
- 继承对于代码可重用性很有用:在创建新类时重用现有类的属性和方法。
- super() 方法引用父类的构造方法。
- 通过在构造方法中调用 super() 方法,我们调用了父类的构造方法,这样就可以访问父类的属性和方法。
class childClass extends parentClass
super 关键字用于访问和调用一个对象的父对象上的函数。。
在构造函数中使用时,super关键字将单独出现,并且必须在使用 this 关键字之前使用。super 关键字也可以用来调用父对象上的函数。
第一种情况,super
作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super
函数。
class A {}
class B extends A {
constructor() {
super();
}
}
第二种情况,super
作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
class A {
p() {
return 2;
}
}
class B extends A {
constructor() {
super();
console.log(super.p()); // 2
}
}
let b = new B();
使用的时候注意事项
- 只能new使用,不能作为方法直接调用会报错
- this调用的是时指向
- 类方法不可枚举
和ES5的区别和相同点
- 与 ES5 不同,类不存在变量提升
- 类的调用必须要使用 new 命令,否则会报错
- 底层还是ES5原型链实现(可称作语法糖)
- 实例的__proto__ 指向 类的prototype
转载自:https://juejin.cn/post/7168762384000122888