类在Javascript中是必需的吗?它们对创建对象有什么影响?

g6ll5ycj  于 2023-01-01  发布在  Java
关注(0)|答案(5)|浏览(93)

请考虑以下示例代码:

class Test {
    say() {
        console.log("I'm a test.");
    }
}

let TestFromClass = new Test();

let TestFromObject = {
    say() {
        console.log("I'm also a test.");
    }
};

TestFromClass.say();    // Output: I'm a test.
TestFromObject.say();   // Output: I'm also a test.

我知道可以创建对象,比如TestFromObject,而不必先创建一个带有class关键字的类。class有必要吗?这两种对象之间有区别吗?如果有区别,显式使用class有什么影响?

pgccezyw

pgccezyw1#

使用new创建一个新对象,其内部原型是类的原型。例如:

class Test {
    say() {
        console.log("I'm a test.");
    }
}

let TestFromClass = new Test();
console.log(Object.getPrototypeOf(TestFromClass) === Test.prototype);

这对于创建多个对象很有用。这样做的通常原因是每个对象都可以具有某种关联的 state -通常是其属性值。例如,Person对象可能具有nameage属性。
但是,如果没有数据与示例关联(如原始代码中的TestFromClass),那么拥有示例就没有多大意义。如果目的只是将命名函数收集到数据结构中,则TestFromObject方法更有意义。
也就是说,有时候需要一个类有一些与之关联的函数(比如say),这些函数与其数据的示例没有任何关系,* 同时 * 仍然能够创建示例--也许可以使用原型上的其他方法。这并不罕见,可以通过使非示例相关的函数static来实现:

class Person {
  static canEat() {
    return ['apples', 'bananas', 'carrots'];
  }
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}
const p = new Person('Bob', 99);
console.log(p.name);
console.log(Person.canEat());
nukf8bse

nukf8bse2#

类或多或少只是原型的语法糖:

// The class way
class Test {
  say() {
    console.log("I'm a test.");
  }
}

// The old fashioned way
function Test() {

}

Test.prototype.say = function () {
  console.log("I'm a test.");
};

这两种情况与直接创建对象的区别在于方法属于原型,而不是直接属于对象。
代码TestFromClass.say()必须遍历原型链才能找到say方法,而TestFromObject直接拥有该方法。
除此之外,没什么区别。

6jygbczu

6jygbczu3#

这两种对象之间有区别吗?如果有,显式使用class有什么效果?
实际上没有什么有意义的区别,但它确实有一些小的影响:

  • 当使用文本语法创建对象时,除非使用特殊的__proto__属性名,否则其原型将始终为Object.prototype。(请注意,__proto__是正式的“可选”,JavaScript引擎不必提供它。)当您使用new X创建它时,假设X是使用class语法创建的构造函数,结果将具有原型X.prototype
  • 在对象字面量中定义的方法直接放在对象上。class X中的方法放在对象 * 继承 * 的X.prototype(非static的方法)上。
qvsjd97n

qvsjd97n4#

对象有两种形式:声明(文字)形式和构造形式。
对象的文本语法如下所示:

var myObj = {
    key: value
    // ...
};

构造的窗体如下所示:

var myObj = new Object();
myObj.key = value;

构造形式和文本形式产生的对象完全相同,唯一的区别是可以在文本声明中添加一个或多个键/值对,而对于构造形式的对象,必须逐个添加属性。
注意:使用“构造形式”来创建对象是非常罕见的,你可能总是想使用字面语法形式,这对于大多数内置对象也是一样的。

**P.S.**要了解更多详细信息,请访问https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/this-object-prototypes/ch3.md

mzillmmw

mzillmmw5#

所以你创建了一个叫做Test的类,它是基类,然后你添加了一个叫做say() {}的方法。

class Test {
    say() {
        console.log("I'm a test.");
    }
}

然后,您创建了Test类的一个示例,如下所示:

let TestFromClass = new Test();

在它下面创建了一个名为TestFromObject的普通JavaScript对象:

let TestFromObject = {
    say() {
        console.log("I'm also a test.");
    }
};

是的,它们都将打印出您对它们的方法的输出:

TestFromClass.say();    // Output: I'm a test.
TestFromObject.say();   // Output: I'm also a test.

只有充分利用所创建类的功能,例如,像这样利用cconstructor()函数,差异才会开始:

class Test {
    constructor() {

    }
    say() {
        console.log("I'm a test.");
    }
}

现在,当我们使用new关键字作为类名时,构造函数会自动被调用,通过构造函数,你也可以访问this,如下所示:

class Test {
    constructor() {
      this.type = 'test';
    }
    say() {
        console.log("I'm a test.");
    }
}

它允许您执行以下操作:

TestFromClass.say();    // Output: I'm a test.
TestFromObject.say();   // Output: I'm also a test.
TestFromClass.type;     // Output: test

构造函数传统上用于在类或类的特定示例中进行一些初始设置。
构造函数通常在创建类的新示例时通过使用一些参数来使用。也许你想指定你创建的Test类有50个问题。你可以像这样传入一个对象到新的Test示例:

let TestFromClass = new Test({ questions: 50 });

你可以随意调用这个对象,我们只调用对象examination,你可以设置这个对象的问题数量。
现在你把这个对象传递给构造函数并调用这个对象,examination如下所示:

class Test {
    constructor(examination) {
      this.questions = examination.questions;
      this.type = 'test';
    }
    say() {
        console.log("I'm a test.");
    }
}

let TestFromClass = new Test({ questions: 50 });

TestFromClass.say();    // Output: I'm a test.
TestFromClass.type;     // Output: test
TestFromClass.questions; // 50

另一件你可以用类对象做的事情是创建一个子类来扩展你的基类的功能,然后你也可以给它添加一些定制的功能。

class Test {
    constructor(examination) {
      this.questions = examination.questions;
      this.type = 'test';
    }
    say() {
        console.log("I'm a test.");
    }
}

class Quiz extends Test {

}

现在,您的测验继承了Test类中的所有方法、函数、属性等,并在其中定义了其他方法。

class Test {
    constructor(examination) {
      this.questions = examination.questions;
      this.type = 'test';
    }
    say() {
        console.log("I'm a test.");
    }
}

class Quiz extends Test {
    constructor(examination) {
    this.topic = examination.topic;
  }
}

现在,为了确保父类的构造函数也被调用,我可以在构造函数中使用super()关键字:

class Test {
    constructor(examination) {
      this.questions = examination.questions;
      this.type = 'test';
    }
    say() {
        console.log("I'm a test.");
    }
}

class Quiz extends Test {
    constructor(examination) {
    super(examination)
    this.topic = examination.topic;
  }
}

然后,您可以示例化该子类,如下所示:

const javascript = new Quiz({topic: 'javascript', questions: 50 });

最后打印出来

javascript.questions; // Output: 50

相关问题