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

时间:2012-02-22 16:09:31

标签: javascript mootools

我一直在尝试元素存储,我对元素存储中.retrieve();的问题感到困惑。

文档说明:

  

元素:retrieve实际上接受一个可选的第二个参数,如果以前不存在另一个值,它将作为存储的默认值。然后它将按预期检索该值。

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

Relevent jsFiddle

如果您看一下小提琴,您可以看到每次单击div时,myClass都会再次实例化。理想情况下,它应该被实例化一次,该对象应该保存到Element存储中,并正确检索以阻止它再次被实例化。

这就是我打电话.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();
});

有什么迹象导致这种行为?

3 个答案:

答案 0 :(得分:3)

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

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

<击>   

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

(更新 - 我的第二个州陈述错了,因为@Julian H. Lam指出:retrieve的第二个参数实际上是立即存储的。)

答案 1 :(得分:1)

不幸的是,这不会按预期工作 - 正如@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属性为custom的元素。

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

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

答案 2 :(得分:0)

你可以试试这个

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

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