当将无效(通过我的规则)值分配给对象的成员时,是否可以发出警告?

时间:2015-10-19 10:46:42

标签: javascript

当我为内置对象的成员分配了错误的值时,Chromium(V8?)发出了警告:

enter image description here

这是我见过的最意外的有用和明确的警告。比较一下,例如,React中没有上下文或有意义的行号的不变违规警告。或者,我在验证函数中发生的console.warn调用远离模块用户实际搞砸的地方。

有没有一种方法可以让我自己的一个类在为一个成员分配一个无效值时抛出一个错误/警告,它会显示在作业旁边,如图所示?

1 个答案:

答案 0 :(得分:4)

是的,您可以使用访问者方法定义属性:

var obj = {
    get foo() {
        return this._foo;
    },
    set foo(value) {
        if (/*...value is invalid...*/) {
            throw new Error(/*...*/);
        }
        this._foo = value;
    }
};

使用时,它们看起来就像普通属性一样:

obj.foo = "some value";
var x = obj.foo;

更多信息:specification | MDN

当然,有了上述内容,一个坚定的人可以改为分配给obj._foo。如果您对此感到担心,可以在IIFE中定义访问者并使用局部变量作为支持值:

var obj = (function() {
    var foo;

    return {
        get foo() {
            return foo;
        },
        set foo(value) {
            if (/*...value is invalid...*/) {
                throw new Error(/*...*/);
            }
            foo = value;
        }
    };
})();

该访问器方法语法只是定义访问器的一种方法;您也可以通过Object.definePropertyspec | MDN)和Object.definePropertiesspec | MDN)(或者同时)在现有对象上执行此操作通过指定第二个参数,使用Object.create [spec | MDN]创建新对象。

defineProperty示例:

var obj = {};
(function() {
    var foo;

    Object.defineProperty(obj, "foo", {
        get: function() {
            return foo;
        },
        set: function(value) {
            if (/*...value is invalid...*/) {
                throw new Error(/*...*/);
            }
            foo = value;
        }
    });
})();

在ES2015中,您也可以在使用class时执行此操作;它看起来很像初始化语法,但在方法之间没有逗号:

class Thingy {
    get foo() {
        return this._foo;
    }
    set foo(value) {
        if (/*...value is invalid...*/) {
            throw new Error(/*...*/);
        }
        this._foo = value;
    }
}

要避免obj._foo问题,您可以使用WeakMapspec | MDN)来存储由this键入的值:

let Thingy = (() => {
    let foos = new WeakMap();

    class Thingy {
        get foo() {
            return foos.get(this);
        }
        set foo(value) {
            if (/*...value is invalid...*/) {
                throw new Error(/*...*/);
            }
            foos.set(this, value);
        }
    }
})();

我已经使用了foo特定的地图,但您也可以使用this键入的地图将所有您的支持属性存储为对象