@barchart/common-js
Version:
Library of common JavaScript utilities
162 lines (131 loc) • 4.95 kB
JavaScript
import * as assert from './assert.js';
import * as is from './is.js';
function getPropertyNameArray(propertyNames, separator = '.') {
let returnRef;
if (is.array(propertyNames)) {
returnRef = propertyNames;
} else {
returnRef = propertyNames.split(separator);
}
return returnRef;
}
function getPropertyTarget(target, propertyNameArray, create) {
let propertyTarget = target;
for (let i = 0; i < (propertyNameArray.length - 1); i++) {
let propertyName = propertyNameArray[i];
if (Object.prototype.hasOwnProperty.call(propertyTarget, propertyName) && !is.nil(propertyTarget[propertyName]) && !is.undef(propertyTarget[propertyName])) {
propertyTarget = propertyTarget[propertyName];
} else if (create) {
propertyTarget = propertyTarget[propertyName] = {};
} else {
propertyTarget = null;
break;
}
}
return propertyTarget;
}
function last(array) {
if (array.length !== 0) {
return array[array.length - 1];
} else {
return null;
}
}
/**
* Utilities for reading and writing "complex" properties to
* objects. For example, the property "name.first" reads the
* "first" property on the "name" object of the target.
*
* @public
* @module lang/attributes
*/
/**
* Checks to see if an attribute exists on the target object.
*
* @public
* @static
* @param {object} target - The object to check for existence of the property.
* @param {string|string[]} propertyNames - The property to check -- either a string with separators, or an array of strings (already split by separator).
* @param {string=} separator - The separator (defaults to a period character).
* @returns {boolean}
*/
export function has(target, propertyNames, separator) {
assert.argumentIsRequired(target, 'target', Object);
if (is.array(propertyNames)) {
assert.argumentIsArray(propertyNames, 'propertyNames', String);
} else {
assert.argumentIsRequired(propertyNames, 'propertyNames', String);
}
const propertyNameArray = getPropertyNameArray(propertyNames, separator);
const propertyTarget = getPropertyTarget(target, propertyNameArray, false);
return propertyTarget !== null && Object.prototype.hasOwnProperty.call(propertyTarget, last(propertyNameArray));
}
/**
* Returns a value from the target object. If the property doesn't exist; undefined
* is returned.
*
* @public
* @static
* @param {object} target - The object to read from.
* @param {string|string[]} propertyNames - The property to read -- either a string with separators, or an array of strings (already split by separator).
* @param {string=} separator - The separator (defaults to a period character).
* @returns {*}
*/
export function read(target, propertyNames, separator) {
assert.argumentIsRequired(target, 'target', Object);
if (is.array(propertyNames)) {
assert.argumentIsArray(propertyNames, 'propertyNames', String);
} else {
assert.argumentIsRequired(propertyNames, 'propertyNames', String);
}
const propertyNameArray = getPropertyNameArray(propertyNames, separator);
const propertyTarget = getPropertyTarget(target, propertyNameArray, false);
let returnRef;
if (propertyTarget) {
const propertyName = last(propertyNameArray);
returnRef = propertyTarget[propertyName];
} else {
returnRef = undefined;
}
return returnRef;
}
/**
* Writes a value to the target object.
*
* @public
* @static
* @param {object} target - The object to write to.
* @param {string|string[]} propertyNames - The property to write -- either a string with separators, or an array of strings (already split by separator).
* @param {*} value - The value to assign.
* @param {string=} separator - The separator (defaults to a period character).
*/
export function write(target, propertyNames, value, separator) {
assert.argumentIsRequired(target, 'target', Object);
if (is.array(propertyNames)) {
assert.argumentIsArray(propertyNames, 'propertyNames', String);
} else {
assert.argumentIsRequired(propertyNames, 'propertyNames', String);
}
const propertyNameArray = getPropertyNameArray(propertyNames, separator);
const propertyTarget = getPropertyTarget(target, propertyNameArray, true);
const propertyName = last(propertyNameArray);
propertyTarget[propertyName] = value;
}
/**
* Erases a property from the target object.
*
* @public
* @static
* @param {object} target - The object to erase a property from.
* @param {string|string} propertyNames - The property to write -- either a string with separators, or an array of strings (already split by separator).
* @param {string=} separator - The separator (defaults to a period character).
*/
export function erase(target, propertyNames, separator) {
if (!has(target, propertyNames)) {
return;
}
const propertyNameArray = getPropertyNameArray(propertyNames, separator);
const propertyTarget = getPropertyTarget(target, propertyNameArray, true);
const propertyName = last(propertyNameArray);
delete propertyTarget[propertyName];
}