是否有可能创建一个更具动态性的新类型?

时间:2021-08-23 16:11:17

Probably not the correct word. But I want to create a new type in JavaScript. It would have the simple property that one could do this:

可能不是正确的词。但我想在JavaScript中创建一个新类型。它有简单的属性,人们可以这样做:

var inst = new SomeType();
inst.key1.key2 = 'something';
inst.key1.key1.key3 = 'something';

Basically you wouldn't have to declare an object literal to extend further. It would create one automatically.

基本上,您不必声明对象文字进一步扩展。它会自动创建一个。

This would allow me to build complex structures without having to worry about checking for the existence of a property to extend off of.

这将允许我构建复杂的结构,而不必担心检查是否存在延伸的属性。

Instead of doing

而不是做

inst.key1 = {};

inst.key1.key2 = 'data';

one could just do

一个人可以这样做

inst.key1.key2 = 'data';

and the

inst.key1 = {};

would be automatic, i.e. would happen internally.

将是自动的,即将在内部发生。

This does have a practical purpose. Particularly I have a registry pattern which I would use this new type to organize data using a more hierarchical approach.

这确实有一个实际的目的。特别是我有一个注册表模式,我将使用这种新类型来使用更分层的方法来组织数据。

Also, I see a pattern, common in libraries, that tests for the existence of an object literal and then creates one if it does not exist.

此外,我看到一个在库中常见的模式,它测试对象文字的存在,然后在不存在的情况下创建一个模式。

This is a common idiom it seems.

这似乎是一种常见的习语。

2 个解决方案

#1


7  

What you'd like to get can easily be achieved with Harmony proxies (MDN). However, this API is not yet stable, so it's fine to use it in non-critical hobby code, but don't use it in production code (yet).

使用Harmony代理(MDN)可以轻松实现您想要获得的内容。但是,这个API还不稳定,因此可以在非关键业余爱好代码中使用它,但不要在生产代码中使用它(尚未)。

Here's an extremely simple example:

这是一个非常简单的例子:

function getFreeChain(object) {
    var handler = {
        get: function(target, name) {
            if (name in target)
                return target[name];
            var newTarget = target[name] = {};
            return new Proxy(newTarget, handler);
        }
    };
    return new Proxy(object, handler);
}

// Usage:
var obj = {};
var magicalObj = getFreeChain(obj);
magicalObj.a.b.c.d.e.g = 1;
console.log(magicalObj.a.b.c.d.e.g); // 1
console.log(obj.a.b.c.d.e.g);        // 1
obj.x.y.z = 1;                       // TypeError: obj.x is undefined

Note: My example is an implementation of the latest Proxy specification, which is only supported by Firefox . Chrome only supports an old, significantly different version of the API, which can be enabled by turning on "Experimental JavaScript" at chrome://flags/. This old API is ugly, and implementing the previous would require significantly more lines of code, so I'll leave this as an exercise to the reader.

注意:我的示例是最新的Proxy规范的实现,只有Firefox支持。 Chrome只支持旧的,显着不同的API版本,可以通过在chrome:// flags /上打开“实验性JavaScript”来启用。这个旧的API很难看,实现前面的API需要更多的代码行,所以我将把它作为练习留给读者。

Oh, there's a library called DirectProxies.js (superseded by harmony-reflect) which brings the simple Proxy API to Chrome. After including the this library, the previous code will work in Firefox and Chrome (with experiments enabled): http://jsfiddle.net/PAhYL/

哦,有一个名为DirectProxies.js的库(由harmony-reflect取代),它将简单的Proxy API引入Chrome。包含此库后,以前的代码将在Firefox和Chrome中运行(启用实验):http://jsfiddle.net/PAhYL/

#2


0  

Because javascript does not support operator overloading, one could create a really ugly fake operator called ._ as such. If someone wants to implement ._ please edit answer.

因为javascript不支持运算符重载,所以可以创建一个名为._的非常丑陋的伪运算符。如果有人想要实施._请编辑答案。

http://jsfiddle.net/586Sc/

var Obj = function () {
    this.hold = {};
};

Obj.prototype._ = function (key) {
    //implement here;
    return this;
};

var obj = new Obj();

obj._('key1')._('key2')._('key3') = 'barbarella';
console.log(test);

#1


7  

What you'd like to get can easily be achieved with Harmony proxies (MDN). However, this API is not yet stable, so it's fine to use it in non-critical hobby code, but don't use it in production code (yet).

使用Harmony代理(MDN)可以轻松实现您想要获得的内容。但是,这个API还不稳定,因此可以在非关键业余爱好代码中使用它,但不要在生产代码中使用它(尚未)。

Here's an extremely simple example:

这是一个非常简单的例子:

function getFreeChain(object) {
    var handler = {
        get: function(target, name) {
            if (name in target)
                return target[name];
            var newTarget = target[name] = {};
            return new Proxy(newTarget, handler);
        }
    };
    return new Proxy(object, handler);
}

// Usage:
var obj = {};
var magicalObj = getFreeChain(obj);
magicalObj.a.b.c.d.e.g = 1;
console.log(magicalObj.a.b.c.d.e.g); // 1
console.log(obj.a.b.c.d.e.g);        // 1
obj.x.y.z = 1;                       // TypeError: obj.x is undefined

Note: My example is an implementation of the latest Proxy specification, which is only supported by Firefox . Chrome only supports an old, significantly different version of the API, which can be enabled by turning on "Experimental JavaScript" at chrome://flags/. This old API is ugly, and implementing the previous would require significantly more lines of code, so I'll leave this as an exercise to the reader.

注意:我的示例是最新的Proxy规范的实现,只有Firefox支持。 Chrome只支持旧的,显着不同的API版本,可以通过在chrome:// flags /上打开“实验性JavaScript”来启用。这个旧的API很难看,实现前面的API需要更多的代码行,所以我将把它作为练习留给读者。

Oh, there's a library called DirectProxies.js (superseded by harmony-reflect) which brings the simple Proxy API to Chrome. After including the this library, the previous code will work in Firefox and Chrome (with experiments enabled): http://jsfiddle.net/PAhYL/

哦,有一个名为DirectProxies.js的库(由harmony-reflect取代),它将简单的Proxy API引入Chrome。包含此库后,以前的代码将在Firefox和Chrome中运行(启用实验):http://jsfiddle.net/PAhYL/

#2


0  

Because javascript does not support operator overloading, one could create a really ugly fake operator called ._ as such. If someone wants to implement ._ please edit answer.

因为javascript不支持运算符重载,所以可以创建一个名为._的非常丑陋的伪运算符。如果有人想要实施._请编辑答案。

http://jsfiddle.net/586Sc/

var Obj = function () {
    this.hold = {};
};

Obj.prototype._ = function (key) {
    //implement here;
    return this;
};

var obj = new Obj();

obj._('key1')._('key2')._('key3') = 'barbarella';
console.log(test);