回顾
- 第一篇文章我们说了一下关于类的一些基础,本文我们就来进一步的了解类吧
- 在继续看下去之前,是否可以赏个心心,点点关注呢?
静态方法
- 什么是类的静态方法?
- 类的静态方法是在类定义的方法前面加上
static
关键字 - 只要看到类定义的方法前面加了
static
关键字,这个就一定是静态方法
class Person {
one() {
console.log('one');
}
static two() {
console.log('to');
}
}
let person = new Person()
person.one() // one
person.two() // Uncaught TypeError: person.two is not a function
- 上面的调用
person.to()
为什么会报错,我相信大家多多少少应该猜到了 - 原因:类定义的静态方法是不能被实例对象所调用的
注意:如果静态方法里出现了 this ,那么这个 this 一定是指向类,而不是指向实例对象的
- 并且,不能通过
one
方法内部执行this.two()
,否则会报错
class Person {
one() {
this.two()
}
static two() {
console.log('to');
}
}
let person = new Person()
person.one() // Uncaught TypeError: this.two is not a function
- 它提示说
this.two
这个方法没有被定义,为什么呢,因为one
是通过person
实例对象调用的,所以one
方法中的this.two
是指向person
这个实例对象的,而person
实例对象上根本就没有two
这个方法,所以报错了
注意点(1)
class Person {
one() {
console.log('one');
}
static two() {
this.prototype.one()
}
}
let person = new Person()
Person.two() // one
- 上面的代码发现了吗,在类中静态方法
two
的内部是可以调用one
方法的, 但是需要通过prototype
来调用。为什么呢?因为类中的静态方法是定义在类本身的原型prorotype
中的,所以调用自然是要通过this.protptype.one()
来调用啦。
注意点(2)
- 还有一个注意点,看下面的代码
class Person {
static one() {
this.two()
}
static two() {
console.log('two');
}
}
Person.one() // two
- 诶!发现了吧,为什么静态方法调用静态方法不用通过
prototype
呢? - 因为静态方法是属于
Person
自己的,并不属于它的原型,当你通过Person.prorotype.one()
调用原型上的one
方法你会发现,它报错了
Person.prototype.one() // Uncaught TypeError: Person.prototype.one is not a function
// 它说 Person.prototype.one() 不是一个函数
静态属性
静态属性,和上面的静态方法差不多,就是这个类自己的属性,不能通过 this
和 prototype
来修改和调用
class Person {
// ...
}
Person.prop = 1;
console.log(Person.prop) // 1
- 静态属性是通过
Person.prop = 1
的方式来创建的,并且不是定义在类里面的 - 当然,上面那种是之前的写法,我们 ES6 的强大,超乎了你想象
- 就是在属性前面添加
static
关键字,没错,就是static
关键字
class Person {
static prop = 1
}
console.log(Person.prop) // 1
你没看错,这次是定义在类的内部,而不是外部,这样做的好处是什么呢,增加代码的整洁以及可阅读性,这样定义在类的内部不是更容易看懂吗?定义在外部容易出问题
私有方法和私有属性
私有方法和私有属性想理解其实蛮简单的, 字面意思嘛,私有方法就是类自己的私人方法呗,别人不能调用这个方法呗,不能被别人知道呗,那私有方法都知道了,私有属性还不是手拿把掐吗?
私有属性
我们先来说说私有属性哈,私有属性捏,就是在属性的前面加上一个 #
,这样就是一个私有属性
class Person {
#prop = 1;
}
let person = new Person()
console.log(Person.prop); // undefined
console.log(person.prop); // undefined
以上代码两个的输出结果都是 undefined
,因为私有属性是不能通过实例对象来调用的,本身的类也不能直接通过 Person.prop
调用
当然,有人会说,你调用这个属性的时候 prop
前面没加 #
,当然是 undefined
啊。
那么好,那我们就加 #
,再来看看结果:
class Person {
#prop = 1;
}
let person = new Person()
console.log(Person.#prop);
// Uncaught SyntaxError: Private field '#prop' must be declared in an enclosing class
console.log(person.#prop);
// Uncaught SyntaxError: Private field '#prop' must be declared in an enclosing class
// 报错的意思是:Private字段'#prop'必须在封闭类中声明
什么意思呢,意思就是,这个私有变量在外部是不能够被访问的,只有在类的内部才可以被访问。
这个问题怎么解决呢?其实有两种方案:
class Person {
#prop = 2;
static add(person) {
return console.log(person.#prop);
}
}
Person.add(new Person()) // 2
上面这段代码是什么意思呢,add
被定义成了一个静态方法,然后通过 Person.add()
来调用 add
这个静态方法,而 add
静态方法内的 person
参数是什么呢?看到调用时传进去的那个 new Person()
的实参吗?
我们可以这样理解,person = new Person()
,嗯,没错,可以这样理解,person
其实就是 Person
的实例,所以这样理解应该是没错的。
class Person {
#prop = 2;
add(person) {
return console.log(person.#prop);
}
}
let person = new Person()
person.add(new Person()) // 2
上面这段代码其实和上上面那段代码是一个意思,不同点就是将 add
方法变成了一个向外公布的方法,意思就是,所有 Person
的实例都可以调用这个方法。
注意了,add
方法中的 person
形参是可以随便定义的,意思就是你可以将 person
改成任何参数,只要符合规则的都行,但是实参是不能更改的,因为如果实参不是 new Person()
的话,形参指向的就不是 Person
这个类,既然不是指向 Person
这个类,那就更不会指向 Person
类中的私有属性 #prop
,那么自然会报错,不信你试试就知道了。
私有方法
私有方法和私有属性的定义方式其实是一样的,在方法的前面加 #
即可。
class Person {
#add() {
console.log('add');
}
}
console.log(Person.prorotype.add) // undefined
私有方法定义之后,是不能通过 Person.prototype.add
去访问的。
那要怎么访问呢?别急,看下面的代码你就知道了
class Person {
#add() {
console.log('add');
}
}
let person = new Person()
person.add // add
看呆了吗?居然这么的神奇,只需要 new
一下,然后再通过实例对象 person.add
就可以调用这个私有方法。
其实有的时候,就是这么的神奇。