/*! * copy-to - index.js * Copyright(c) 2014 dead_horse * 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; }