【问题标题】:assigning setter / getter for js object为 js 对象分配 setter / getter
【发布时间】:2015-05-09 22:00:59
【问题描述】:

我试图为我的 js“类”分配一个 setter:

function testing(){
    this.value = "content";
    set a(b){
        this.value = b;
    };
}
var test1 = new testing();
test1.a = "nope";

但它在set a(b){ 线上抛出了SyntaxError: missing ; before statement 有人能告诉我正确的语法是什么吗?

【问题讨论】:

  • 尝试使用Object.defineProperty

标签: javascript setter


【解决方案1】:

有几种方法可以做到这一点。

构造函数和Object.defineProperty

要像您一样在构造函数中执行此操作,您可以使用Object.definePropertyObject.defineProperties。例如:

function Testing(){
    this.value = "content";
    Object.defineProperty(this, "a", {
        set: function(b){
            this.value = b;
        }
    });
}

实例

function Testing() {
  this.value = "content";
  Object.defineProperty(this, "a", {
    set: function(b) {
      this.value = b;
    }
  });
}
var t = new Testing();
snippet.log("t.value before: " + t.value);
t.a = "new content";
snippet.log("t.value after: " + t.value);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

(注意:我将第一个 t 设为 Testing 大写,因为这是 JavaScript 中构造函数的压倒性约定。)

构造函数属性和Object.defineProperty使用原型

或者你可以在原型上定义setter:

function Testing(){
    this.value = "content";
}
Object.defineProperty(Testing.prototype, "a", {
    set: function(b){
        this.value = b;
    }
});

实例

function Testing(){
    this.value = "content";
}
Object.defineProperty(Testing.prototype, "a", {
    set: function(b){
        this.value = b;
    }
});
var t1 = new Testing();
snippet.log("t1.value before: " + t1.value);
t1.a = "new content";
snippet.log("t1.value after: " + t1.value);
var t2 = new Testing();
snippet.log("t2.value before: " + t2.value);
t2.a = "new content";
snippet.log("t2.value after: " + t2.value);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

原型的构造函数和对象初始化器

您尝试使用的语法用于对象初始化程序,而不是构造函数。我们可以使用对象初始化器来替换 Testing.prototype,如下所示:

function Testing(){
    this.value = "content";
}
Testing.prototype = {
    constructor: Testing, // The old object had this, so let's maintain it
    set a(b){
        this.value = b;
    }
};

实例

function Testing(){
    this.value = "content";
}
Testing.prototype = {
    constructor: Testing, // The old object had this, so let's maintain it
    set a(b){
        this.value = b;
    }
};
var t1 = new Testing();
snippet.log("t1.value before: " + t1.value);
t1.a = "new content";
snippet.log("t1.value after: " + t1.value);
var t2 = new Testing();
snippet.log("t2.value before: " + t2.value);
t2.a = "new content";
snippet.log("t2.value after: " + t2.value);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

一次性对象的对象初始化器

这只是创建一个一次性对象,而不是可以用来构建一堆这些对象的函数:

var t = {
  value: "content",
  set a(b) {
    this.value = b;
  }
};

实例

var t = {
  value: "content",
  set a(b) {
    this.value = b;
  }
};
snippet.log("t.value before: " + t.value);
t.a = "new content";
snippet.log("t.value after: " + t.value);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

一个构建器函数和原型的Object.create

构造函数(与new 一起使用的函数)并不是城里唯一一种创建带有原型的对象的游戏。如果您愿意,您也可以通过 Object.create 使用构建器功能:

var testingPrototype = {
    set a(b){
        this.value = b;
    }
};
function testing(){
    var obj = Object.create(testingPrototype);
    obj.value = "content";
    return obj;
}

您不要将new 与这些一起使用,因为它们自己创建对象:

实例

var testingPrototype = {
    set a(b){
        this.value = b;
    }
};
function testing(){
    var obj = Object.create(testingPrototype);
    obj.value = "content";
    return obj;
}
var t1 = testing();
snippet.log("t1.value before: " + t1.value);
t1.a = "new content";
snippet.log("t1.value after: " + t1.value);
var t2 = testing();
snippet.log("t2.value before: " + t2.value);
t2.a = "new content";
snippet.log("t2.value after: " + t2.value);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

一个构建器函数,没有原型

最后但同样重要的是,您可以使用构建器函数而不使用原型:

function testing() {
    return {
        value: "content",
        set a(b){
            this.value = b;
        }
    };
}

您也不要将new 与这些一起使用:

实例

function testing(){
    return {
        value: "content",
        set a(b){
            this.value = b;
        }
    };
}
var t1 = testing();
snippet.log("t1.value before: " + t1.value);
t1.a = "new content";
snippet.log("t1.value after: " + t1.value);
var t2 = testing();
snippet.log("t2.value before: " + t2.value);
t2.a = "new content";
snippet.log("t2.value after: " + t2.value);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

【讨论】:

  • 感谢您和@garryp 的回复!两者都有效,但女巫是更好的方法?
  • @Feirell:两者都不是更好。构造函数和构建函数(garryp 向您展示的名称)都是使用 JavaScript 的完全有效的方法。请注意,您不要将 new 与 garryp 之类的构建器函数一起使用(他似乎不愿意更正他的答案;我放弃了)。 garryp 回答中的方法的一个小缺点是您不能为对象分配一个 prototype (具有通用功能的对象底层的对象),这通常很方便。您可以使用构造函数或Object.create 来做到这一点,但不能使用他展示的模式。
  • @Feirell:我在上面添加了第四个示例(在第三个位置)。享受。 :-)
  • Corwder 好的,老实说,我不确定您的意思,您在他的回答的评论部分写道,现在不再可以使用 new 关键字,但是为什么?当我使用你的对象定义模式时,我怎么能从那个“类”中创建多个对象?
  • 你太棒了,我非常感谢你的努力。如果我提醒正确的话,你帮助我解决了我过去遇到的一些其他问题,每次你给自己制造这么多麻烦,在我看来这是不正常的事情,所以我想说谢谢!一个小问题为什么我必须在 Object 前面使用 .defineProperty ?如果我使用您在第一个示例中使用的这种符号样式,会有问题吗?喜欢它是一种糟糕或不常见的风格吗?
【解决方案2】:

在这样的示例中,集合需要成为对象的一部分:

一种方法是这样的:

function testing(){
    var value = "content";
    return {
        set a(b){
            value = b;
        },
        get a() {
            return value;
        }
    };
}
var test1 = new testing();
test1.a = "nope";

http://jsfiddle.net/GarryPas/1s7v0rdn/

【讨论】:

  • new 与非构造函数一起使用是没有意义的。
  • new 来自 OP。
  • 是的,但是 OP 的函数是构造函数。你的不是。
  • 是的,但是 OP 最初的问题是关于 getter 和 setter ;-)
  • @garryp 我很感谢任何帮助,所以是的,它有点超出了范围,但我很感激 :)
猜你喜欢
  • 2016-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-13
  • 1970-01-01
  • 2016-07-01
  • 2012-10-05
相关资源
最近更新 更多