前端开发之:ES6Class对象

对象

一个对象是 Javascript 中的引用数据类型。它由键值对构成,每对键值间使用冒号分隔,键值对之间使用逗号分隔。一个对象可以为空或拥有无数个属性。

对象有比较多的应用。它可以用于将相关的数据封装到一起,形成一系列有关联的数据和功能,这些相关数据和功能被封装在一个对象中,这种设计思想就称为面向对象编程。

对于前端开发者来说,对象是非常常见的,它可以用于存储当前页面的状态、响应用户事件等。此外,许多前端框架(如 Vue.js、React 等)都使用对象进行组件化开发和状态管理。

原型链

  1. 在Javascript中,每个对象都有一个内置的属性 [[Prototype]],它指向对象的原型(prototype)。
  2. 对象的原型也可以有自己的原型,这样一直延续下去就形成了原型链。
  3. 在JS中,如果你想要访问一个对象上的某个方法或属性,但该对象本身并没有该方法或属性,那么Javascript会自动查找该对象的原型,
  4. 如果原型上也没有该方法或属性,那么Javascript将继续沿着原型链继续查找,直到找到该方法或属性为止。
  5. 原型链是Javascript中继承的基础,也是Javascript中许多特性的基础之一。

构造函数

  1. 构造函数原型是JS中所有函数对象都具有的一个属性,是一个对象,包含了所有由该构造函数创建的对象所共享的属性和方法。
  2. 通过向构造函数原型对象上添加属性和方法,可以实现多个实例共享同一属性或方法的效果。
  3. 在构造函数中,可以通过this关键字给实例添加一些独特的属性和方法。
//下面的代码演示了使用构造函数和构造函数原型创建一个Person对象,并输出对象的属性。
// 使用构造函数创建一个Person对象
function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.greeting = function() {
  console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};
const person1 = new Person('John', 30);
person1.greeting(); // 输出:Hello, my name is John and I am 30 years old. 
// 在上述示例中,我们首先定义了一个名为Person的构造函数,这个构造函数接收name和age两个参数。
// 然后,我们使用this关键字将这两个参数赋值给新建对象的属性。
// 最后,我们在Person函数的原型对象上添加了一个greeting方法,在方法中输出一条问候语。
// 通过这种方式,我们可以在实例中访问原型中定义的方法和属性。

Class对象

缺点

Class对象的缺点有以下几点:
1. JavaScript中的类是基于原型继承机制实现的语法糖,本质上依然是通过原型链来实现继承,因此如果使用不当,仍然可能造成原型链深度过深、原型污染等问题。
3. Class对象中的getter和setter只能定义在属性的descriptor中,因此不能像普通方法一样被定义在原型上,这使得在Class对象中实现比较复杂的计算属性变得比较困难。
4. 在使用Class对象的继承机制时,必须通过super关键字来引用父类的方法和属性,这在某些情况下并不方便。
5. Class对象中的静态属性和静态方法只能通过Class对象本身来访问,不能被实例所继承。这在一些情况下可能不是很方便。

必要性

  1. 使用Class对象可以实现更完整、更严格的面向对象编程特性,例如封装、继承、多态等概念。
  2. 在Class对象中,可以使用关键字static定义静态属性和方法,这些静态属性和方法可以通过Class对象本身直接访问,而不需要实例化对象。
  3. 此外,Class对象中还支持更加灵活、强大的继承机制,可以实现更加高级的继承特性。
  4. 与此相比,构造函数相对简单,没有这些高级特性。同时,使用Class对象可以让代码更加简洁、易读。

执行原理

  1. ES6中的Class对象是JavaScript中的一种新的语法糖,它是在现有基于原型的继承机制之上引入的一个概念。
  2. 它是JavaScript中一种特殊的函数类型,通过class关键字声明。
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}
console.log(typeof Person) //输出:function
  1. class关键字允许我们去声明一个类,并在这个类的内部去定义一些属性和方法。
  2. 通过类创建实例的过程和构造函数很相似。
  3. 在类的内部,可以定义属性、方法、getter、setter等。
  4. Class对象是一种面向对象编程思想的具体体现,通过它可以封装一些特定的数据和方法到一个对象中,并且可以方便地进行组件化开发和状态管理。
  5. 类声明的执行原理如下:

- 定义类:使用class关键字来定义类,类名一般首字母大写。
- 定义构造函数:通过constructor关键字定义构造函数,用来初始化对象实例。
- 定义方法:在类中定义方法,并将其添加到类原型之中。
- 创建类实例:使用new关键字创建类实例,并传递实例化时需要的参数。
- 访问属性:使用点号(.)访问实例属性,使用this关键字引用类中定义的属性和方法。

// 下面是一个示例,展示如何调用上面示例中定义的Person类,并访问类中定义的属性和方法。
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greeting() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  }
}

// 使用class创建一个对象实例,并调用其中定义的方法
const person = new Person('John', 30);
person.greeting(); // 输出:Hello, my name is John and I am 30 years old.

constructor

  1. 在Class对象中,constructor是一个特殊的方法,它用来构造和初始化对象实例。
  2. 在一个类中,constructor方法会在实例创建时立即执行,并且可以通过this关键字引用当前对象实例。
  3. 在constructor方法中,可以使用this关键字向对象实例中添加属性和方法。
  4. 如果在一个类中没有明确定义constructor方法,那么默认会创建一个空的constructor方法。
  5. 如果需要在实例化对象时传递参数,可以在constructor方法中定义这些参数。
// 下面的代码演示了在Class对象中定义constructor方法和传递参数。
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greeting() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  }
}
// 使用class创建一个对象实例,并调用其中定义的方法
const person = new Person('John', 30);
person.greeting(); // 输出:Hello, my name is John and I am 30 years old.
  1. constructor中的变量

- 在Class对象的constructor方法中,可以定义需要使用的参数和属性,并使用this关键字将它们赋值给对象的实例属性。
- 这些实例属性可以在类的方法中使用,并且可以在Class对象创建的实例中访问。

// 下面是一个示例,展示如何在Class对象的constructor方法中定义属性和方法。
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
    this.gender = "unknown"; // 在constructor方法中定义了一个名为gender的实例属性。
  }

  greeting() {
    console.log(`Hello, my name is ${this.name}, I am ${this.age} years old, and my gender is ${this.gender}.`);
  }
}
const person = new Person("John", 30);
person.gender = "male"; // 将对象实例的gender属性重新赋值为"male"。
person.greeting(); // 输出:Hello, my name is John, I am 30 years old, and my gender is male.
  1. 在使用Class对象时,需要注意以下几点:

- 在一个类中只能定义一个constructor方法,不能重复定义。
- 如果需要继承父类的构造函数,需要在子类的constructor方法中调用super()方法。
- 如果一个类不需要定义构造函数,可以省略constructor方法。
- 在constructor方法中定义的属性和方法都是实例属性和方法,只能通过实例对象进行访问。
- 如果需要定义静态属性和方法,可以使用静态关键字static来定义。静态属性和方法是指与类相关联的属性和方法,可以直接通过类来访问,而不需要创建实例对象。

// 下面的代码演示了在Class对象中定义constructor方法和静态属性和方法。
class Person {
  static species = "human"; // 使用静态关键字定义一个名为species的静态属性。
  static sayHello() { // 使用静态关键字定义一个名为sayHello的静态方法。
    console.log("Hello from Person!");
  }

  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greeting() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  }
}
const person = new Person("John", 30);
person.greeting(); // 输出:Hello, my name is John and I am 30 years old.
console.log(Person.species); // 输出:human
Person.sayHello(); // 输出:Hello from Person!

getter|setter

Class对象的 Descriptor

  1. 用于给对象中的属性或方法加上介绍性质描述的工具方法叫做descriptor。
  2. 每个属性都拥有自己的描述符,它们分别是:value、writable、enumerable、configurable。
描述符定义
value属性的实际值。
writable布尔值,指示属性的值是否可以被更改。
enumerable布尔值,指示属性是否可以在for...in循环中遍历。
configurable布尔值,指示属性是否可以被删除或其描述符是否可以被更改。
// 在对象定义时,使用Object.defineProperty()方法为属性添加介绍性质描述。
// 下面是一个示例,展示如何使用descriptor定义属性描述符。
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

const animal = new Animal("Dog");
Object.defineProperty(animal, "name", { // 使用descriptor定义name属性的描述符。
  value: "Cat",
  writable: false,
  enumerable: false,
  configurable: false
});

animal.speak(); // 输出:Cat makes a noise.
console.log(animal.name); // 输出:Cat

// 在使用descriptor时,需要注意以下几点:

// 1. 使用descriptor定义的属性,如果是不可写的,那么它的值将无法被修改。
// 2. 使用descriptor定义的属性,如果不可枚举,那么它将无法通过for-in循环进行遍历。
// 3. 使用descriptor定义的属性,如果不可配置,那么它将无法被删除或者再次修改描述符。
// 4. 使用descriptor定义的属性,如果没有设置任何描述符,默认情况下它的所有描述符值都为false。

上一篇
下一篇