如何通过另一个包含对象的对象访问对象,该对象是我想要访问的对象的属性?

时间:2014-08-23 02:30:39

标签: javascript jquery css svg prototype

有点难以想出这个标题,希望它是可以理解的,也是有道理的。

嗯,也许,提出标题的难度反映了这种情况的一些不必要的复杂性 - 如果有一种简单的方法可以做到这一点,我很乐意知道。

在这个示例中,有一个Car'类,我可以从中实例化对象(汽车)。它有一个模板(一个SVG,实际上不是汽车,但是谁在乎),还有用于修改模板的公共方法,通过jQuery。

在carContainerClick()函数中,如何访问当前单击的carContainer元素包含模板的Car实例?

Sample here

$(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");
  }
};

更新

我用这里提供的解决方案做了一点test,事实证明它在性能上几乎没有差别......但我喜欢IIFE的简单性。 Sample

4 个答案:

答案 0 :(得分:2)

您可以使用内联函数作为将car作为参数传递的事件处理程序...但是,因为car声明从循环中提升(特别是在当前的顶部)函数),你需要确保事件处理程序捕获正确的Car实例,而不是最后一个通过循环的实例。

您可以使用自调用函数表达式创建闭包,该表达式为循环中存在的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);
    })();
  }

现在你可以拥有一个可以获得你需要的Car实例的函数。

  function carContainerClick(car) {
    car.changeColor();
  }

答案 1 :(得分:1)

使用closure将汽车实例作为参数传递给carContainerClick函数。

我提取了一个新函数,因为在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) {
    //...
}

答案 2 :(得分:1)

尝试将其存储在属性中:

$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");
    }
};

一些注意事项:

  • 不要使用$来获取循环内的元素,这非常慢!将结果存储在循环之前的变量中
  • 旧版浏览器上的
  • { class: 'car-container'}可能会失败,因为保留了class。尝试'class'引号或addClass方法。
  • 要记住什么是DOM元素以及什么是jQuery包装器,可以在变量名的开头使用$

答案 3 :(得分:0)

使用jQuery&#39; .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);
}

然后您可以从jQuery对象访问它:

function carContainerClick() {
    var car = this.data('car');
    car.changeColor();
}