Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript JS:修改JS对象中的值/对_Javascript - Fatal编程技术网

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

Javascript JS:修改JS对象中的值/对,javascript,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 } 唯一改变的是类型。有没有更好的方法来写

我正试图找出最好的方法来修改一个对象,而不必三次写出一个类似的对象。我有三个目标:

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

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

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

唯一改变的是类型。有没有更好的方法来写这个,这样我就不会重复我自己了?

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

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

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

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

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

由于原型是跨对象共享的,因此与在每个对象上使用相同的原型相比,您的内存占用会更小。

创建一个函数

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提供创建和对象使用的速度测试

可以找到测试

在Windows Server 2008 R2/7上使用Chrome 47.0.2526.27进行测试

创建测试

  • 通过对象分配创建:84270±0.94%
  • 通过函数创建:18267444±1.72%
  • 通过新建和原型创建:7886088±1.69%
  • 创建内联(文字):29203404±1.34%最快创建
使用测试。

  • 用于对象指定:266301340±2.45%
  • 用于创建的功能:301185103±1.78%最快使用
  • 用于新建和原型创建:18628401±3.14%
  • 用于创建的内联:272981998±2.74%
可以看出,
object.assign
在创建对象时速度非常慢,但在使用对象时保持不变

创建原型是你能做的最糟糕的事情。虽然没有对象分配那么慢,但在使用以这种方式创建的对象时,它会受到严重影响。以低于第二快的十分之一的速度跑步

正如预期的那样,创建内嵌对象是迄今为止最快的,尽管不是最方便的。然而,当它开始使用时,它并不是最快的,这有点令人惊讶

最快的使用方法是通过函数创建。虽然我不知道为什么,并怀疑这与V8的优化有关

每种方法都有其优点和缺点,应根据其用途和项目标准和惯例进行判断。在大多数情况下,速度不是问题。尽管要记住,“绿色编码”倾向于使用cpu周期数最少的代码,但执行速度可以很好地估计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
    };
  };

如果我们正在处理所有这些属性的原语,那么您就可以放心地使用它们

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});

您不必使用模板对象,您可以直接跳转到第一个对象(请参见上一版本),但如下所示:如果您不能保证对象将如您所期望的那样,则最好使用可以保证的模板。

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

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

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
函数视为“存储”
start
end
的值,以便在返回的闭包中使用。它在概念上与在另一个答案中提出的“模板”中“存储”它们有关

原型

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

演出
我不太清楚为什么或者什么时候我们都开始如此担心表现。归根结底,任何备选方案之间的性能差异(内存或速度)都将是微乎其微的。(例外情况是,如果您正在创建数百万或数千万这样的对象。)指导原则应该是找到一种易于编写、易于阅读和易于维护的方法。如果您正在创建数以千万计的对象,您通过分析程序确定此特定区域是瓶颈,那么这将是返回并优化它的时候。

确定哪些是静态的,哪些是可变的,然后创建一个包含静态部分并接受变量部分作为参数的函数。如果您不熟悉JavaScript中的函数:。是
start
end
日期还是编号?您将字符串“end”和“start”分配给
prototype.end
prototype.start”。同样使用
JSON.stringify(object1)`和
console.log(object1)
将不会显示属性
end
start
@Blindman67是的,我只是做了一些示例输出。第二点是正确的,
console.log(Object.getPrototypeOf(object1))
用于调试。您必须小心使用这种方法,因为它可能会为未经验证的用户引入难以发现的错误。如果指定object1的属性
end
start
,新对象将获得当前object1状态。这很容易被忽略,而且是一个很难找到的bug。例如说
end=10
object2
object3
上使用
var
,这样就可以添加行
object1.end=20在它们之间。现在object3将具有endvar creator = make_creator(start, end);
var object1 = creator(1);
var object2 = creator(2);
var object3 = creator(3);