2013-11-08 4 views
0

У меня возникла проблема с объектом JS, когда значение свойства переписывается неожиданно.Непосредственно перезаписано свойство объекта JS

В приведенном ниже примере после того, как я установил css_on['color'] = 'red';, вывод css_on на консоль показывает правильное значение. Однако после css_off['color'] = 'blue'; по какой-то причине css_on.color теперь также blue.

Может кто-нибудь рассказать мне, почему это происходит? И как остановить это! Благодарю.

var css = { 
    'line-height': this.options.height+'px', 
    'width':  this.options.label_width+'px' 
} 
var css_on = css 
var css_off = css; 

css_on['color'] = 'red'; 
console.log(css_on); 
css_off['color'] = 'blue'; 
console.log(css_on); 
+0

'css_on' и' css_off' ссылка на тот же объект. – RobG

+0

Итак, если вы хотите скопировать его, используйте, например, 'css_on = jQuery.extend ({}, css);'. –

+0

Но я создал новые экземпляры с помощью 'var css_on = css;' (и для '_off'). –

ответ

2

Оба css_on и css_off указывают на один и тот же объект. Когда вы изменяете свойство этого объекта, используете ли вы css_on или css_off для его ссылки, это изменение очевидно видно в обоих способах доступа к нему.

Если вы хотите два новых объекта, вы можете клонировать исходный объект css. Если вы не имеете функцию клонирования в вашей предпочитаемой библиотеки (или не иметь библиотеку), вы можете сделать эту простую вещь:

var css_on = Object.create(css); 
var css_off = Object.create(css); 

Это создаст две пустые объекты, которые имеют CSS в своей цепочке прототипов , Когда вы делаете:

console.log(css_on['width']) 

он будет искать width собственности на объект css_on. Он НЕ найдет его (потому что css_on пуст), поэтому он будет искать его в цепочке прототипов. Он найдет его на объект CSS, поэтому он будет регистрировать this.options.label_width+'px'

Когда вы

css_on['width'] = '3px'; 

Вы установите свойство ширины объекта css_on. Объект css или объекты css_off не будут затронуты, так что это именно то, что вы хотите.

+0

Спасибо за объяснение, это очень полезно. Кто-то предложил в комментарии к моему вопросу, что 'css_on = jQuery.extend ({}, css);' также выполнит эту работу. Это точно так же, как ваш метод, или он действительно создаст совершенно новый объект? –

+0

jQuery.extend - это функция clone в вашей предпочитаемой библиотеке. Он фактически просматривает все свойства в css и добавляет их вручную к результирующему объекту. Он не использует метод цепи прототипа. Есть преимущества и недостатки в использовании этого, но ничего, что должно вас беспокоить на данный момент. – Tibos

+0

Спасибо, это очень помогает. –

1

Это потому, что оба css_on & css_off относятся к тому же объектов JavaScript css. У них нет собственной копии. Поэтому всякий раз, когда вы изменить любое имущество одного из них, это будет отражать с другой.

1

Это не неожиданное поведение, это то, что вы должны ожидать от объекта. Есть много способов справиться с этим, хотя и простой - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

например.

var css = { 
'line-height': this.options.height+'px', 
'width':  this.options.label_width+'px' 
} 

var css_on = Object.create(css); 
var css_off = Object.create(css); 

Это не поддерживается во всех старых браузерах. Поэтому, если вам нужна поддержка IE8 или старше, это не сработает. Это действительно информационный поток, который даст вам много вариантов, в том числе некоторых более многословных из них (но поддерживается в более старых браузерах): How do I correctly clone a JavaScript object?

1

Поскольку css_on и css_off оба относятся к одному объекту, так что вы должны создать новый объект для css_on и css_off:

var css_on = new Object(css); 
var css_off = new Object(css); 

и теперь, они разные, и вы можете изменить любой из них.

css_on['width'] = '0px'; 
css_off['width'] = '2px' 
console.log(css_on['width'], css_off['width']); // out put: '0px, 2px' 
Смежные вопросы