Skip to content

Instantly share code, notes, and snippets.

@kejun
Created April 1, 2014 06:18
Show Gist options
  • Save kejun/9908688 to your computer and use it in GitHub Desktop.
Save kejun/9908688 to your computer and use it in GitHub Desktop.
不可变数据更新
var DIRECTIVE_SET = '$set';
var DIRECTIVE_PUSH = '$push';
var DIRECTIVE_UNSHIFT = '$unshift';
var DIRECTIVE_SPLICE = '$splice';
var DIRECTIVE_MERGE = '$merge';
var ALL_DIRECTIVES_SET = {};
ALL_DIRECTIVES_SET[DIRECTIVE_SET] = true;
ALL_DIRECTIVES_SET[DIRECTIVE_PUSH] = true;
ALL_DIRECTIVES_SET[DIRECTIVE_UNSHIFT] = true;
ALL_DIRECTIVES_SET[DIRECTIVE_SPLICE] = true;
ALL_DIRECTIVES_SET[DIRECTIVE_MERGE] = true;
function copyProperties(obj, obj1) {
obj = obj || {};
for (var k in obj1) {
if (obj1.hasOwnProperty(k)) {
obj[k] = obj1[k];
}
}
return obj;
}
function shallowCopy(e) {
if (Object.prototype.toString.call(e) == '[object Array]') {
return e.concat();
} else if (typeof e == 'object') {
return copyProperties({}, e);
} else {
return e;
}
}
function immutableUpdate(value, spec) {
if (spec.hasOwnProperty(DIRECTIVE_SET)) {
return spec[DIRECTIVE_SET];
}
var nextValue = shallowCopy(value);
var specValue;
if (spec.hasOwnProperty(DIRECTIVE_PUSH)) {
specValue = spec[DIRECTIVE_PUSH];
if (Object.prototype.toString.call(specValue) == '[object Array]') {
nextValue = nextValue.concat(specValue);
} else {
nextValue.push(specValue);
}
}
if (spec.hasOwnProperty(DIRECTIVE_UNSHIFT)) {
specValue = spec[DIRECTIVE_UNSHIFT];
if (Object.prototype.toString.call(specValue) == '[object Array]') {
nextValue.splice.apply(nextValue, [0,0].concat(specValue));
} else {
nextValue.unshift(specValue);
}
}
if (spec.hasOwnProperty(DIRECTIVE_SPLICE)) {
nextValue.splice.apply(nextValue, spec[DIRECTIVE_SPLICE]);
}
if (spec.hasOwnProperty(DIRECTIVE_MERGE)) {
nextValue = copyProperties(nextValue, spec[DIRECTIVE_MERGE]);
}
for (var k in spec) {
if (!ALL_DIRECTIVES_SET.hasOwnProperty(k)) {
nextValue[k] = immutableUpdate(value[k], spec[k]);
}
}
return nextValue;
}
/*
var foo = {
x: 10,
y: {
x1: [1, 2, 3],
y1: { x2: 'foo1' }
}
};
console.log('update result:',
immutableUpdate(foo,
{
x: { $set: 20 },
y: {
x1: { $push: {x: 0} },
y1: { $merge: { x2: 'updated!' }
}
}
}
)
);
//返回结果:
{
x: 20,
y: {
x1: [1, 2, 3, {x:0}],
y1: { x2: 'updated' }
}
}
console.log('result', foo);
// foo 属性不变
var foo = {
x: 10,
y: {
x1: [1, 2, 3],
y1: { x2: 'foo1' }
}
};
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment