2013-06-28 3 views
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 } 

ответ

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: '[email protected]'}); 
// First, [email protected], null 

new User({name : 'First', email: '[email protected]', password : 'password1'}); 
// First, [email protected], 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/

+0

Решение не должно присваивать свойства, которые не были определены на объекте. Объект должен определить его свойства и не должен устанавливать свойства по параметру, который не был определен. Достигает ли это решение? – michaelward82

+0

@ michaelward82 - почему это важно? Переменные могут ** только ** получить доступ через объект 'options', чтобы они не переписывали что-либо еще в функции. Кроме того, почему вы все равно пропускаете ненужные переменные? – Joe

+0

@ michaelward82 - Я обновил свой ответ альтернативой, если вы не хотите добавлять дополнительные свойства, переданные функции, - не нужно jQuery. – Joe

0

Во-первых, я позволил бы конструктор объекта принять параметр

function User(params) { 
... 

Чтобы разрешить произвольное число аргументов, подлежащих поставке, параметр params принимает литерал объекта:

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

Далее Я передаю объект params на общую функцию, которая будет обрабатывать назначение свойств объекта params для target объект.

function setObjectProperties(params, target) { 
} 

setObjectProperties функция должна убедиться, что мы правильно прошли какие-то данные. Он проверяет, как params и target определены:

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); 
    } 
} 

Используя $.each функции JQuery, которая итерацию над объектами свойствами без побочного эффекта перебора всех свойств объекта, таких как прототипы, и т.д.Это работает, но означает, что нам нужно иметь дело с побочным эффектом, который this получает переопределенную внутреннюю часть функции обратного вызова функции $.each. Теперь мы больше не знаем, что такое оригинальный объект.

Однако $.proxy функция JQuery разработана, чтобы позволить нам вызвать функцию в то время как определять, что мы хотели бы использовать в качестве 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 } 
+1

Почему бы вам просто не использовать '$ .extend()' - или даже простой 'for ... in' loop - вместо всего этого' $ .each() 'mess? Это излишне сложная реализация. –

+0

@MattBall - полностью аргумент. Майкл - см. Мой ответ на гораздо более простой способ сделать это. – Joe