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