假设我们有一个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()包装在一个函数中并从中返回实例,但如果可以不包装类,那么代码语义会更好。
答案 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)