博客列表 >PartIII 05 类成员与类继承(0904fri)

PartIII 05 类成员与类继承(0904fri)

老黑
老黑原创
2020年09月12日 22:11:00835浏览

主要内容:类成员与类继承

  1. 类表达式:其中先有一个构造函数,然后再有方法返回
  2. 类的构造方法
  3. 类实例属性和原型属性
  4. 存取属性 / 存取属性实现数据的双向绑定
  5. 静态成员
  6. 类中的私有成员(私有属性、私有方法)
  7. 类的继承:原生及es6中的class

1. 类表达式

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>类表达式</title>
  7. </head>
  8. <body>
  9. <script>
  10. // 类表达式
  11. let Person = class {
  12. constructor(name) {
  13. this.name = name;
  14. }
  15. sayName() {
  16. return this.name;
  17. }
  18. };
  19. let person = new Person("小丽");
  20. console.log(person.sayName());
  21. // 类做为参数使用
  22. let createObj = function (className, ...args) {
  23. return new className(...args);
  24. };
  25. let obj = createObj(
  26. class {
  27. hello() {
  28. return "hello JS";
  29. }
  30. }
  31. );
  32. console.log(obj.hello());
  33. // 立即实例化一个类表达式, 创建一个单例
  34. // 通常的格式是两个括号:(函数/类声明)(调用参数列表),如果要创建就在前面加个new,否则直接调用就行了。
  35. let user = new (class {
  36. constructor(email) {
  37. this.email = email;
  38. }
  39. getEmail() {
  40. return this.email;
  41. }
  42. })("peter@qq.com");
  43. console.log(user.getEmail());
  44. </script>
  45. </body>
  46. </html>

2. 类的构造方法

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>类的构造方法</title>
  7. </head>
  8. <body>
  9. <script>
  10. class User {
  11. constructor() {
  12. // return this;
  13. // return {};
  14. // __proto__
  15. return Object.create(null);
  16. //这种情况才能产生出真正的空的类。
  17. }
  18. }
  19. const user = new User();
  20. console.log(user);
  21. </script>
  22. </body>
  23. </html>

3. 类实例属性和原型属性

  • 实例属性/方法: 直接绑定到实例上面
  • 原型属性/方法:proto中的东东(o)
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>类实例属性和原型属性</title>
  7. </head>
  8. <body>
  9. <script>
  10. class User {
  11. constructor(id, name) {
  12. // 实例属性: 直接绑定到实例上面
  13. this.id = id;
  14. this.name = name;
  15. // 实例方法:绑定到实例上的方法
  16. this.getName = () => console.log("hello ", this.name);
  17. }
  18. // 原型方法
  19. show() {
  20. console.log(this.id, this.name);
  21. }
  22. }
  23. const user = new User(1, "admin");
  24. console.log(user);
  25. console.log(user.show());
  26. </script>
  27. </body>
  28. </html>


4. 存取属性

  • 在User.prototype原型对象上设置”存取器属性”
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>存取属性</title>
  7. </head>
  8. <body>
  9. <script>
  10. function User(age) {
  11. this.age = age;
  12. }
  13. // 公共方法或属性定义在函数的原型对象上
  14. // 在User.prototype原型对象上设置"存取器属性"
  15. Object.defineProperty(User.prototype, "verifyAge", {
  16. get() {
  17. return this.age;
  18. },
  19. set(value) {
  20. if (value >= 18 && value <= 60) this.age = value;
  21. },
  22. configurable: true, //说明这个属性是可以删除的。
  23. enumerable: true, //这样就可以遍历了。
  24. });
  25. let user = new User(30);
  26. console.log(user);
  27. console.log(user.age);
  28. console.log(user.verifyAge);
  29. user.verifyAge = 40;
  30. user.age = 50;
  31. user.verifyAge = 80;
  32. console.log(user.age);
  33. // 对象的原型永远等于它的构造函数的原型对象,对象上从它的构造函数的原型对象上继承成员(属性和方法)
  34. // console.log(user.__proto__ === User.prototype);
  35. // console.log(user.constructor);
  36. // console.log(user.__proto__ === user.constructor.prototype);
  37. </script>
  38. </body>
  39. </html>

5. 存取属性实现数据的双向绑定

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>存取属性实现数据的双向绑定</title>
  7. </head>
  8. <body>
  9. <input type="text" />
  10. <p></p>
  11. <script>
  12. // 最终的结果是实现input中录入,下面同步将对应信息展示出来
  13. const obj = {};
  14. Object.defineProperty(obj, "hello", {
  15. set(value) {
  16. document.querySelector("input").value = value;
  17. document.querySelector("p").innerHTML = value;
  18. // p就是下面的展示行
  19. },
  20. });
  21. document.addEventListener("input", (ev) => (obj.hello = ev.target.value));
  22. // 这个地方监听input,keyup都可以。
  23. </script>
  24. </body>
  25. </html>

" class="reference-link">

6. 静态成员

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>静态成员</title>
  7. </head>
  8. <body>
  9. <script>
  10. // 静态成员的特征
  11. // 1. 不能被实例访问
  12. // 2. 不能被实例共享
  13. // 3. 必能通过类才可以访问
  14. // 原生
  15. function User() {}
  16. // 函数对象的静态成员就是函数的属性,直接添加
  17. User.site = "php中文网";
  18. User.say = () => `我是 "${User.site}" 的朱老师`;
  19. console.dir(User);
  20. // 下面是对方法的检查,返回true or false
  21. console.log(User.hasOwnProperty("site"));
  22. console.log(User.hasOwnProperty("say"));
  23. console.log(User.hasOwnProperty("constructor"));
  24. console.log(User.hasOwnProperty("call"));
  25. console.log(User.hasOwnProperty("name"));
  26. // ES6中的类实现静态成员
  27. class UserClass {
  28. // 下面这个是原型方法,因为实例方法是写在构造函数中的
  29. hello() {
  30. return "欢迎大家来上我的课程";
  31. }
  32. // 静态属性
  33. static position = "讲师";
  34. // 静态方法
  35. static say() {
  36. return `我是一名 : ${UserClass.position}`;
  37. }
  38. }
  39. // 访问原型方法
  40. console.log(new UserClass().hello());
  41. // 访问静态成员
  42. console.log(UserClass.position); // 这个就需要用类来访问,而非是用实例
  43. console.log(UserClass.say());
  44. </script>
  45. </body>
  46. </html>


7. 类中的私有成员

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>类中的私有成员</title>
  7. </head>
  8. <body>
  9. <script>
  10. // 1. 原生实现私有成员
  11. function User() {
  12. // 私有成员: 是函数中的私有变量/局部变量来充当
  13. let course = "es6编程";
  14. let hello = () => `大家一定要好好学习 [${course}] 课程`;
  15. this.say = () => console.log(hello());
  16. }
  17. new User().say();
  18. // 2. es6实现类中的私有成员
  19. class UserClass {
  20. // 1. 私有属性
  21. #salary;
  22. constructor(salary = 0) {
  23. this.#salary = salary;
  24. }
  25. // 私有属性应该设置getter, setter
  26. // getter
  27. get salary() {
  28. return this.#salary;
  29. }
  30. // setter
  31. set salary(value) {
  32. if (value < this.salary) console.log("禁止降薪,否则辞职");
  33. else this.#salary = value;
  34. }
  35. // 私有方法
  36. #max(arr) {
  37. return Math.max(...arr);
  38. }
  39. // 私有方法只能在类中用
  40. getMax(arr) {
  41. return this.#max(arr);
  42. }
  43. // 静态私有属性
  44. static #hobby = "摄影";
  45. static #eat() {
  46. return "我爱吃肉";
  47. }
  48. static getHobby() {
  49. // 需要设置下这块的方法,否则外部无法访问。因此需要有return。
  50. return UserClass.#eat() + "和 " + UserClass.#hobby;
  51. }
  52. // 原型方法中访问静态成员
  53. getHobby() {
  54. return UserClass.#eat() + "哈哈, 和 " + UserClass.#hobby;
  55. }
  56. }
  57. const user = new UserClass(8888);
  58. console.log(user);
  59. console.log(user.salary);
  60. user.salary = 6666;
  61. console.log(user.salary);
  62. user.salary = 9999;
  63. console.log(user.salary);
  64. console.log(UserClass.getHobby());
  65. // 访问静态私有方法
  66. console.log(new UserClass().getHobby());
  67. // 尽管同名,但其实是访问原型方法
  68. </script>
  69. </body>
  70. </html>

8. 类的继承:原生

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>类的继承:原生</title>
  7. </head>
  8. <body>
  9. <script>
  10. // 原生是通过修改原型链来实现继承
  11. // 1.父类
  12. function Vehicle(fuel, purpose) {
  13. this.fuel = fuel;
  14. this.purpose = purpose;
  15. }
  16. // 公共/原型方法
  17. Vehicle.prototype.show = function () {
  18. return `燃料: ${this.fuel}\n用途: ${this.purpose}\n`;
  19. };
  20. // 2. 子类
  21. function Car(fuel, purpose, color) {
  22. Vehicle.call(this, fuel, purpose);
  23. this.color = color;
  24. }
  25. // 关键代码
  26. // 更新当前子类的原型对象,这样才能实现真正意义上继承
  27. Car.prototype = Object.create(Vehicle.prototype);
  28. // 手工补上constructor
  29. Car.prototype.constructor = Car;
  30. // 子类中重写父类的原型方法
  31. Car.prototype.show = function () {
  32. return Vehicle.prototype.show
  33. .call(this)
  34. // 这段相当于前面父类中的“return `燃料: ${this.fuel}\n用途: ${this.purpose}\n`”
  35. // 在这个后面继续加上了新的子类中加的属性color
  36. .concat(`颜色: ${this.color}\n`);
  37. };
  38. // 实例化子类
  39. const car = new Car("天然气", "商用", "红色");
  40. console.log(car.show());
  41. </script>
  42. </body>
  43. </html>

" class="reference-link">

9. es6中的类继承

  • es6中用类来实现上面用原生实现的类继承。具体对应关系如下图:
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>es6中的类继承</title>
  7. </head>
  8. <body>
  9. <script>
  10. // 父类
  11. class Vehicle {
  12. // 构造方法
  13. constructor(fuel, purpose) {
  14. this.fuel = fuel;
  15. this.purpose = purpose;
  16. }
  17. // 原型方法
  18. show() {
  19. return `燃料: ${this.fuel}\n用途: ${this.purpose}\n`;
  20. }
  21. }
  22. // 子类
  23. class Car extends Vehicle {
  24. constructor(fuel, purpose, color) {
  25. // 调用父类的构造方法
  26. // super()必须是第一条,否则不能正确的生成子类的this
  27. super(fuel, purpose);
  28. this.color = color;
  29. }
  30. // 重写父类的原型方法
  31. show() {
  32. // super:代码父类的原型对象
  33. console.log(super.show === Vehicle.prototype.show);
  34. return super.show().concat(`颜色: ${this.color}\n`);
  35. }
  36. // super(两种身份):
  37. // 1. 当成函数: super()代表父类的构造方法,必须用在子类的构造方法中的第一行
  38. // 2. 当成对象: super用在原型方法/静态方法,代码父类的原型对象
  39. }
  40. // 实例化子类
  41. const car = new Car("新能源", "商用", "绿色");
  42. console.log(car.show());
  43. </script>
  44. </body>
  45. </html>

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议