【问题标题】:Strange JavaScript behaviour (I was expecting recursion)奇怪的 JavaScript 行为(我期待递归)
【发布时间】:2014-02-26 10:52:51
【问题描述】:

我用 JavaScript 写了一个简单的class(因为需要更好的词)。该类创建了两个访问器(get/set)属性,称为foobar,以及两个方法,称为setPropertygetProperty

属性的 get/set 方法调用 getPropertysetProperty,它们依次从属性对象中获取和设置属性。

我希望在这里看到无限递归,其中属性调用方法,调用属性,调用方法......等等。

但它确实有效......而且我对这些值的存储方式和存储位置感到困惑!

示例代码

var Test = (function () {
    return function Test() {
        var $this = this,
            properties = {
                foo: {
                    get: function () { return $this.getProperty("foo"); },
                    set: function (value) { $this.setProperty("foo", value); },
                    enumerable: false,
                    configurable: false
                },
                bar: {
                    get: function () { return $this.getProperty("bar"); },
                    set: function (value) { $this.setProperty("bar", value); },
                    enumerable: false,
                    configurable: false
                }
            };

        Object.defineProperties(this, properties);

        this.getProperty = function (name) {
            console.log("get was definitely called!");
            return properties[name];
        };

        this.setProperty = function (name, value) {
            console.log("set was definitely called!");
            properties[name] = value;
        };
    };
})();

var test = new Test();
//undefined
test.foo = "Hello World";
//set was definitely called!
//"Hello World"
test.bar = 3;
//set was definitely called!
//3
test.foo;
//get was definitely called!
//"Hello World"
test.bar;
//get was definitely called!
//3

很想知道为什么我不只是得到一个“递归过多”的错误!

【问题讨论】:

    标签: javascript recursion methods properties


    【解决方案1】:

    当您调用defineProperties 时,您是在test 对象中创建属性,而不是properties 对象中的属性。

    properties 对象不再用作属性,仅用作属性值的存储。设置foo 属性会将property 对象中的属性定义替换为值。

    当您设置test.foo 属性时,它将调用该属性的设置器代码并将值存储在properties 对象中,但这不会影响test.foo 属性。一旦创建了属性,用于定义它们的对象将不再使用。

    代码有点混乱,因为它首先使用properties 对象作为属性的定义,然后将其重新用于存储属性值。如果为此使用两个单独的对象,则更清楚为什么设置属性不会影响属性本身:

    var Test = (function () {
        return function Test() {
            var $this = this,
                def = {
                    foo: {
                        get: function () { return $this.getProperty("foo"); },
                        set: function (value) { $this.setProperty("foo", value); },
                        enumerable: false,
                        configurable: false
                    },
                    bar: {
                        get: function () { return $this.getProperty("bar"); },
                        set: function (value) { $this.setProperty("bar", value); },
                        enumerable: false,
                        configurable: false
                    }
                },
                storage = {};
    
            Object.defineProperties(this, def);
    
            this.getProperty = function (name) {
                console.log("get was definitely called!");
                return storage[name];
            };
    
            this.setProperty = function (name, value) {
                console.log("set was definitely called!");
                storage[name] = value;
            };
        };
    })();
    

    【讨论】:

    • 一针见血……很好的答案;现在一切都说得通了!
    猜你喜欢
    • 2016-11-07
    • 2015-01-31
    • 2020-11-11
    • 1970-01-01
    • 2016-11-06
    • 2019-04-11
    • 2013-07-23
    • 2017-05-23
    • 1970-01-01
    相关资源
    最近更新 更多