【问题标题】:Javascript/AngularJS: Bind function to every object or make helper object?Javascript/AngularJS:将函数绑定到每个对象或制作辅助对象?
【发布时间】:2015-01-17 12:47:37
【问题描述】:

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

如果您使用 AngularJS 从 JSON 格式的 API 中获取“人员”列表,然后将其转换为 JS 数组/对象:

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

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

那么通常认为使用解决方案 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;
}

我知道这是非常基本的,但有时这是最好的方法;)

【问题讨论】:

    标签: javascript angularjs function oop


    【解决方案1】:

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

    第二个更轻。

    另一个想法:

    也许你可以将你的 JSON 解析为一个特定的对象,比如这里:

    Parse JSON String into a Particular Object Prototype in JavaScript

    然后使用原型

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

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

    【讨论】:

    • 所以原型是静态的,因此是解决方案 1 的良好实现?
    • 确实,你是对的!从来不知道原型的这个重要用例-.-
    • 自己昨天才发现的 ;)
    【解决方案2】:

    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“构造”对象(在其 prototype 中使用辅助方法或属性。

    编辑

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

    【讨论】:

    • 稍后会仔细研究。感谢您的调查!
    猜你喜欢
    • 1970-01-01
    • 2017-03-27
    • 1970-01-01
    • 2017-12-05
    • 1970-01-01
    • 2017-01-04
    • 1970-01-01
    • 2019-02-25
    • 1970-01-01
    相关资源
    最近更新 更多