JavaScript中的类与实例范围

时间:2019-07-10 15:40:47

标签: javascript object singleton es6-class monostate

我正在评估一种在JavaScript中使用称为Monostate的Singleton模式的方法。

我有一些类似以下的代码:

class Boss {
  get name() { return Boss._name }
  set name(value) {
    Boss._name = value;
  }

  get age() { return Boss._age }
  set age(value) {
    Boss._age = value
  }

  toString() {
    return `
      Boss' name is ${this.name}
      and he is ${this.age} years old.
    `
  }
}

Boss._age = undefined;
Boss._name = undefined;

但是我对类作用域和实例作用域之间的区别不甚了解

我的意思是如果我做以下事情:

let boss = new Boss();
boss.name = 'Bob';
boss.age = 55;

let boss2 = new Boss();
boss2.name = 'Tom';
boss2.age = 33;

console.log(boss.toString());
console.log(boss2.toString());

我将始终获取名称为Tom的第二个实例的数据,但是为什么呢?

Boss' name is Tom and he is 33 years old.

3 个答案:

答案 0 :(得分:2)

此行为发生的原因是由于Boss实例引用相同的Boss对象来设置和读取其值。 Boss的实例在_name上设置_ageBoss的值。从这些实例属性读取时,将返回最后一个值集。

您可以通过Boss._name的值每次Boss实例设置其名称时更改的值来查看此内容。在boss.name = 'Bob'之后,Boss._name的值为'Bob'。设置boss2.name = 'Tom'后,Boss._name的值将为'Tom'

我添加了一个片段,希望可以更好地显示令人烦恼的行为。在以下情况下,boss1boss2拥有自己的存储空间,而boss3boss4共享它们的存储空间(您将Boss对象用作存储空间。) >

class Boss {
  constructor(storage) {
    this.storage = storage || {};
  }
  
  get name() {
    return this.storage.name;
  }
  
  set name(value) {
    this.storage.name = value;
  }
}

var boss1 = new Boss(),
    boss2 = new Boss(),
    sharedStorage = {},
    boss3 = new Boss(sharedStorage),
    boss4 = new Boss(sharedStorage);

boss1.name = "a";
boss2.name = "b";
boss3.name = "c";
boss4.name = "d";

console.log(boss1.name, boss2.name, boss3.name, boss4.name);

答案 1 :(得分:0)

Boss没有引用类的实例,而是将引用构造函数Boss,该函数在整个代码中只是一个。在方法中,您不是在实例中添加属性,而是在构造函数中添加属性。

您需要使用this来访问对象方法内的实例。

class Boss {
  get name() { return this._name }
  set name(value) {
    this._name = value;
  }

  get age() { return this._age }
  set age(value) {
    this._age = value
  }
}


let boss = new Boss();
boss.name = 'Bob';
boss.age = 55;

let boss2 = new Boss();
boss2.name = 'Tom';
boss2.age = 33;


console.log(boss2.name);

console.log(boss.name);

答案 2 :(得分:0)

使用this代替类名Boss从类定义中引用对象实例:

class Boss {
  get name() {
    return this._name
  }
  set name(value) {
    this._name = value;
  }

  get age() {
    return this._age
  }
  set age(value) {
    this._age = value
  }

  toString() {
    return `
      Boss' name is ${this.name}
      and he is ${this.age} years old.
    `
  }
}

const b1 = new Boss();
b1.name = 'Tom';
b1.age = 55;

const b2 = new Boss();
b2.name = 'Bill';
b2.age = 33;

console.log(b1.toString());
console.log(b2.toString());

当您确实需要实例时,您在代码中所指的Boss实际上是构造函数。