[英]How do I access an object via another object that contains an object which is a property of the object I want to have access to?
It was kinda hard to come up with the title for this one, hope it's understandable and makes sense. 很难想出这个标题,希望它是可以理解的并且有意义。
Well , maybe, the difficulty to come up with the title reflects some unnecessary complexity of this situation - if there's a simple way to do this I'd love to know. 好吧,也许,拿出标题的难度反映了这种情况的一些不必要的复杂性-如果有一种简单的方法,我很想知道。
In this sample, there's a Car 'class', from which I can instance objects (Cars). 在此示例中,有一个Car'class',可以从中实例对象(Cars)。 It has a template (an SVG, which is not a car, actually, but who cares), and also public methods, used to modify the template, via jQuery. 它有一个模板(实际上是一个SVG,实际上不是汽车,但在乎谁),还有一个公共方法,用于通过jQuery修改模板。
In the carContainerClick() function, how do I access the Car instance whose template is contained by the currently clicked carContainer element? 在carContainerClick()函数中,如何访问其模板包含在当前单击的carContainer元素中的Car实例?
$(function(){
var cars = [];
for (var i = 0; i < 2; i++) {
var carContainer = $('<div/>', { class: 'car-container'});
var car = new Car();
cars[i] = car;
carContainer.on('click', carContainerClick);
carContainer.append(car.getTemplate());
$('.container').append(carContainer);
}
function carContainerClick() {
// HERE - how do I access the Car instance whose template is contained by the currently clicked carContainer element?
cars[0].changeColor();
}
});
function Car () {
this.template = $('<svg viewBox="0 0 301 259"> <g class="svg-group"><path class="stick-2" fill-rule="evenodd" clip-rule="evenodd" d="M74.192,27.447c2.589-2.042,4.576-3.188,6.991-5.093c0,0,1.753-1.11,0.416-2.945 c-1.13-1.546-3.242,0.014-3.242,0.014c-4.831,3.804-9.678,7.589-14.491,11.418c-2.335,1.861-4.335,4.009-7.954,3.233 c-2.136-0.458-3.892,1.798-3.913,4.021c-0.02,2.326,1.531,4.107,3.734,4.296c2.353,0.2,4.689-1.183,4.635-3.241 c-0.066-2.415,1.215-3.474,2.981-4.492c1.821-1.049,5.809-3.993,7.21-4.785C71.961,29.082,74.192,27.447,74.192,27.447z"/></g></svg>');
}
Car.prototype = {
getTemplate: function() {
return this.template;
},
changeColor: function() {
console.log('changeColor');
$('.svg-group', this.template).find("path, polygon, circle").attr("fill", "#aff");
}
};
update 更新
i made a little test with the solutions provided here and turns out it makes almost no difference in performance .. but i like the IIFE one for its simplicity. 我对这里提供的解决方案进行了一些测试 ,结果证明它在性能上几乎没有区别..但是我喜欢IIFE,因为它简单易用。 Sample 样品
You can use an inline function as your event handler that passes car
as a parameter... however, because the car
declaration is hoisted out of your loop (specifically to the top of the current function), you need to ensure that the event handler captures the right Car
instance, and not the last one to pass through the loop. 您可以将内联函数用作将car
作为参数传递的事件处理程序...但是,由于car
声明是从循环中提升的(特别是在当前函数的顶部),因此需要确保事件处理程序捕获正确的Car
实例,而不是最后一个要通过循环的实例。
You can create a closure by using a self invoking function expression that creates a new scope for car
that exists within the loop and allows the right car instance to be captured when you set up your handler. 您可以通过创建一个新的范围自调用函数表达式创建一个封闭car
内环路存在,并且允许当您设置处理程序来捕捉正确的汽车实例。
for (var i = 0; i < 2; i++) {
(function(){
var carContainer = $('<div/>', { class: 'car-container'});
var car = new Car();
cars[i] = car;
carContainer.on('click', function(){
carContainerClick(car);
});
carContainer.append(car.getTemplate());
$('.container').append(carContainer);
})();
}
Now you can have a function that gets handed the Car
instance you need. 现在,您可以拥有一个传递所需的Car
实例的函数。
function carContainerClick(car) {
car.changeColor();
}
Use closure to pass the car instance as an argument to the carContainerClick
function. 使用闭包将car实例作为参数传递给carContainerClick
函数。
I extracted a new function, cause doing that stuff in a for loop will probably not work (always passing the last car as an argument) 我提取了一个新函数,因为在for循环中执行此操作可能无法正常工作(始终将最后一辆车作为参数传递)
for (var i = 0; i < 2; i++) {
var carContainer = $('<div/>', { class: 'car-container'});
var car = new Car();
cars[i] = car;
bindCarContainer(carContainer, car);
carContainer.append(car.getTemplate());
$('.container').append(carContainer);
}
function bindCarContainer(carContainer, car) {
carContainer.on('click', function(event) {
carContainerClick.call(this, car, event);
});
}
function carContainerClick(car, event) {
//...
}
Try assigning storing it in a property: 尝试分配将其存储在属性中:
$container = $('.container');
for (var i = 0; i < 2; ++i) {
var car = new Car(),
carContainer = $('<div/>').addClass('car-container').prop('car', car);
carContainer.on('click', carContainerClick);
carContainer.append(car.getTemplate());
$container.append(carContainer);
}
function carContainerClick() {
this.car.changeColor();
}
var $template = $('<svg viewBox="0 0 301 259"> <g class="svg-group"><path class="stick-2" fill-rule="evenodd" clip-rule="evenodd" d="M74.192,27.447c2.589-2.042,4.576-3.188,6.991-5.093c0,0,1.753-1.11,0.416-2.945 c-1.13-1.546-3.242,0.014-3.242,0.014c-4.831,3.804-9.678,7.589-14.491,11.418c-2.335,1.861-4.335,4.009-7.954,3.233 c-2.136-0.458-3.892,1.798-3.913,4.021c-0.02,2.326,1.531,4.107,3.734,4.296c2.353,0.2,4.689-1.183,4.635-3.241 c-0.066-2.415,1.215-3.474,2.981-4.492c1.821-1.049,5.809-3.993,7.21-4.785C71.961,29.082,74.192,27.447,74.192,27.447z"/></g></svg>');
function Car () {
this.$template = $template.clone();
}
Car.prototype = {
getTemplate: function() {
return this.$template;
},
changeColor: function() {
console.log('changeColor');
$('.svg-group', this.$template).find("path, polygon, circle").attr("fill", "#aff");
}
};
Some notes: 一些注意事项:
$
to get elements inside a loop, it's very slow! 不要使用$
来使元素进入循环,这非常慢! Store the result in a variable before the loop instead 将结果存储在循环之前的变量中 { class: 'car-container'}
may fail on old browsers because class
was reserved. { class: 'car-container'}
在旧版浏览器上可能会失败,因为class
是保留的。 Try 'class'
with quotes or addClass
method. 尝试使用带引号或addClass
方法的'class'
。 $
at the beginning of the variable name. 要记住什么是DOM元素和什么是jQuery包装器,可以在变量名的开头使用$
。 Use jQuery's .data()
to attach a reference to the car to the template: 使用jQuery的.data()
将对汽车的引用附加到模板:
function Car () {
this.template = $('<svg viewBox="0 0 301 259"> <g class="svg-group"><path class="stick-2" fill-rule="evenodd" clip-rule="evenodd" d="M74.192,27.447c2.589-2.042,4.576-3.188,6.991-5.093c0,0,1.753-1.11,0.416-2.945 c-1.13-1.546-3.242,0.014-3.242,0.014c-4.831,3.804-9.678,7.589-14.491,11.418c-2.335,1.861-4.335,4.009-7.954,3.233 c-2.136-0.458-3.892,1.798-3.913,4.021c-0.02,2.326,1.531,4.107,3.734,4.296c2.353,0.2,4.689-1.183,4.635-3.241 c-0.066-2.415,1.215-3.474,2.981-4.492c1.821-1.049,5.809-3.993,7.21-4.785C71.961,29.082,74.192,27.447,74.192,27.447z"/></g></svg>');
this.template.data('car', this);
}
Then later you can access it from the jQuery object: 然后,您可以从jQuery对象访问它:
function carContainerClick() {
var car = this.data('car');
car.changeColor();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.