仅当定义了值

时间:2018-02-26 19:59:15

标签: javascript firebase object firebase-realtime-database properties

情况

我目前正在编写用于将数据推送到数据库的构造函数。

其中一个构造函数如下所示:



/**
 * Timestamp
 *
 * @constructor
 */
function Timestamp() {
	this.timestamp = new Date().getTime();
	this.date = new Date().toUTCString();
}

/**
 * @param {string}    [parameters.status]
 * @param {Timestamp} [parameters.sent]
 * @param {Timestamp} [parameters.delivered]
 * @constructor
 */
function Shipping(parameters) {
	const { status, sent, delivered } = parameters;
	this.status                       = status;
	this.timestamps                   = {
		sent:      sent,
		delivered: delivered
	};
}

console.log(new Shipping({
	status: "pending",
	delivered: new Timestamp()
}));




后端会更新已设置的所有值(我使用Firebase数据库)。

在此示例中,有2个时间戳

  1. 已发送 - 表示发送货件的时间戳
  2. 已交付 - 表示货件到达时的时间戳
  3. 在上面的情景中,货物已经在一段时间前发货了。已调用更新数据库的功能,因为货件已到达。我们想要更新delivered时间戳, sent时间戳。

    另一方面,Firebase对覆盖与更新相关的数据非常敏感。如果我们要使用上面的代码,我们会将sent时间戳设置为undefined,这将删除数据库中的时间戳。因此,我们根本不能设置sent的值。

    问题

    我可以写出构造函数内部的函数来测试undefined。这可行,但它不漂亮,不易维护。特别是在考虑庞大的数据库结构时(上面的例子没有显示整个扩展)。

    该代码可能与此类似(此代码有效):

    
    
    /**
     * Timestamp
     *
     * @constructor
     */
    function Timestamp() {
    	this.timestamp = new Date().getTime();
    	this.date = new Date().toUTCString();
    }
    
    /**
     * @param {string}    [parameters.status]
     * @param {Timestamp} [parameters.sent]
     * @param {Timestamp} [parameters.delivered]
     * @constructor
     */
    function Shipping(parameters) {
    	const { status, sent, delivered } = parameters;
    	if (status !== undefined) this.status = status;
    	this.timestamps = {};
    	if (sent !== undefined) this.timestamps.sent = sent;
    	if (delivered !== undefined) this.timestamps.delivered = delivered;
    }
    
    console.log(new Shipping({
    	status:    "pending",
    	delivered: new Timestamp()
    }));
    
    
    

    我的解决方案想法

    最好的"伪"我能想到的解决这个问题的方法是使用OR运算符进行内联测试。请注意,此赢了,因为至少根据我的经验null以及undefined执行覆盖 firebase数据。

    相反,我们" 甚至不想触摸"数据。

    以下是解决方案如果 null 不会覆盖

    中的数据

    
    
    /**
     * Timestamp
     *
     * @constructor
     */
    function Timestamp() {
    	this.timestamp = new Date().getTime();
    	this.date = new Date().toUTCString();
    }
    
    /**
     * @param {string}    [parameters.status]
     * @param {Timestamp} [parameters.sent]
     * @param {Timestamp} [parameters.delivered]
     * @constructor
     */
    function Shipping(parameters) {
    	const { status, sent, delivered } = parameters;
    	this.status                       = status || null;
    	this.timestamps                   = {
    		sent:      sent || null,
    		delivered: delivered || null
    	};
    }
    
    console.log(new Shipping({
    	status:    "pending",
    	delivered: new Timestamp()
    }));
    
    
    

    如果JS对象包含值,我该怎么设置它呢?

    解决方案

    感谢您Jonas W.提供解决方案!

    工作代码:

    
    
    /**
     * Timestamp
     *
     * @constructor
     */
    function Timestamp() {
    	this.timestamp = new Date().getTime();
    	this.date = new Date().toUTCString();
    }
    
    /**
     * Remove all nested keys with value "undefined" in an object
     * @param object
     */
    function clean(object) {
    	Object.keys(object).forEach(key => {
    		if (object[key] && typeof object[key] === "object") {
    			// Iterate through nested keys
    			clean(object[key]);
    		} else if (object[key] === undefined) {
    			// Found a value which is undefined so we'll remove its key
    			delete object[key];
    		}
    	});
    }
    
    /**
     * @param {string}    [parameters.status]
     * @param {Timestamp} [parameters.sent]
     * @param {Timestamp} [parameters.delivered]
     * @constructor
     */
    function Shipping(parameters) {
    	const { status, sent, delivered } = parameters;
    	this.status                       = status;
    	this.timestamps                   = {
    		sent:      sent,
    		delivered: delivered
    	};
    	clean(this);
    }
    
    console.log(new Shipping({
    	status:    "pending",
    	delivered: new Timestamp()
    }));
    
    
    

    工作原理

    在完成构造函数之前,我们执行clean()函数,该函数删除值为undefined的所有键。您还可以修改clean()函数以测试其他值。例如,您可以使用此函数删除值为"remove me"的所有键:

    /**
     * Remove all nested keys with value "remove me" in an object
     * @param object
     */
    function clean(object) {
        Object.keys(object).forEach(key => {
            if (object[key] && typeof object[key] === "object") {
                // Iterate through nested keys
                clean(object[key]);
            } else if (object[key] === "remove me") {
                // Found a value which is equal to "remove me" so we'll remove its key
                delete object[key];
            }
        });
    }
    

2 个答案:

答案 0 :(得分:1)

您可以清除对象中的未定义:

select * from (values('active', 0),('inactive', 0),('deleted', 0)) as statuses
  where column1 not in (select status from transactions)
union select status, sum(amount) from transactions group by status

这可以在构造函数中完成,也可以在发送到数据库时完成。

答案 1 :(得分:1)

function Shipping(parameters) {
    const timestamps = Object.keys(parameters)
    .reduce((acc, key) => {
       if (parameters[key] !== undefined) acc[key] = parameters[key];
       return acc;
    }, {});
    console.log(timestamps);
}

Shipping({
    status: 'pending',
    delivered: '26/02/2018',
    sent: undefined
})