繁体   English   中英

跨JavaScript代码共享getter / setter函数

[英]Sharing getter/setter functions across Javascript code

以下示例基于Mike Bostock的可重用图表建议

给定两个函数( bar()pie() ),每个函数都会生成不同种类的图表:

function bar() {
  var width = 720, // default width
      height = 80; // default height

  function my() {
    console.log('bar created: ' + width + ' ' + height);
  }

  my.width = function(value) {
    if (!arguments.length) return width;
    width = value;
    return my;
  };

  my.height = function(value) {
    if (!arguments.length) return height;
    height = value;
    return my;
  };

  my.render = function() {
    my();

    return my;
  };

  return my;
}

function pie() {
  var width = 720, // default width
      height = 80; // default height

  function my() {
    console.log('pie created: ' + width + ' ' + height);
  }

  my.width = function(value) {
    if (!arguments.length) return width;
    width = value;
    return my;
  };

  my.height = function(value) {
    if (!arguments.length) return height;
    height = value;
    return my;
  };

  my.render = function() {
    my();

    return my;
  };

  return my;
}

我可以通过链接方法调用这些函数,例如:

bar().width(200).render();  // bar created: 200 80
pie().height(300).render();  // pie created 720 300

在我的getter和setter方法相同的地方,是否可以编写这些代码? 例如,我计划在每个函数width()函数完全相同。 如何使bar()pie()函数继承共享的函数,例如width()height()render()

是的。关于这种特殊类型的实例化函数并停止使用其他方法的事情是,变量必须是实例化返回的函数( barpie )的函数范围的一部分。 由于这些变量是内部变量,无法在此范围之外访问,因此在扩展实例时无法找到它们。

在继续之前,请注意您的实现有些偏离。 首先,在console.log('bar created: ' + width + ' ' + height); ,从语义上讲是不正确的。 那实际上不是它的创建地,而是它的渲染地。 它是在调用bar()时创建的。

然后,当您渲染此图表时,您应该做的是代替bar().width(200).render() ,例如

var barChart = bar().width(200);

d3.select('svg')
  .append('g')
  .call(barChart)

您不需要render() 相反, my()的主体是您的渲染器。 但是,按照mbostocks的建议, my()应该将d3选择作为参数,在此示例中将附加g元素。 这是链接到的可重用图表教程的权利; 重新阅读它,您会明白我的意思。

最后,回答您的实际问题。 我的方法是使用d3.rebind 首先,您必须创建一个具有内部width变量和width() getter / setter的通用基类,如下所示:

function base() {
  var width;

  function my(selection) {
    console.log('base: ' + width);
  }

  my.width = function(value) {
    if (!arguments.length) return width;
    width = value;
    return my;
  };

  return my;
}

接下来,您要使bar (和pie )实质上扩展基数,如下所示:

function bar() {
  var _base = base(); // instantiate _base, which has width() method

  function my(selection) {
    // In here, if you want to get width, you call `_base.width()`
    // and, if there's some shared rendering functionality you want
    // to put in base, you can run it with `selection.call(_base)`
  }

  d3.rebind(my, _base, 'width'); // make width() a function of my
  return my;
}

最后一行,将width()复制到my以便您可以调用bar().width() 这是一个有效的小提琴。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM