code: function extend(...args){
  	if ( !args.length || isArray(args[0]) || !args[0] ) return null;
  
  	let keys = args[args.length-1];
  	if ( !keys ) return;
  
  	let oOrig = args[0];
  	oOrig.class = classToPlantObject(oOrig.class);
  
  	if ( isArray(keys) ) {
  		for ( let i=0, oCopy; i<args.length-1; i++ ) {
  			oCopy = args[i];
  			if ( oOrig !== oCopy && isPlainObject(oCopy) ) {
  				keys.forEach(k => {
  					if ( oCopy[k] !== undefined ) {
  						k == 'class' ? Object.assign(oOrig.class, classToPlantObject(oCopy[k])) : (oOrig[k] = _copyObjectValue(oCopy[k]));
  					}
  				});
  			}
  		}
  	}else{
  		for ( let i=1, oCopy; i<args.length; i++ ) {
  			oCopy = args[i];
  			if ( oOrig !== oCopy && isPlainObject(oCopy) ) {
  				for ( let k in oCopy ) {
  					k == 'class' ? Object.assign(oOrig.class, classToPlantObject(oCopy[k])) : (oOrig[k] = _copyObjectValue(oCopy[k]));
  				}
  			}
  		}
  	}
  	return oOrig;
  }
docs: 深复制对象属性，与Object.assign(...)的区别在于 1) 如果最后一个参数为数组，则该数组限定了复制的属性范围；如果是null等false值，则不复制；其他情况则复制所有属性 2) 第一参数null时返回null不报错，其他参数null时忽略 3) 对属性class做特殊处理 4) 深度复制