如果条件为真,则返回现有实例

时间:2014-06-09 10:29:01

标签: javascript

假设我们有一个JS类,它应该包装一个HTML元素并改变它的一些属性,子元素等。

我可以知道该元素是否已被“触摸”或已经被包装,但我在构造函数返回时设置了this对象的一些内部属性,如果它同时存在于两个位置,属性不会一起改变。例如:

window.my_class = function( id ){ 

    // find the element
    this.element = document.getElementById(id);

    // make sure it's a valid HTML element in the page
    if(!this.element)
        return console.error('No such element: #'+id);

    // wrap jquery
    var jq = $(this.element);
    var my_class = jq.data('my_class');

    // was this HTML element already "touched" by our class? does it have a corresponding instance of the `my_class` class?
    if(!$.isEmptyObject(my_class)){

        ////////////////////////////////////////////////////////
        // Here's the dilemma: 
        // how do I make `this` point to the old `my_class` ?
        ////////////////////////////////////////////////////////
        this = my_class; // <- I don't think this is okay
        return false;
    }

    // add elements to class
    this.id = id;
    this.initialized = true;
    this.style.backgroundColor = '#f0f';
    this.innerHTML = '<h1>PARSED</h1>';
    this.something = false;

    // save "this" for later use
    jq.data('my_class',this);
}

// the rest of the class methods go here
window.my_class.prototype.do_something = function(){ 
    this.something = 'changed';
}

现在假设我们在该页面上有一个<div id="wrap_me">

// the div gets initialized here
var instance1 = new my_class('wrap_me'); 

// the div doesn't get initialized again, but `instance2` 
// should now be the same with `instance1`; except it isn't
var instance2 = new my_class('wrap_me');

// changes the "this.something" property internally
instance2.do_something();

// this prints false. should print true in a perfect world
console.log( instance2.something===instance1.something ); 

我知道有一种替代方法可以将my_class()包装在一个函数中并从中返回实例,但如果可以不包装类,那么代码语义会更好。

1 个答案:

答案 0 :(得分:0)

这是您的替代模式。我将jQuery用于dom / selector的东西,并将实例保存在jQuery启动器的data对象中。这样,每个元素只返回一个类的“实例”:

$.fn.my_class = function() {
    return this.each(function() {
        var inst = $(this).data('my_class')
        if ( !inst ) { // only create a new instance if none was saved from before
            $(this).data('my_class', new my_class(this))
        }
        return this // always return this so you don’t break the chain
    })
}

然后:

function my_class(elem) {
    this.element = elem
    this.something = false
    // etc...
}

my_class.prototype.do_something = function() {
    this.something = true
}

var inst1 = $('#my_class').my_class().data('my_class') // you need to use `.data` to get the instance
var inst2 = $('#my_class').my_class().data('my_class')
inst2.do_something()
console.log(inst1.something === true)