JavaScript 类的三部曲(二)

4 篇文章 0 订阅
3 篇文章 0 订阅

回顾

  • 第一篇文章我们说了一下关于类的一些基础,本文我们就来进一步的了解类吧
  • 在继续看下去之前,是否可以赏个心心,点点关注呢?

静态方法

  • 什么是类的静态方法?
  • 类的静态方法是在类定义的方法前面加上 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() 不是一个函数

静态属性

静态属性,和上面的静态方法差不多,就是这个类自己的属性,不能通过 thisprototype 来修改和调用

	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 就可以调用这个私有方法。
其实有的时候,就是这么的神奇。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值