function select(projection, obj, valueToSet) {
	if (!obj) {
		obj = this;
	}

	// Support [] array syntax
	let parts = typeof projection === 'string' ? sfPath.parse(projection) : projection;

	if (typeof valueToSet !== 'undefined' && parts.length === 1) {
		// special case, just setting one variable
		obj[parts[0]] = valueToSet;

		return obj;
	}

	if (typeof valueToSet !== 'undefined' && typeof obj[parts[0]] === 'undefined') {
		// We need to look ahead to check if array is appropriate
		obj[parts[0]] = parts.length > 2 && numRe.test(parts[1]) ? [] : {};
	}

	let value = obj[parts[0]];

	for (let i = 1; i < parts.length; i++) {
		// Special case: We allow JSON Form syntax for arrays using empty brackets
		// These will of course not work here so we exit if they are found.
		if (parts[i] === '') {
			return undefined;
		}

		if (typeof valueToSet !== 'undefined') {
			if (i === parts.length - 1) {
				// last step. Let's set the value
				value[parts[i]] = valueToSet;
				return valueToSet;
			} else {
				// Make sure to create new objects on the way if they are not there.
				// We need to look ahead to check if array is appropriate
				let tmp = value[parts[i]];

				if (typeof tmp === 'undefined' || tmp === null) {
					tmp = numRe.test(parts[i + 1]) ? [] : {};
					value[parts[i]] = tmp;
				}

				value = tmp;
			}
		} else if (value) {
			// Just get nex value.
			value = value[parts[i]];
		}
	}

	return value;
}
/**
 * @description
 * Utility method to access deep properties without
 * throwing errors when things are not defined.
 * Can also set a value in a deep structure, creating objects when missing
 * ex.
 * var foo = Select('address.contact.name',obj)
 * Select('address.contact.name',obj,'Leeroy')
 *
 * @param {string} projection A dot path to the property you want to get/set
 * @param {object} obj   (optional) The object to project on, defaults to 'this'
 * @param {Any}    valueToSet (opional)  The value to set, if parts of the path of
 *                 the projection is missing empty objects will be created.
 * @returns {Any|undefined} returns the value at the end of the projection path
 *                          or undefined if there is none.
 */
@description
Utility method to access deep properties without
throwing errors when things are not defined.
Can also set a value in a deep structure, creating objects when missing
ex.

@param {string} projection A dot path to the property you want to get/set
@param {object} obj   (optional) The object to project on, defaults to 'this'
@param {Any}    valueToSet (opional)  The value to set, if parts of the path of
the projection is missing empty objects will be created.
@returns {Any|undefined} returns the value at the end of the projection path
or undefined if there is none.
@description Utility method to access deep properties without throwing errors when things are not defined . Can also set a value in a deep structure creating objects when missing ex . @param { string } projection A dot path to the property you want to get / set @param { object } obj ( optional ) The object to project on defaults to ' this ' @param { Any } valueToSet ( opional ) The value to set if parts of the path of the projection is missing empty objects will be created . @returns { Any|undefined } returns the value at the end of the projection path or undefined if there is none .
function select(projection, obj, valueToSet) {
	if (!obj) {
		obj = this;
	}
	let parts = typeof projection === 'string' ? sfPath.parse(projection) : projection;
	if (typeof valueToSet !== 'undefined' && parts.length === 1) {
		obj[parts[0]] = valueToSet;
		return obj;
	}
	if (typeof valueToSet !== 'undefined' && typeof obj[parts[0]] === 'undefined') {
		obj[parts[0]] = parts.length > 2 && numRe.test(parts[1]) ? [] : {};
	}
	let value = obj[parts[0]];
	for (let i = 1; i < parts.length; i++) {
		if (parts[i] === '') {
			return undefined;
		}
		if (typeof valueToSet !== 'undefined') {
			if (i === parts.length - 1) {
				value[parts[i]] = valueToSet;
				return valueToSet;
			} else {
				let tmp = value[parts[i]];
				if (typeof tmp === 'undefined' || tmp === null) {
					tmp = numRe.test(parts[i + 1]) ? [] : {};
					value[parts[i]] = tmp;
				}
				value = tmp;
			}
		} else if (value) {
			value = value[parts[i]];
		}
	}
	return value;
}
function select ( projection , obj , valueToSet ) { if ( ! obj ) { obj = this ; } let parts = typeof projection === 'string' ? sfPath . parse ( projection ) : projection ; if ( typeof valueToSet !== 'undefined' && parts . length === 1 ) { obj [ parts [ 0 ] ] = valueToSet ; return obj ; } if ( typeof valueToSet !== 'undefined' && typeof obj [ parts [ 0 ] ] === 'undefined' ) { obj [ parts [ 0 ] ] = parts . length > 2 && numRe . test ( parts [ 1 ] ) ? [ ] : { } ; } let value = obj [ parts [ 0 ] ] ; for ( let i = 1 ; i < parts . length ; i ++ ) { if ( parts [ i ] === '' ) { return undefined ; } if ( typeof valueToSet !== 'undefined' ) { if ( i === parts . length - 1 ) { value [ parts [ i ] ] = valueToSet ; return valueToSet ; } else { let tmp = value [ parts [ i ] ] ; if ( typeof tmp === 'undefined' || tmp === null ) { tmp = numRe . test ( parts [ i + 1 ] ) ? [ ] : { } ; value [ parts [ i ] ] = tmp ; } value = tmp ; } } else if ( value ) { value = value [ parts [ i ] ] ; } } return value ; }
@description
 Utility method to access deep properties without
 throwing errors when things are not defined.
@description Utility method to access deep properties without throwing errors when things are not defined .
// Support [] array syntax // special case, just setting one variable // We need to look ahead to check if array is appropriate // Special case: We allow JSON Form syntax for arrays using empty brackets // These will of course not work here so we exit if they are found. // last step. Let's set the value // Make sure to create new objects on the way if they are not there. // We need to look ahead to check if array is appropriate // Just get nex value.