1 setter/getter
js 中的setter getter 在类封装成了set get
class Person {
constructor(name, age) {
this._name = name;
this._age = age;
}
// Getter for name
get name() { // 注意这里的name 不要和constructor this.name名字一样 可写成this._name
console.log('Getting the name');
return this._name;
}
// Setter for name
set name(newName) {
console.log('Setting a new name');
this._name = newName;
}
}
const person = new Person('Alice', 30);
console.log(person.name); // 输出: Getting the name Alice
person.name = 'Bob'; // 输出: Setting a new name
console.log(person.name); // 输出: Getting the name Bob
2 class修饰符 public
static #private
-
public
:- 在JavaScript中,默认情况下所有类成员都是公共的,不需要使用
public
关键字来标记。
- 在JavaScript中,默认情况下所有类成员都是公共的,不需要使用
-
private
:- JavaScript本身没有内置的
private
关键字。为了实现私有成员,可以使用符号(Symbol)或者闭包来模拟私有成员。 - ES2020引入了私有字段特性,允许使用
#
前缀来定义私有属性和方法。 -
class MyClass { #privateField = 'Private Value'; // 私有属性 constructor() { this.publicField = 'Public Value'; } #privateMethod() { // 私有方法 console.log(obj.#privateField) console.log('This is a private method.'); } publicMethod() { console.log('This is a public method.'); this.#privateMethod(); // 可以在类内部调用 } } const obj = new MyClass(); console.log(obj.publicField); // 输出 "Public Value" // console.log(obj.#privateField) // 报错,无法访问私有属性 只能再类内部访问 // console.log(obj.#privateMethod); // 报错,无法访问私有方法 只能再类内部使用 obj.publicMethod()
- JavaScript本身没有内置的
-
protected
:- JavaScript标准中并没有直接支持
protected
修饰符。要实现类似的功能,可以使用闭包、私有字段结合某些约定或设计模式。
- JavaScript标准中并没有直接支持
-
static
:static
关键字用于定义静态方法和属性,它们不属于类的实例,而是属于类本身。
class MyClass { static staticMethod() { console.log('This is a static method.'); } static staticProperty = 'Static Property'; } MyClass.staticMethod(); // 调用静态方法 console.log(MyClass.staticProperty); // 访问静态属性
3 案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
p {
width: 200px;
height: 100px;
border: 1px solid #000;
}
</style>
</head>
<body>
<input type="text">
<button class="button1">一级</button>
<button class="button2">二级</button>
<p></p>
<script>
const input = document.querySelector('input'),
button1 = document.querySelector('.button1'),
button2 = document.querySelector('.button2')
p = document.querySelector('p');
class Build {
static tips() {
return `温馨提示!`
}
static show_tips() {
//静态方法中调用静态方法直接使用this,这里的this并不是绑定实例的 这里的this是绑定类本身
p.innerHTML = this.tips()
}
constructor(text, color) {
this.text = text
this.color = color
}
show() {
p.innerHTML = this.text + input.value
p.style.color = this.color
}
// js 中的setter getter 再类封装成了set get
set extra(value) {
this.value = value
p.innerHTML = p.innerHTML + this.value
}
get extra() {
return `不是输入的值:${this.text} ${this.value}`
}
}
button1.addEventListener('click', () => {
const build = new Build('一级', 'red') // new 一个实例
build.show()
// build.extra('呢') // 报错 这是一个属性不是个方法
build.extra = '呢'
console.log(build.extra);
})
class BuildSon extends Build {
constructor(text, color, fontsize) {
// 这样是无法执行的this指向混乱 父类和子类都有this 父类和子类的this都是指向各自绑定的实例
/* this.text = text
this.color = color */
super(text, color) //super初始化this ,前super,后this
this.fontsize = fontsize
}
show() {
p.innerHTML = this.text + p.innerHTML
p.style.color = this.color
p.style.fontsize = this.fontsize
}
}
const build2 = new BuildSon('二级', 'pink', '66')
button2.addEventListener('click', () => {
build2.show()
})
p.addEventListener('click', () => {
Build.show_tips() // 静态方法调用直接使用类调用而不是实例调用, 不需要new实例
})
// class修饰符 #private定义私有方法和属性
class MyClass {
#privateField = 'Private Value'; // 私有属性
constructor() {
this.publicField = 'Public Value';
}
#privateMethod() { // 私有方法
console.log(obj.#privateField)
console.log('This is a private method.');
}
publicMethod() {
console.log('This is a public method.');
this.#privateMethod(); // 可以在类内部调用
}
}
const obj = new MyClass();
console.log(obj.publicField); // 输出 "Public Value"
// console.log(obj.#privateField) // 报错,无法访问私有属性 只能再类内部访问
// console.log(obj.#privateMethod); // 报错,无法访问私有方法 只能再类内部使用
obj.publicMethod()
</script>
</body>
</html>
4 类的原型机制
为什么类能实现这样的功能呢?当然和原型离不开关系,因为我们都知道JS是基于原型的语言。js的类也是基于原型的。
他的运行机制主要有三步:
1.类定义
因为当你定义一个类时,实际上你定义了一个构造函数(通过class
关键字),并且在这个构造函数上挂载了一些属性和方法。这些属性和方法实际上是定义在构造函数的prototype
对象上的。
2.创建实例
当你使用new
关键字创建类的实例时,JavaScript引擎会执行以下步骤:
- 创建一个新的空对象。
- 将这个新对象的
__proto__
设置为类的prototype
对象。 - 执行构造函数,并将
this
绑定到新创建的对象上。 - 如果构造函数返回了一个对象,那么这个对象将成为
new
表达式的返回值;否则,返回新创建的对象。
3.访问属性和方法
由于实例的__proto__
指向了类的prototype
对象,所以当你尝试访问实例上的一个属性或方法时,JavaScript会首先在实例自身上查找。如果找不到,它会继续在实例的原型链上查找,直到找到为止,或者直到原型链的末尾(即Object.prototype
)
class MyClass {
#privateField = 'Private Value'; // 私有属性
constructor() {
this.publicField = 'Public Value';
}
#privateMethod() { // 私有方法
console.log(obj.#privateField)
console.log('This is a private method.');
}
publicMethod() {
console.log('This is a public method.');
this.#privateMethod(); // 可以在类内部调用
}
}
const obj = new MyClass();
console.log(obj.__proto__)
console.log(MyClass.prototype)
console.log(obj.__proto__ === MyClass.prototype) //true