Rebol 真的有 javascript 原型属性的等效项吗?

发布于 2024-10-05 01:26:14 字数 1456 浏览 0 评论 0原文

Gregogy 在这里发表了一篇关于 rebol 和 javascript 的文章 http://blog.revolucent.net /2009/05/javascript-rebol.html

但是当我更深入地比较 javascript 和 rebol 时,我看不出 javascript 原型的 rebol 等价物是什么。因为使用 rebol 中的 make 从另一个对象实例扩展对象实例并不完全像 javascript 原型属性,因为 js 原型允许一次扩展所有实例。

那么我是否弄错了,或者是否有与下面的 rebol 代码等效的代码:

<html>
<head>
</head>

<body>
  <script>        
    function Person(firstName, lastName, sex) {
      this.firstName = firstName;
      this.lastName = lastName;      
      this.whoAreYou = function() {
        alert( "I've been built with Constructor and my name is " + this.firstName + " " + this.lastName);
      }
      this.WhatIsYourSex = function() {
        alert(this.sex);
      }
    };

    Person.prototype.sex = "Man";

  </script>

  <script>
    JaneDoe = new Person("Jane", "Doe");
    JaneDoe.whoAreYou();
    JaneDoe.WhatIsYourSex();
    alert("Are you sure?");
    JaneDoe.sex = "Woman";
    JaneDoe.WhatIsYourSex();
  </script>

</body>
</html>

更新:我当然不关心语法糖。没有什么可以通过重新定义对象来阻止 R2 中的扩展。我的问题不是关于对象实例的扩展,而是关于一次所有实例的扩展:这就是 js 原型属性所允许的。

所以重新表述我的问题: Rebol 是否可以允许通过像 javascript 一样扩展父类来自动扩展子级的所有实例,无论我不关心什么语法?

就性能而言,我确实看到了 R2 和 R3 之间的差异,但就语言功能特性而言,我没有自动扩展所有子对象,这是一个很大的负担,因为我必须自己管理它们,这会非常慢因为它不是由系统本身完成的。如果我想创建一个像 jquery 这样严重依赖这种功能的框架怎么办?这将是一个很大的麻烦。

Gregogy has made a post about rebol and javascript here http://blog.revolucent.net/2009/05/javascript-rebol.html

But as I'm going deeper into comparing javascript and rebol, I can't see what's the equivalent of rebol for javascript prototype. Because extending an object instance from another one with make in rebol isn't exactly like javascript prototype property as js prototype allows to extend ALL instances at once.

So am I mistaken or is there an equivalent of the code below for rebol:

<html>
<head>
</head>

<body>
  <script>        
    function Person(firstName, lastName, sex) {
      this.firstName = firstName;
      this.lastName = lastName;      
      this.whoAreYou = function() {
        alert( "I've been built with Constructor and my name is " + this.firstName + " " + this.lastName);
      }
      this.WhatIsYourSex = function() {
        alert(this.sex);
      }
    };

    Person.prototype.sex = "Man";

  </script>

  <script>
    JaneDoe = new Person("Jane", "Doe");
    JaneDoe.whoAreYou();
    JaneDoe.WhatIsYourSex();
    alert("Are you sure?");
    JaneDoe.sex = "Woman";
    JaneDoe.WhatIsYourSex();
  </script>

</body>
</html>

Update: I don't care about syntactic sugar of course. Nothing prevents extension in R2 by just redefining an object. My question is not about extension of an object INSTANCE but about extension of ALL INSTANCES at once: that's what js prototype property allows.

So to reformulate my question:
Can Rebol allow to also extend AUTOMATICALLY ALL INSTANCES of children by extending the parent class like javascript can whatever the syntax I don't care ?

For performance sure I see the difference between R2 and R3 for one instance but as for language functional feature I don't have automatic extension of all children objects which is a big burden as I'll have to manage them myself which will be quite slow since it's not done by the system itself. What if I want to create a framework like jquery which heavily relies on this kind of feature ? It would be a great hassle.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情绪操控生活 2024-10-12 01:26:14

Oldes 是对的,默认情况下 REBOL 中不存在类似 JS 的原型。但您可以自由创建适合您需求的自己的功能。下面是一个简单的例子,使用嵌套上下文在多个实例之间共享值来模拟 JS 原型:

creature: func [
    /prototype
        field [word!]
        value [any-type!]
    /local result proto
][
    proto: [
        context [
            static: context [
                vars: reduce [
                    'kind "Monkey"
                ]
                extend: func [
                    blk [block!]
                    field [word!]
                    value [any-type!]
                    /local pos
                ][
                    either pos: find/skip blk field 2 [
                        change/only next pos :value
                    ][
                        insert/only insert tail blk reduce field :value
                    ]
                    :value
                ]

                get: func [
                    field [word!]
                ][
                    all [
                        field: any [
                            select/skip this/instance field 2
                            select/skip vars field 2
                        ]
                        first field
                    ]
                ]

                set: func [
                    field [word!]
                    value [any-type!]
                ][

                    extend this/instance field :value
                ]

                prototype: func [
                    field [word!]
                    value [any-type!]
                ][
                    extend vars field :value
                ]

                who-are-you: does [
                    print ["Hello I'm" this/get 'kind this/get 'sex this/get 'first-name join this/get 'last-name "."]
                ]
            ]

            instance: reduce [
                'first-name none
                'last-name none
            ]

            ;exported "API"
            get: system/words/get in static 'get
            set: system/words/get in static 'set
            prototype: system/words/get in static 'prototype
            who-are-you: system/words/get in static 'who-are-you

            this: none
        ]
    ]
    unless object? proto/1 [result: reduce proto append clear proto result] 

    if prototype [proto/1/prototype field :value]

    result: make proto/1 []
    result/this: result
]

creature/prototype 'sex "male"


jane: make creature []
jane/set 'first-name "Jane"
jane/set 'last-name "Rebol"

john: make creature []
john/set 'first-name "John"
john/set 'last-name "Doe"

jane/who-are-you

jane/set 'sex "female"

jane/who-are-you

john/who-are-you

creature/prototype 'kind "Human"

jane/who-are-you
john/who-are-you

Oldes is right, the JS-like prototyping is not present in REBOL by default. But you are free to create own functionality that suits your needs. Here is simple example that uses nested context for value sharing between multiple instances to simulate the JS prototyping:

creature: func [
    /prototype
        field [word!]
        value [any-type!]
    /local result proto
][
    proto: [
        context [
            static: context [
                vars: reduce [
                    'kind "Monkey"
                ]
                extend: func [
                    blk [block!]
                    field [word!]
                    value [any-type!]
                    /local pos
                ][
                    either pos: find/skip blk field 2 [
                        change/only next pos :value
                    ][
                        insert/only insert tail blk reduce field :value
                    ]
                    :value
                ]

                get: func [
                    field [word!]
                ][
                    all [
                        field: any [
                            select/skip this/instance field 2
                            select/skip vars field 2
                        ]
                        first field
                    ]
                ]

                set: func [
                    field [word!]
                    value [any-type!]
                ][

                    extend this/instance field :value
                ]

                prototype: func [
                    field [word!]
                    value [any-type!]
                ][
                    extend vars field :value
                ]

                who-are-you: does [
                    print ["Hello I'm" this/get 'kind this/get 'sex this/get 'first-name join this/get 'last-name "."]
                ]
            ]

            instance: reduce [
                'first-name none
                'last-name none
            ]

            ;exported "API"
            get: system/words/get in static 'get
            set: system/words/get in static 'set
            prototype: system/words/get in static 'prototype
            who-are-you: system/words/get in static 'who-are-you

            this: none
        ]
    ]
    unless object? proto/1 [result: reduce proto append clear proto result] 

    if prototype [proto/1/prototype field :value]

    result: make proto/1 []
    result/this: result
]

creature/prototype 'sex "male"


jane: make creature []
jane/set 'first-name "Jane"
jane/set 'last-name "Rebol"

john: make creature []
john/set 'first-name "John"
john/set 'last-name "Doe"

jane/who-are-you

jane/set 'sex "female"

jane/who-are-you

john/who-are-you

creature/prototype 'kind "Human"

jane/who-are-you
john/who-are-you
转角预定愛 2024-10-12 01:26:14

REBOL 没有等效项。

R3 中的对象是使用任何其他对象作为原型创建的。但一旦创建,它就是一个独立的实体。对用作原型的对象的更改不会影响较新的对象,反之亦然。

REBOL 2 中的对象一旦创建,就无法添加新字段;您真正能做的就是基于旧对象创建一个新对象,但使用新字段。这可能很烦人,因为它可能会破坏对旧对象的引用。

REBOL 3 在这方面要好得多。 extendappend 允许将新字段添加到任何对象。


这个脚本可能会有所帮助: 链接文本

  • 它将目标对象与
    参考对象,并添加任何
    缺少字段:
  • 它是 REBOL 2 代码,因此目标
    对象被副本替换
    而不是扩展
  • ,但它确实通过任何嵌套对象进行递归,因此它可以一次性进行复杂的嵌套更改

REBOL does not have a equivalent.

An object in R3 is created using any other object as a prototype. But once, created, it is an independent entity. Changes to the object that was used as the prototype will not affect the newer object -- or vice versa.

Objects in REBOL 2, once created, cannot have new fields added to them; all you can really do is create a new object based on the old one, but with new fields. That can be annoying, as it may break references to the old object.

REBOL 3 is much better in that way. extend and append allow new fields to be added to any object.


This script may help a little: link text.

  • It compares an target object to a
    reference object, and adds any
    missing fields:
  • It is REBOL 2 code, so the target
    object gets replaced by a copy
    rather than extended
  • but it does recurse through any nested objects, so it can make complex nested changes in one pass
魔法少女 2024-10-12 01:26:14

Rebol教程,你的反应包含太多“我不在乎”的成分,你不觉得吗?顺便说一句,明智的设计 - 到底谁想到了类定义在类实例化发生后影响活动对象的想法? :-)

那么 - 您实际上是否进行了任何测量,以比较在循环中扩展相关对象的速度有多慢?您的说法“……会很慢”可能会显得未经证实。

让我们做一些测量:

<块引用>

obj:上下文[a:1]
== 制作对象! [
答:1
]

dt 循环 1'000'000 [追加 blk 复制 obj]
== 0:00:00.023372

长度?块
== 1000000

dt [foreach obj blk [append obj [b: 2]]]
== 0:00:02.677348

长度?块
== 1000000

大块/1
== 制作对象! [
答:1
乙:2
]

大块/2
== 制作对象! [
答:1
乙:2
]

大块/1/a:3
== 3

大块/1
== 制作对象! [
答:3
乙:2
]

大块/2
== 制作对象! [
答:1
乙:2
]

因此,如您所见,我成功地在 == 0:00:02.677348 时间内使用自定义字段扩展了 100 万个对象。我的机器已经有 4 年历史了。您的应用程序有多少个对象?

我知道这可能不是您想要的,因为您必须构建要扩展的对象列表,但它是一个入门者:-)

-pekr-

Rebol Tutorial, your reactions contain too much of "I don't care", don't you think? And by the way, design wise - who on eart came with an idea of a class definition influencing live objects after class instantiation happened? :-)

So - did you actually do any measurements, to compare how slow it is to extend related objects in a loop? Your claim " ... will be quite slow" might show as unsubstantiated.

Let's do some measurements:

obj: context [a: 1]
== make object! [
a: 1
]

dt loop 1'000'000 [append blk copy obj]
== 0:00:00.023372

length? blk
== 1000000

dt [foreach obj blk [append obj [b: 2]]]
== 0:00:02.677348

length? blk
== 1000000

blk/1
== make object! [
a: 1
b: 2
]

blk/2
== make object! [
a: 1
b: 2
]

blk/1/a: 3
== 3

blk/1
== make object! [
a: 3
b: 2
]

blk/2
== make object! [
a: 1
b: 2
]

So, as you can see, I managed to extend 1 million of objects with custom fields in == 0:00:02.677348 time. I am on 4 years old machine. How many of objects your application have?

I know it's not what you probably want, as you have to build list of objects to extend, but it is a starter :-)

-pekr-

风柔一江水 2024-10-12 01:26:14

我想您出于某种原因不会喜欢这一点:

person: context [
    firstName: secondName: none
    whoAreYou: does [print [firstName secondName]]
    WhatIsYourSex: does [print sex]
]
extend person 'sex "male"
JaneDoe: make person [firstName: "Jane" secondName: "Doe"]
JaneDoe/whoAreYou
JaneDoe/WhatIsYourSex
ask "Are you sure?"
JaneDoe/sex: "female"
JaneDoe/WhatIsYourSex

我必须说,我不会真正使用这样的代码,因为我不明白为什么我应该将数据与函数混合在一起。这只是尝试模仿你的 JS 代码。

但我想,你有错误的例子,你想展示这一点:

<script>
    JaneDoe = new Person("Jane", "Doe");
    DoeJane = new Person("Doe", "Jane");
    Person.prototype.sex = "Man";
    JaneDoe.WhatIsYourSex();
    DoeJane.WhatIsYourSex();
</script>

我必须说,在 REBOL 中不支持这样的东西,至少现在是这样。

I guess you will not like this from some reason:

person: context [
    firstName: secondName: none
    whoAreYou: does [print [firstName secondName]]
    WhatIsYourSex: does [print sex]
]
extend person 'sex "male"
JaneDoe: make person [firstName: "Jane" secondName: "Doe"]
JaneDoe/whoAreYou
JaneDoe/WhatIsYourSex
ask "Are you sure?"
JaneDoe/sex: "female"
JaneDoe/WhatIsYourSex

I must say, that I would not use code like this one in real as I don't see reason why I should mix data with functions. It's just a try to mimic your JS code.

But I guess, you have wrong example and you want to show this:

<script>
    JaneDoe = new Person("Jane", "Doe");
    DoeJane = new Person("Doe", "Jane");
    Person.prototype.sex = "Man";
    JaneDoe.WhatIsYourSex();
    DoeJane.WhatIsYourSex();
</script>

Than I must say, that in REBOL something like this is not supported, at least now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文