You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					162 lines
				
				2.9 KiB
			
		
		
			
		
	
	
					162 lines
				
				2.9 KiB
			| 
											3 years ago
										 | /*! | ||
|  |  * copy-to - index.js | ||
|  |  * Copyright(c) 2014 dead_horse <dead_horse@qq.com> | ||
|  |  * MIT Licensed | ||
|  |  */ | ||
|  | 
 | ||
|  | 'use strict'; | ||
|  | 
 | ||
|  | /** | ||
|  |  * slice() reference. | ||
|  |  */ | ||
|  | 
 | ||
|  | var slice = Array.prototype.slice; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Expose copy | ||
|  |  * | ||
|  |  * ```
 | ||
|  |  * copy({foo: 'nar', hello: 'copy'}).to({hello: 'world'}); | ||
|  |  * copy({foo: 'nar', hello: 'copy'}).toCover({hello: 'world'}); | ||
|  |  * ```
 | ||
|  |  * | ||
|  |  * @param {Object} src | ||
|  |  * @return {Copy} | ||
|  |  */ | ||
|  | 
 | ||
|  | module.exports = Copy; | ||
|  | 
 | ||
|  | 
 | ||
|  | /** | ||
|  |  * Copy | ||
|  |  * @param {Object} src | ||
|  |  * @param {Boolean} withAccess | ||
|  |  */ | ||
|  | 
 | ||
|  | function Copy(src, withAccess) { | ||
|  |   if (!(this instanceof Copy)) return new Copy(src, withAccess); | ||
|  |   this.src = src; | ||
|  |   this._withAccess = withAccess; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * copy properties include getter and setter | ||
|  |  * @param {[type]} val [description] | ||
|  |  * @return {[type]} [description] | ||
|  |  */ | ||
|  | 
 | ||
|  | Copy.prototype.withAccess = function (w) { | ||
|  |   this._withAccess = w !== false; | ||
|  |   return this; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * pick keys in src | ||
|  |  * | ||
|  |  * @api: public | ||
|  |  */ | ||
|  | 
 | ||
|  | Copy.prototype.pick = function(keys) { | ||
|  |   if (!Array.isArray(keys)) { | ||
|  |     keys = slice.call(arguments); | ||
|  |   } | ||
|  |   if (keys.length) { | ||
|  |     this.keys = keys; | ||
|  |   } | ||
|  |   return this; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * copy src to target, | ||
|  |  * do not cover any property target has | ||
|  |  * @param {Object} to | ||
|  |  * | ||
|  |  * @api: public | ||
|  |  */ | ||
|  | 
 | ||
|  | Copy.prototype.to = function(to) { | ||
|  |   to = to || {}; | ||
|  | 
 | ||
|  |   if (!this.src) return to; | ||
|  |   var keys = this.keys || Object.keys(this.src); | ||
|  | 
 | ||
|  |   if (!this._withAccess) { | ||
|  |     for (var i = 0; i < keys.length; i++) { | ||
|  |       key = keys[i]; | ||
|  |       if (to[key] !== undefined) continue; | ||
|  |       to[key] = this.src[key]; | ||
|  |     } | ||
|  |     return to; | ||
|  |   } | ||
|  | 
 | ||
|  |   for (var i = 0; i < keys.length; i++) { | ||
|  |     var key = keys[i]; | ||
|  |     if (!notDefined(to, key)) continue; | ||
|  |     var getter = this.src.__lookupGetter__(key); | ||
|  |     var setter = this.src.__lookupSetter__(key); | ||
|  |     if (getter) to.__defineGetter__(key, getter); | ||
|  |     if (setter) to.__defineSetter__(key, setter); | ||
|  | 
 | ||
|  |     if (!getter && !setter) { | ||
|  |       to[key] = this.src[key]; | ||
|  |     } | ||
|  |   } | ||
|  |   return to; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * copy src to target, | ||
|  |  * override any property target has | ||
|  |  * @param {Object} to | ||
|  |  * | ||
|  |  * @api: public | ||
|  |  */ | ||
|  | 
 | ||
|  | Copy.prototype.toCover = function(to) { | ||
|  |   var keys = this.keys || Object.keys(this.src); | ||
|  | 
 | ||
|  |   for (var i = 0; i < keys.length; i++) { | ||
|  |     var key = keys[i]; | ||
|  |     delete to[key]; | ||
|  |     var getter = this.src.__lookupGetter__(key); | ||
|  |     var setter = this.src.__lookupSetter__(key); | ||
|  |     if (getter) to.__defineGetter__(key, getter); | ||
|  |     if (setter) to.__defineSetter__(key, setter); | ||
|  | 
 | ||
|  |     if (!getter && !setter) { | ||
|  |       to[key] = this.src[key]; | ||
|  |     } | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | Copy.prototype.override = Copy.prototype.toCover; | ||
|  | 
 | ||
|  | /** | ||
|  |  * append another object to src | ||
|  |  * @param {Obj} obj | ||
|  |  * @return {Copy} | ||
|  |  */ | ||
|  | 
 | ||
|  | Copy.prototype.and = function (obj) { | ||
|  |   var src = {}; | ||
|  |   this.to(src); | ||
|  |   this.src = obj; | ||
|  |   this.to(src); | ||
|  |   this.src = src; | ||
|  | 
 | ||
|  |   return this; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * check obj[key] if not defiend | ||
|  |  * @param {Object} obj | ||
|  |  * @param {String} key | ||
|  |  * @return {Boolean} | ||
|  |  */ | ||
|  | 
 | ||
|  | function notDefined(obj, key) { | ||
|  |   return obj[key] === undefined | ||
|  |     && obj.__lookupGetter__(key) === undefined | ||
|  |     && obj.__lookupSetter__(key) === undefined; | ||
|  | } |