JS:修改JS对象中的值/对

时间:2015-10-31 00:41:22

标签: javascript

我正在尝试找出修改对象的最佳方法,而不是写出三次类似的对象。所以我有这三个对象:

var object1 = {
    start: start,
    end: end,
    type: 1
}

var object2 = {
    start: start,
    end: end,
    type: 2
}

var object3 = {
    start: start,
    end: end,
    type: 3
}

唯一改变的是类型。是否有更好的方法来写这个,所以我不重复自己?

4 个答案:

答案 0 :(得分:2)

您可以将公共属性设置为原型对象。例如:

function ObjectMaker (typeVal) {
  this.type = typeVal;
}

ObjectMaker.prototype.start = "start";
ObjectMaker.prototype.end = "end";

var object1 = new ObjectMaker("1");
var object2 = new ObjectMaker("2");

给出

> object1.start
"start"
> object1.end
"end"
> object1.type
"1"

如果变量数量更多,您可以将对象传递给maker函数。

由于原型是在对象之间共享的,因此每个对象的内存占用量都比相同。

答案 1 :(得分:2)

创建一个功能

function createObj(start,end,type){
    return  {
        start : start,
        end   : end,
        type  : type
    }
}
var object1 = createObj(start,end,1);
var object2 = createObj(start,end,2);
var object3 = createObj(start,end,3);

// if start and end are in scope to the function 
function createObj(type){
    return  {
        start : start,
        end   : end,
        type  : type
    }
}
var object1 = createObj(1);
var object2 = createObj(2);

更新以代替给出的各种答案。

由于有三个答案都是有效的,我将从jperf.com提出创建和使用对象的速度测试。

可以找到测试Here jsperf.com

在Windows Server 2008 R2 / 7上的Chrome 47.0.2526.27中进行测试

创建测试

  • 通过对象分配创建:84,270±0.94%
  • 通过功能创建:18,267,444±1.72%
  • 通过新的和原型创建:7,886,088±1.69%
  • 创建内联(文字):29,203,404±1.34%最快创建

使用测试。

  • 用于对象分配:266,301,340±2.45%
  • 用于创建的功能:301,185,103±1.78%最快使用
  • 用于创建新原型和原型:18,628,401±3.14%
  • 用于内联创建:272,981,998±2.74%

可以看出object.assign在创建对象时非常慢,但在使用对象时保持自己的状态。

创建原型是您可以做的最糟糕的事情。虽然没有像对象分配那么慢但它在使用以这种方式创建的对象时会严重受损。以低于十分之一速度的速度运行。

正如预期的那样,内联创建对象是最快的,尽管不是最方便的。然而,它在使用时并不是最快的,这有点令人惊讶。

使用最快的是通过功能创建。虽然我不知道为什么,并怀疑它与V8的优化有关。

每种方法都有其优点和缺点,应根据其使用和项目标准和惯例来判断。在大多数情况下,速度不是问题。虽然记住“绿色编码”有利于采用最小cpu周期数的代码,但执行速度可以给出很好的估计。节约周期可以节省电力,金钱和我们生活的可爱世界。

以下是测试的代码。我认为我对所有四种方法都很公平。

//================================================================
// Create via Object Assign
var object1 = {
    start: start,
    end: end,
    type: 1
};

var object2 = Object.assign({}, object1, {type: 2});
var object3 = Object.assign({}, object1, {type: 3});

//================================================================
//Create via function
function createObj(type){
    return  {
        start : start,
        end   : end,
        type  : type
    }
}
var object1 = createObj(1);
var object2 = createObj(2);
var object3 = createObj(3);

//================================================================
//Create via new and prototype
function ObjectMaker (typeVal) {
  this.type = typeVal;
}

ObjectMaker.prototype.start = start;
ObjectMaker.prototype.end = end;

var object1 = new ObjectMaker(1);
var object2 = new ObjectMaker(2);
var object2 = new ObjectMaker(3);

//================================================================
// Create inline objects
var object1 = {
    start: start,
    end: end,
    type: 1
};
var object2 = {
    start: start,
    end: end,
    type: 2
};
var object3 = {
    start: start,
    end: end,
    type: 3
};

使用测试。

//================================================================
// Use case for object created with Object.assign
objectB2.end += 1;
objectB2.start += 1;
objectB2.type += 1;

//================================================================
// Use case for object create with new
objectA1.end += 1;
objectA1.start += 1;
objectA1.type += 1;

//================================================================
// Use case for function created object
objectC1.end += 1;
objectC1.start += 1;
objectC1.type += 1;

//================================================================
// Use of literal object create
objectD1.end += 1;
objectD1.start += 1;
objectD1.type += 1;

设置代码

  Benchmark.prototype.setup = function() {
    // assuming start and end are global
    var start = 0;
    var end = 10;

    // Prototype Method
    // object for use test 
    function ObjectMakerA (typeVal) {
      this.type = typeVal;
    }
    ObjectMakerA.prototype.start = start;
    ObjectMakerA.prototype.end = end;
    var objectA1 = new ObjectMakerA(1);

    // Object assign method 
    // for use test
    var objectB1 = {
        start: start,
        end: end,
        type: 1
    };
    // object to use
    var objectB2 = Object.assign({}, objectB1, {type: 2});

    // Anonymous object
    // for use test
    function createObj1(type){
        return  {
            start : start,
            end   : end,
            type  : type
        }
    }
    // object for use test
    var objectC1 = createObj1(1);

    // Literal object for use test
    var objectD1 = {
        start: start,
        end: end,
        type: 1
    };
  };

答案 2 :(得分:1)

如果我们处理所有这些属性的基元,您可以毫无顾虑地使用Object.assign

var objectTemplate = {
    start: start,
    end: end,
    type: 0
};

var object1 = Object.assign({}, objectTemplate, {type: 1})
    object2 = Object.assign({}, objectTemplate, {type: 2}),
    object3 = Object.assign({}, objectTemplate, {type: 3});

您不必使用模板对象,您可以直接跳转到第一个对象(请参阅上一版本),但是作为@Blindman67 points out:如果您无法保证对象将按照您的预期,使用您可以保证的模板可能会更好。

答案 3 :(得分:0)

我假设您要创建具有相同开始/结束对但具有不同类型的多组对象。

一种方法是编写一个函数,您将传递一个开始/结束对,并返回一个函数来创建具有特定类型的对象:

function make_creator(start, end) {
  return function(type) {
    return { start, end, type };
  };
}

现在您可以将对象创建为

var creator = make_creator(start, end);
var object1 = creator(1);
var object2 = creator(2);
var object3 = creator(3);

在这种情况下,您可以将make_creator函数视为"存储" startend的值,以便在返回的闭包中使用。它在概念上与"存储"相关。他们在"模板"在另一个答案中提出。

原型

让我们考虑使用原型。将值放在原型中通常不是一个好主意。当您尝试设置属性并最终在实例上创建一种阴影值时,您可能会在脚中射击。除非您拥有一百万个对象,否则任何性能(内存)差异都将微不足道,并且在原型链上查找属性的成本将超过它。更重要的是,如果您想要具有相同开始/结束对的多组对象,则必须为每个对象创建单独的原型。

性能

我不太清楚为什么或什么时候我们都开始担心性能问题。最重要的是,任何替代方案之间的性能差异(记忆或速度)都将是微不足道的。 (例外情况是,如果您要创建数百万或数千万个这些对象。)指导原则应该是找到一种易于编写,易于阅读和易于维护的方法。如果您 创建数以千万计的对象,您可以通过分析您的程序确定此特定区域是瓶颈,那么这将是返回和优化的时候它