.retrieve() 中的第二个参数;总是跑步?

发布于 2025-01-08 01:53:33 字数 1240 浏览 0 评论 0原文

我一直在尝试元素存储,但我被元素存储中的 .retrieve(); 问题所困扰。

文档指出:

Element:retrieve 实际上接受一个可选的第二个参数,如果先前不存在另一个值,则该参数将充当要存储的默认值。然后它将按预期检索值。

基本示例有效,但是当我在第二个参数中实例化 Class 时,该实例化得到每次都运行,即使我可以验证 .retrieve(); 返回之前实例化的 Class 对象。

相关 jsFiddle

如果你看一下 fiddle,你会发现每次点击 div 时,myClass 都会得到再次实例化。理想情况下,它应该实例化一次,该对象应该保存到元素存储中,并正确检索以阻止它再次实例化。

这就是我调用 .retrieve(); 的方式:

$('baz').addEvent('click', function() {
    this.retrieve('foobar', new myClass()).foo();
});

...只是为了好玩,我尝试了这个(它也不起作用):

$('baz').addEvent('click', function() {
    this.retrieve('foobar', (function() {
        return new myClass();
    })()).foo();
});

...这就是我最终得到它的方式要工作,不使用 .retrieve() 的第二个参数:

$('baz').addEvent('click', function() {
    var instClass = this.retrieve('foobar');
    if (instClass == null) {
        instClass = this.store('foobar', new myClass()).retrieve('foobar');
    }
    instClass.foo();
});

有任何线索导致此行为吗?

I've been experimenting with Element storage, and I'm stumped by a problem with .retrieve(); in Element Storage.

The documentation states:

Element:retrieve actually accepts an optional second parameter which will act as the default value to store if another value doesn’t previously exist. It will then retrieve the value as expected.

Basic examples work, but when I am instantiating a Class in the second parameter, that instantiation gets run every time, even though I can verify that .retrieve(); is returning the Class object that was instantiated prior.

Relevent jsFiddle

If you take a look at the fiddle, you can see that every time you click the div, myClass gets instantiated again. Ideally, it should be instantiated once, that object should be saved into Element storage, and retrieves properly in order to stop it from being instantiated again.

This is how I am calling .retrieve();:

$('baz').addEvent('click', function() {
    this.retrieve('foobar', new myClass()).foo();
});

... and just for fun, I tried this (it also didn't work):

$('baz').addEvent('click', function() {
    this.retrieve('foobar', (function() {
        return new myClass();
    })()).foo();
});

... and here is how I finally got it to work, by NOT using .retrieve()'s second parameter:

$('baz').addEvent('click', function() {
    var instClass = this.retrieve('foobar');
    if (instClass == null) {
        instClass = this.store('foobar', new myClass()).retrieve('foobar');
    }
    instClass.foo();
});

Any clue what's causing this behaviour?

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

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

发布评论

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

评论(3

半步萧音过轻尘 2025-01-15 01:53:33

第二个参数总是被评估,是的。在您的情况下,每次 retrieve 调用都会实例化一个 myClass 实例 - 这就是您在控制台中看到的内容。这种情况总是会发生,无论调用的结果如何,或者参数是否在方法中实际处理(您可以将例如 10 个以上的参数传递给方法,它们都会在调用时进行评估)。

在您的情况下,还有另一个误解:当使用 retrieve 调用的默认参数时,它不会自动存储。因此,您的第三个变体实际上是任务的正确解决方案


检索键“foobar”的值 - 如果尚未设置值,则创建一个新值
myClass的实例,将其存储为“foobar”并返回。

(更新 - 我的第二个状态语句是错误的,如@ Julian H. Lam 指出:retrieve 的第二个参数实际上是立即存储的。)

The second argument always gets evaluated, yes. In your case, a new instance of myClass is instantiated with every retrieve call - that's what you see in the console. This will always happen, regardless of the outcome of the call or whether the parameter is actually processed in the method (you could pass e.g. 10 more parameters to the method, they will all get evaluated at the moment of the call).

In your case, there is another misunderstanding: when the default parameter of the retrieve call is used, it won't be stored automatically. Therefore your third variant is actually the right solution to the task

Retrieve value for key 'foobar' – if no value has been set, create a new
instance of
myClass, store it as 'foobar' and return it.

(Updated - I was wrong with my second state statement, as @Julian H. Lam pointed out: the second parameter to retrieve is actually immediately stored.)

苏大泽ㄣ 2025-01-15 01:53:33

不幸的是,这不会按预期工作 - 正如 @Julian D. 指出的,它将始终运行 new myClass()

另一种模式在 mootools 中非常流行,由 element.tween / morph 使用等等,看起来像这样:

var myClass = new Class({

    Implements: [Options],

    options: {
        foo: "bar"
    },

    initialize: function(element, options) {
        console.log('I have been initialized!');
        this.setOptions(options);
    },
    foo: function() {
        console.log(this.options.foo);
    }
});

Element.Properties.myClass = {

    set: function(options){
        this.get('myClass').setOptions(options);
        return this;
    },

    get: function(){
        var instance = this.retrieve('myClass');
        if (!instance){
            instance = new myClass(this);
            this.store('myClass', instance);
        }
        return instance;
    }

};


$('baz').addEvent('click', function() {
    this.get('myClass').foo();
});

http://jsfiddle.net/dimitar/R7qFA/2/

getter - 运行时 - 将从存储中为您返回实例(如果可用),否则,它将为您创建一个实例并存储它,然后返回它。

要创建具有自定义选项的实例,请使用 element.set("myClass", { options }

您甚至可以在新的 Element 构造函数中使用它,如下所示:

new Element("a", {
    myClass: {
        foo: "no bars for you"
    }
});

上面将创建 myClass 的实例并使其可用于具有自定义 foo 属性的元素,

这是我在现实生活中使用它的示例:
https://github.com/DimitarChristoff/mootstrap-button /blob/master/Source/mootstrap-button.js

并在此处检查文档/示例:
https://github.com/DimitarChristoff/mootstrap-button/

This won't work as expected, unfortunately - as @Julian D. pointed out, it will always run the new myClass()

An alternative pattern is quite popular in mootools, used by element.tween / morph and so forth, that looks like this:

var myClass = new Class({

    Implements: [Options],

    options: {
        foo: "bar"
    },

    initialize: function(element, options) {
        console.log('I have been initialized!');
        this.setOptions(options);
    },
    foo: function() {
        console.log(this.options.foo);
    }
});

Element.Properties.myClass = {

    set: function(options){
        this.get('myClass').setOptions(options);
        return this;
    },

    get: function(){
        var instance = this.retrieve('myClass');
        if (!instance){
            instance = new myClass(this);
            this.store('myClass', instance);
        }
        return instance;
    }

};


$('baz').addEvent('click', function() {
    this.get('myClass').foo();
});

http://jsfiddle.net/dimitar/R7qFA/2/

The getter - when run - will return the instance from storage for you, if available, else, it will make one for you and store it, then return it.

To create an instance with custom options, use element.set("myClass", { options }.

You can even use this in a new Element constructor like so:

new Element("a", {
    myClass: {
        foo: "no bars for you"
    }
});

The above will create an instance of myClass and make it available to the element with the foo property being custom.

Here is an example in real life where I use it:
https://github.com/DimitarChristoff/mootstrap-button/blob/master/Source/mootstrap-button.js

and check documentation/example here:
https://github.com/DimitarChristoff/mootstrap-button/

落日海湾 2025-01-15 01:53:33

您可以尝试

(function() {
  var def = new myClass();
  $('baz').addEvent('click', function() {
    this.retrieve('foobar', def).foo();
  });
}());

这种方式,事件函数已经实例化了实例,因此在执行时不会创建新实例。

You can try this

(function() {
  var def = new myClass();
  $('baz').addEvent('click', function() {
    this.retrieve('foobar', def).foo();
  });
}());

This way the event function has the instance already instantiated so at execution will not create new ones.

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