在javascript中,对象文字和构造函数中包含值的类之间有什么区别?

在javascript中,对象文字和构造函数中包含值的类之间有什么区别?,javascript,class,object,constructor,Javascript,Class,Object,Constructor,我一直在testcafe中进行端到端测试,在他们的文档中,我发现了页面模型的以下解决方案: class Page { constructor () { this.nameInput = Selector('#developer-name'); } } export default new Page(); 我一直在做一些研究,但我无法理解为什么不能用对象文字来解决这个问题: export const Page = { nameInput: Selecto

我一直在testcafe中进行端到端测试,在他们的文档中,我发现了页面模型的以下解决方案:

class Page {
    constructor () {
        this.nameInput = Selector('#developer-name');
    }
}

export default new Page();
我一直在做一些研究,但我无法理解为什么不能用对象文字来解决这个问题:

export const Page = {
    nameInput: Selector('#developer-name');
}

使用它们的后果是什么?

类可以看作是一个蓝图,它们最终都提供了一个对象。但是,正如对象文字名称所暗示的,您可以直接在那里创建它,然后使用这种“文字”语法。然而,我们将使用一个类来实例化1个基本蓝图中的新实例

let x = { myProp: undefined }
let y = { myProp: undefined }

x.myProp = "test";
y.myProp // undefined
在这里,我们创建了两个单独的实例,但我们必须重复代码

class X { }

let x = new X();
let y = new X();
类不需要重复代码,因为它都封装在X应该是什么的概念中,即蓝图

let x = { myProp: undefined }
let y = { myProp: undefined }

x.myProp = "test";
y.myProp // undefined
与上面[字面上]类似,我们有两个单独的实例,但它更干净、可读性更强,我们希望对这个“X”对象的每个实例所做的任何更改现在都可以在类中简单地更改

还有很多其他好处,甚至还有一个专门用于面向对象编程的范例,请阅读此处了解更多信息:

要进一步探讨构造函数问题。。。在其他语言中,我们有字段。 我相信当你在构造器中分配一个字段时,它只会创建一个类似于underthehood的字段(我说underthehood-like是因为JavaScript是基于原型的,而类语法是语法糖,可以帮助熟悉其他语言中类语法的程序员更容易地编写原型)

下面是C#中的一个例子

在其他语言中,在构造函数中分配字段更像是一种约定,因此我假设这与JavaScript中的字段分配有关


希望这会有所帮助。

通过将其声明为类,您可以在以后识别它所使用的对象类型。constructor.name:

类页面{
构造函数(){
this.nameInput=“something”;
}
//没有逗号
anotherMethod(){
}
}
const pageClass=新页面();
常量pageLiteral={
名称输入:“某物”
,//必须有逗号
anotherMethod(){
}   
}
console.log(“类的构造函数名称:”,pageClass.constructor.Name);//页

console.log(“literal的构造函数名称:”,pageLiteral.constructor.Name);//对象
差别很大,但基本上两者都是JavaScript对象,尽管属性和值不同。列出语言层面上的所有差异将是一个很长的故事,你应该明智地继续阅读和理解,但最重要的差异是:

  • Page
    是一个原型对象:每当使用
    new Page()
    创建类
    Page
    的对象时,构造函数将使用
    this
    调用,它引用的是正在创建的对象,而不是
    Page
    本身。您在对象上访问的任何属性都将沿着所谓的“原型链”进行搜索,包括所谓的原型对象。可以通过
    页面访问此原型对象。prototype
    实际上,您在类
    页面
    中定义的所有方法也是此原型对象的属性。与自己的属性不同,JavaScript中的函数被设计为引用特定于对象的唯一对象或原语,在对象或函数创建期间不必绑定到对象,可以在对象之间共享(例如,属于同一类),并在实际实例上调用,而不是它们可能属于的原型。换句话说,构造函数中的
    this.nameInput
    实际上向使用
    new Page()
    创建的对象添加了名为
    nameInput
    的属性,而不是原型,而构造函数本身(
    构造函数
    )您可能添加到
    Page
    的任何非静态方法都将作为
    Page.prototype
    的属性添加。顺便说一句,正如您自然期望的那样,可以通过
    Page.prototype.constructor
    访问构造函数<代码>Page.prototype.constructor==Page计算结果为
    true

  • 类似于
    {nameInput:…}
    的形式表达式创建了一个原型为
    对象的对象。原型实际上是对象的最基本形式,没有原型,因此没有超类或超出基本对象原型对象所能提供的任何特征。任何这样的
    {…}
    对象似乎通过其原型链拥有的任何属性,包括方法,都是
    对象的属性。原型
    。这就是为什么您可以执行
    ({}).toString()
    ({}).hasOwnProperty(“foobar”)
    对象中实际上没有
    toString
    hasOwnProperty
    属性--
    toString
    hasOwnProperty
    对象的属性。prototype
    引用了两种不同的方法,分别称为
    toString
    hasOwnProperty
    ,JavaScript在对象上创建一个名为
    \uuuuu proto\uuuu
    的特殊属性,该属性引用
    object.prototype
    。这就是它知道如何“走原型链”的方式。顺便说一句,函数本身的名称并不重要——我可以在引用匿名函数的对象上添加一个属性:
    var foo=({});foo.bar=函数(){}
    并使用
    foo.bar()
    调用所述未命名函数

您可能犯的一个错误是将类的对象与类混淆,否则您将无法将
export default class Page{…}
export const Page={nameInput:Selector(…)}
——前者创建一个可作为
页面
访问的类,该类在创建类的对象时用作原型对象,而后者创建一个可作为
页面
访问的对象,该页面包含
名称输入
引用r
new (function() { this.nameInput = Selector("#developer-name"); })();
function Page() {
    this.nameInput = Selector("#developer-name");
}

var foo = new Page();
function Page() {
    this.nameInput = Selector("#developer-name");
}

Page.prototype.bar = function() {
    console.log(this.nameInput);
}

var foo = new Page();
foo.bar();
class Page {
    constructor() {
        this.nameInput = Selector("#developer-name");
    }
    bar() {
        console.log(this.nameInput);
    }
}