code: function mergeOption(oldOption, newOption) {
      newOption = newOption || {};
  
      each(newOption, function (newCptOpt, mainType) {
          if (newCptOpt == null) {
              return;
          }
  
          var oldCptOpt = oldOption[mainType];
  
          if (!ComponentModel.hasClass(mainType)) {
              oldOption[mainType] = merge(oldCptOpt, newCptOpt, true);
          }
          else {
              newCptOpt = modelUtil.normalizeToArray(newCptOpt);
              oldCptOpt = modelUtil.normalizeToArray(oldCptOpt);
  
              var mapResult = modelUtil.mappingToExists(oldCptOpt, newCptOpt);
  
              oldOption[mainType] = map(mapResult, function (item) {
                  return (item.option && item.exist)
                      ? merge(item.exist, item.option, true)
                      : (item.exist || item.option);
              });
          }
      });
  }
docs: Consider case:
  `chart.setOption(opt1);`
  Then user do some interaction like dataZoom, dataView changing.
  `chart.setOption(opt2);`
  Then user press 'reset button' in toolbox.
  
  After doing that all of the interaction effects should be reset, the
  chart should be the same as the result of invoke
  `chart.setOption(opt1); chart.setOption(opt2);`.
  
  Although it is not able ensure that
  `chart.setOption(opt1); chart.setOption(opt2);` is equivalents to
  `chart.setOption(merge(opt1, opt2));` exactly,
  this might be the only simple way to implement that feature.
  
  MEMO: We've considered some other approaches:
  1. Each model handle its self restoration but not uniform treatment.
  (Too complex in logic and error-prone)
  2. Use a shadow ecModel. (Performace expensive)