class 可以理解为构造函数的语法糖。
关于这篇主要掌握相关的语法,最重要的是使用场景。
1、class创建
class ClassSelf {
constructor(name,age,lang){
this.name = name;
this.age = age;
this.lang = lang;
this.a = 11;
this.shot = function(){
console.log('constructor',this.lang)
}
}
shout(){
console.log(this.lang)
}
}
const cat = new ClassSelf('大咪',2,'喵喵');
cat值:
仅对于class ClassSelf 来说:
- constructor方法不用加function,且直接定义在了类的prototype里。
类的prototype不可枚举的( diff1:但构造函数是可以的)
console.log('ClassSelf1:'Object.keys(ClassSelf.prototype))
console.log('ClassSelf2:', Object.getOwnPropertyNames(ClassSelf.prototype))
关于可枚举可简单理解为:Object.keys()可枚举构造函数的prototype,不可枚举class里的函数(虽说也是直接添加到了class的prototype里),但可枚举通过prototype、proto添加的属性。Object.getOwnPropertyNames()无论构造函数还是类都可以取出来可直接给类原型添加新方法
Object.assign(ClassSelf.prototype,{sleep(){}})
2、constructor
是类的默认方法,一个类必须有一个constructor()方法。如果没有显示定义,一个空的constructor()方法会被默认添加。
constructor默认返回实例对象(this),也可指定返回其他对象
constructor(name,age,lang){
this.name = name;
this.age = age;
this.lang = lang;
this.a = 11;
this.shot = function(){
console.log('constructor',this.lang)
}
return {
test:1
}
}
在使用 new生成实例时,会自动调用 constructor函数。
3、类的实例
类必须使用 new 命令生成实例对象,否则报错。( diff2:但构造函数可以不用new,构造函数可以当作普通函数,类不可以)。
- 实例的属性 除非显示定义在本身(即定义在this对象上),否则都是定义在原型上。
❓❎此处存疑:定义在this外的常量也在实例的属性上
解疑:constructor同级的属性 也是实例属性。
class ClassSelf {
constructor(name,age,lang){
this.name = name;
this.age = age;
this.lang = lang;
this.a = 11;
this.shot = function(){
console.log('constructor',this.lang)
}
}
b = 2; //!!!!!!!
shout(){
console.log(this.lang)
}
}
const cat = new ClassSelf('大咪',2,'喵喵');
console.log('cat: ',cat)
console.log('cat Property: ',Object.getOwnPropertyNames(cat))
console.log(cat.hasOwnProperty('b'))
- 所有的实例共享一个原型。使用proto可改写原型 ```javascript const cat = new ClassSelf(‘大咪’,2,’喵喵’); const cat1 = new ClassSelf(‘小咪’,22,’喵喵喵喵’)
cat.proto.say = function(){ console.log(‘say:’,this.name) } cat1.say()
<a name="p6kTo"></a>
### ![image.png](https://cdn.nlark.com/yuque/0/2022/png/1398967/1651029729054-7144fcb2-9588-4b45-9da2-e3444ce028ee.png#clientId=u463176de-e72e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=221&id=u91eb06fc&margin=%5Bobject%20Object%5D&name=image.png&originHeight=442&originWidth=1404&originalType=binary&ratio=1&rotation=0&showTitle=false&size=162613&status=done&style=none&taskId=u31ed5701-0ce6-4336-b1e0-e7f833c6f7e&title=&width=702)
<a name="dCcKe"></a>
### 4 、get set
对某个属性设置存值函数和取值函数,拦截该属性的存取行为。<br />官方解释如上,个人觉得是有点坑的,因为不小心就会会错意。<br />怎么滴个用法呢,如下。
```javascript
class ClassSelf {
constructor(name,age,lang){
this.age = age;
}
get _age(){
return this.age + 'get'
}
set _age(value){
this.age = value+"set"
// this._age = value+"set" 报错 Uncaught RangeError: Maximum call stack size exceeded
}
}
const cat = new ClassSelf('大咪',2,'喵喵');
cat._age = 888
- 间接改变改变值,可以实现数据绑定。
- 通过get定义的属性,只要用户访问该属性就会触发这个get。通过set定义的属性,只要用户修改该属性的值,就会触发set。
❌下述写法会报错
class ClassSelf {
constructor(name,age,lang){
this.age = age;
}
get age(){
return this.age + 'get'
}
set age(value){
this.age = value + 'set'
// return value + 'set' 或者这样
}
}
5、this
实例属性
- 定义在constructor()方法里面的this上面;
- 定义在类的最顶层
好处:看上去比较整洁
class ClassSelf {
constructor(name,age,lang){
//this上的都是实例属性
this.name = name;
this.age = age;
this.lang = lang;
this.a = 11;
this.shot = function(){
console.log('constructor',this.lang)
}
}
b = 2; //实例属性
}
静态方法
如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
class ClassSelf {
constructor(name,age,lang){
this.age = age;
this.name = name;
this.a = 11;
}
static see(){
// console.log('a:',this.a)
// console.log('name:',this.name)
console.log('what do you look!')
}
}
ClassSelf.see() //'what do you look!'
cat.see() //报错:Uncaught TypeError: cat.see is not a function
- 关于静态方法里的this:指的是类,而不是实例。
- 静态方法和非静态方法可以重名。
-
静态属性
静态属性指的是 Class 本身的属性,即class.propName,而不是定义在实例对象(this)上的属性。 ```javascript class ClassSelf {
static s = ‘see’ //es6后的提案写法 }
ClassSelf.s = ‘see’;
<a name="Fa1Mq"></a>
### 私有方法、私有属性
私有方法和私有属性,是只能在类的内部访问的方法和属性,外部不能访问。<br />(ES6 不提供,只能通过变通方法模拟实现)<br />变通方法:
```javascript
//方法3:利用Symbol值的唯一性,将私有方法的名字命名为一个Symbol值
const bar = Symbol('bar');
const snaf = Symbol('snaf');
class ClassSelf {
// 公有方法
foo (baz) {
this._bar(baz);
}
// 私有方法
//方法1:在命名上加以区别,不保险,在类的外部也可以调用
_bar(baz) {
return this.snaf = baz;
}
//方法2:私有方法移出类
foo (baz) {
bar.call(this, baz);
}
foo(baz) {//方法3:
this[bar](baz);
}
[bar](baz) {// 私有方法
return this[snaf] = baz;
}
//提案:方法是在属性名之前,使用#表示
#count = 0;
}
//方法2:
function bar(baz) {
return this.snaf = baz;
}