Javascript/AngularJS: 将函数绑定到每个对象还是制作辅助对象?

Javascript/AngularJS: Bind function to every object or make helper object?

只是一个快速的想法,我不知道如何google它。

如果你从 API 中得到一个 'persons' 的列表,格式为 AngularJS JSON,然后将其转换为 JS array/object :

[
  {firstName: 'Foo', lastName: 'Bar'},
  {firstName: 'Banana', lastName: 'Fruit'}
]

并且您需要一些将名字和姓氏连接到 fullName 中的通用函数。

那么通常认为使用解决方案 1 或 2 更好吗?

解决方案 1 数组由对象组成,这些对象本身具有所需的所有方法。

[
  {firstName: 'Foo', lastName: 'Bar', fullName: function(){return this.firstName+' '+this.lastName;}},
  {firstName: 'Banana', lastName: 'Fruit', fullName: function(){return this.firstName+' '+this.lastName;}}
]

我认为这是最 OOP 的解决方案,但在 Javascript(和长列表)的情况下也是最佳解决方案?

解决方案 2 制作只被实例化一次的辅助函数。

var helper = function(person)
{
   return person.firstName+' '+person.lastName;
}

我知道这是非常基本的,但有时这是最正确的事情;)

在您的第一个解决方案中,您要为每个对象添加一个函数,这感觉很麻烦,如果您有很多对象并且迭代其他对象,我认为这不是最好的。

第二个更轻

另一个想法:

也许您可以将 JSON 解析为特定对象,例如此处:

Parse JSON String into a Particular Object Prototype in JavaScript

然后使用原型

Foo.prototype.fullname = function (){
    return this.firstName+' '+this.lastName;
}

因此每个 Foo 对象都可以通过原型调用 f​​ullname()(在内存中只调用一次 vs 在每个对象中)。

Boris Charpentier 已经为您提供了很好的答案。我可以添加一些示例代码:

可以通过原始 JSON 对象初始化自身的构造函数:

function Workout(workoutJson) {
    if (workoutJson) {
        this.duration = workoutJson.duration;
        ... // or copy all properties in a for-loop
    }
}

var fn = Workout.prototype;

// extend the prototype with some functions
fn.getSomeData = function () {
    return this.onePart + ' ' + this.anotherPart;
};

// another smart solution: get properties (modern browser necessary)
Object.defineProperties(fn, {
    durationMinutes: {
        enumerable: true,
        get: function () {
            return roundMillisToMinutes(this.duration);
        },
        set: function (val) {
            this.duration = val * 60000;
        }
    }
});

现在您有一个 属性 durationMinutes,它的行为类似于真正的 属性,但由 getter 和 setter 函数组成。

让我们添加一些静态函数(不需要实例),稍后我们将使用它们将原始 JSON 对象转换为领域对象:

Workout.fromJson = function(workoutJson) {
    return new Workout(workoutJson);
};

Workout.fromJsonArray = function(workoutJsonArray) {
    return workoutJsonArray.map(Workout.fromJson);
};

在我的数据访问服务中,我将原始数据转换为我的域模型实例(在本例中为锻炼):

/**
 * Get an overview list of all workouts.
 * @returns {*} a promise resolving in an array of `Workout` objects
 */
function getOverview() {
    var defer = $q.defer();

    $http.get('/api/web/workouts?overview=1')
        .success(function (data) {
            defer.resolve(Workout.fromJsonArray(data));
        }).error(function (response) {
            defer.reject(response);
        });

    return defer.promise;
}

/**
 * Get a single Workout by its `extId`.
 * @param extId
 * @returns {*} a promise resolving in the fetched workout
 */
function getByExtId(extId) {
    return WorkoutRS.get({id: extId}).$promise.then(function (data) {
        return $q.when(Workout.fromJson(data));
    });
}

备注:我知道有更好的方法来处理 $q 承诺并进行一些链接而不是使用 $q。这是 Angular 的一些早期工作。这里的重点是在哪里以及如何将原始 JSON 数据转换为 JavaScript "constructed" 对象(在它们的 prototype.

中使用辅助方法或属性

编辑

我在 Opinionated AngularJS 博客中找到了一篇关于此的有趣文章。