2

在 Javascript 中实例化对象时,我想启用以下场景:

  • 该对象可以在没有任何参数的情况下实例化,并使用默认属性值创建
  • 可以使用设置对象属性初始值的参数来实例化对象

解决方案应该:

  • 不分配尚未在对象上定义的属性
  • 允许设置任意数量的属性(无、部分或全部)
  • 易于应用于脚本定义的任何对象,这意味着我们不知道可以设置哪些属性。

jQuery 可供使用,但欢迎使用纯 JS 解决方案。

采用以下对象构造函数:

function User() {
    this.name = null;
    this.email = null;
    this.password = null;
}

该解决方案应该允许我实现以下目标:

new User();
// User { name: null, email: null, password: null }

new User(<parameter(s) that specify a value for name, email and password>);
// User { name: "passed value", email: "passed value", password: "passed value" }

new User(<parameter that specifies a value for name>);
// User { name: "passed value", email: null, password: null }

new User(<parameter(s) that specify values for name and non-existent property age>);
// User { name: "passed value", email: null, password: null }
4

2 回答 2

2

与默认对象结合$.extend()使这非常容易:

function User(options) {
    var defaults = {
        name: null,
        email: null,
        password: null
    };
    var options = $.extend({}, defaults, options);
    console.log(options);

}

new User(); 
// null, null, null

new User({name : 'First'});
// First, null, null

new User({name : 'First', email: 'users.name@users-email.com'});
// First, users.name@users-email.com, null

new User({name : 'First', email: 'users.name@users-email.comm', password : 'password1'});
// First, users.name@users-email.com, password1

它在这里工作:http: //jsfiddle.net/m6KQC/2/

如果您不想添加调用函数时传递的额外属性,则只需使用下面的代码而不是$.extend(). 这与您的原始功能具有相同的功能:

function setObjectProperties(defaults, options, target) {
    var options = options || {};
    for (var prop in defaults) { 
        target[prop] = (typeof options[prop] === "undefined") ?  defaults[prop] : options[prop];
    }
}

您可以将其包装在原始函数中并像这样使用它:

setObjectProperties(defaults, options, this);

你可以在这里看到这个替代方案:http: //jsfiddle.net/m6KQC/9/

于 2013-06-28T13:23:05.313 回答
0

首先,我会允许对象构造函数接受一个参数

function User(params) {
...

为了允许提供任意数量的参数,params参数将接受一个对象字面量:

new User({name: 'name 1', id: 1});

接下来,我将params对象传递给一个通用函数,该函数将处理从params对象到target对象的属性分配。

function setObjectProperties(params, target) {
}

setObjectProperties函数需要验证我们是否正确传递了一些数据。它检查是否都定义了paramstarget

function setObjectProperties(params, target) {
    if (params !== undefined && target !== undefined) {

    }
}

一旦我们确信我们可以使用某些东西,就该迭代参数并分配给对象属性了。

function setObjectProperties(params, target) {
    if (params !== undefined && target !== undefined) {
        $.each(params, function (i, property) {
            this[i] = property;
        }, target);
    }
}

使用 jQuery 的$.each函数,它迭代对象的属性而没有迭代所有对象属性(如原型等)的副作用。这可行,但意味着我们需要处理this在函数的回调闭包中重新定义的副作用$.each。我们现在不再知道什么是原始对象了。

但是,jQuery 的$.proxy函数旨在允许我们调用函数,同时指定我们想要使用的内容this

function setObjectProperties(params, target) {
    if (params !== undefined && target !== undefined) {
        $.each(params, $.proxy(function (key, value) {
                this[key] = value;
        }, target));
    }
}

这里我们告诉 jQuery 设置this为目标参数的值,该参数是this在对象构造函数内部设置的,如下所示:

function User(params) {
    this.name = null;
    this.email = null;
    this.password = null;

    setObjectProperties(params, this);
}

一个问题仍然存在,我们应该检查对象上声明的属性,看看我们是否可以分配传入的值:

function setObjectProperties(params, target) {
    if (params !== undefined && target !== undefined) {
        $.each(params, $.proxy(function (key, value) {
            if (this.hasOwnProperty(key)) {
                this[key] = value;
            }
        }, target));
    }
}

这是完整和最终的代码:

function setObjectProperties(params, target) {
    if (params !== undefined && target !== undefined) {
        $.each(params, $.proxy(function (key, value) {
            if (this.hasOwnProperty(key)) {
                this[key] = value;
            }
        }, target));
    }
}

function User(params) {
    this.name = null;
    this.email = null;
    this.password = null;

    setObjectProperties(params, this);
}

user1 = new User();
// User { name: null, email: null, password: null }

user2 = new User({ name: 'First Last' });
// User { name: "First Last", email: null, password: null }

user3 = new User({ name: 'First Last', age: '400' });
// User { name: "First Last", email: null, password: null }
于 2013-06-28T13:05:07.803 回答