引用对象中的通用值

Refer to common values within an object

本文关键字:对象 引用      更新时间:2023-09-26

我有一个带有嵌套对象的对象,这些嵌套对象在这些嵌套对象属性中具有相同的变量。我试图通过将公共变量合并到嵌套对象的一个属性中来使我的代码更加DRY,但我不确定这是正确的还是最好的编写方法。有人有什么想法吗?

用法

我将调用各种函数作为jQuery-each/onclick语句的回调。

$('#foo').each(foo.part1.begin);
$('.bar a').on('click', foo.part1.middle);

在我使用.each的情况下,我会在分析工具中添加用于跟踪的数据属性,即当用户单击链接时,它会与这些属性一起发送。在绑定到事件的情况下,我会为自定义事件发送一个特殊的分析标记。

我已经更新了foo对象中的第一个属性begin,以说明我正在做什么。我有一个实用程序库,其中有一个函数接受$this和一个对象,该函数循环通过该对象并设置锚标签上的所有属性,等等。

当前实施:

var foo = {
    part1: {
        begin: function () {
            var $this = jQuery(this),
                name = 'the beginning of time',
                color = 'blue',
                type = 'blackberries';
            utility.loopThroughAndSetAttributes($this, {
                name: name,
                color: color,
                type: type
            });
        },
        middle: function () {
            var name = 'the beginning of time',
                color = 'blue',
                type = 'strawberries';
            console.log(name + color + type);
        },
        end: function () {
            var name = 'the beginning of time',
                color = 'blue',
                type = 'raspberries';
            console.log(name + color + type);
        }
    },
    part2: {
        begin: function () {
            var name = 'the middle of the city',
                color = 'green',
                type = 'pluto';
            console.log(name + color + type);
        },
        middle: function () {
            var name = 'the middle of the city',
                color = 'green',
                type = 'mars';
            console.log(name + color + type);
        },
        end: function () {
            var name = 'the middle of the city',
                color = 'green',
                type = 'earth';
            console.log(name + color + type);
        },
    }
};

建议的解决方案:创建嵌套对象的新属性,并在函数中引用该属性。

var foo = {
    part1: {
        name: 'the beginning of time',
        color: 'blue',
        begin: function () {
            var name = foo.part1.name,
                color = foo.part1.color,
                type = 'blackberries';
            console.log(name + color + type);
        },
        middle: function () {
            var name = foo.part1.name,
                color = foo.part1.color,
                type = 'strawberries';
            console.log(name + color + type);
        },
        end: function () {
            var name = foo.part1.name,
                color = foo.part1.color,
                type = 'raspberries';
            console.log(name + color + type);
        }
    },
    part2: {
        name: 'the middle of the city',
        color: 'green',
        begin: function () {
            var name = foo.part1.name,
                color = foo.part1.color,
                type = 'pluto';
            console.log(name + color + type);
        },
        middle: function () {
            var name = foo.part1.name,
                color = foo.part1.color,
                type = 'mars';
            console.log(name + color + type);
        },
        end: function () {
            var name = foo.part1.name,
                color = foo.part1.color,
                type = 'earth';
            console.log(name + color + type);
        },
    }
};

您缺少this关键字:

part1: {
   name: 'the beginning of time',
   color: 'blue',
   begin: function () {
       var name = this.name,
       // ...         
   },

此外,您还可以创建一个构造函数,避免重复代码片段。

var Foo = function(params) {
   this.name = params.name;
   this.color = params.color;
   // ...
}
Foo.prototype.begin = function() {
    // this.name...
};
var foo = {};
foo.part1 = new Foo({
    name: 'the beginning of time',
    color: 'red'
});
foo.part2 = new Foo({
   name: 'bar',
   color: 'baz'
});

编辑:我真的不确定你到底想实现什么,但有一些要点可能是相关的。

jQuery on方法将传递函数的this值设置为单击的元素。为了覆盖引用实例的this值,可以使用Function.prototype.bind或jQuery $.proxy方法:

$('.bar a').on('click', foo.part1.middle.bind(foo.part1));
Foo.prototype.middle = function(event) {
    var clickedElement  = event.currentTarget;
    // `this` here refers to the instance
};

另一种选择是使用jQuery .data()方法将实例附加到元素:

$('element').data('foo', foo.part1);

然后,为了获得数据,可以使用data方法作为getter:

var foo = $('element').data('foo');

当谈到分析时,建议使用D3库!

看起来大多数功能都存在于一个"部分"中,所以让我们创建一个封装该功能的函数对象:

function Part(name, color, types) {
    this.name = name;
    this.color = color;
    this.types = types;
    this.begin = function() {
        console.log(this.name + this.color + this.types.begin);  
    };
    this.middle = function() {
        console.log(this.name + this.color + this.types.middle);  
    };
    this.end = function() {
        console.log(this.name + this.color + this.types.end);  
    };
}

现在,您可以构建foo,除了定义每个参数所需的部分外,还可以删除常见功能:

var foo = {
    part1: new Part('the beginning of time', 'blue', 
        { begin: 'blackberries', middle: 'strawberries', end: 'raspberries' }),
    part2: new Part('the middle of the city', 'green', 
        { begin: 'pluto', middle: 'mars', end: 'earth'})
};

这里的用法是:

foo.part1.begin();
foo.part1.middle();
foo.part1.end();
foo.part2.begin();
foo.part2.middle();
foo.part2.end();

你可以更进一步,但我现在就到此为止。

我喜欢将函数工厂用于这类"几乎相同"的函数。

function fooFunc(name, color, type) {
  return function() {
    console.log(name + color + type);
  };
}
var foo = {
  part1: {
    begin: fooFunc('the beginning of time', 'blue', 'blackberries'),
    middle: fooFunc('the beginning of time', 'blue', 'strawberries'), 
    end: fooFunc('the beginning of time', 'blue', 'raspberries')
  },
  part2: {
    begin: fooFunc('the middle of the city', 'green', 'pluto'),
    middle: fooFunc('the middle of the city', 'green', 'mars'), 
    end: fooFunc('the middle of the city', 'green', 'earth')
  }
};