在处理对象时,javascript x = y如何工作?

时间:2011-08-29 17:17:36

标签: javascript variable-assignment adobe-analytics

我正在使用Omniture标记,我在页面上有很多活动。在omniture中,基础对象是s此对象由Omniture全局创建。

s对象有很多“标准”变量,我想为它设置,网址,页面标题,网站停留时间,你有什么...

对于每个事件,我设置了一个或两个附加属性

我认为我在编写像:

这样的函数时非常聪明
 //  s is a global variable create by omniture

 function ClickFoo(){
      var s_ = s;  // make a copy of s which has all the standard vars
      s_.event = "Click Foo";  // set X number of custom vars 
      s_.prop1 = "foo";
      s_.t();    // the Omniture "submit event" function
 }

 function ClickBar(){
      var s_ = s;
      s_.event = "Click Bar";
      s_.prop2 = "bar";
      s_.t();    
 }

 ClickFoo();
 ClickBar();
 // at this point, s.prop1 = "foo"

如果用户点击foo,那么bar就会在条提交中设置s_.prop1对象属性。

我一直在关注JS控制台中这些东西的行为,似乎对s_的更改对全局对象有影响。

任何人都可以解释这项任务是如何运作的,所以我将来不会犯这个错误吗?有没有一种快速的方法来正确地做到这一点?

4 个答案:

答案 0 :(得分:7)

您最初基本上拥有的是一个对象和一个引用它的变量:

enter image description here

您正在做的是将另一个变量设置为同一个对象:

enter image description here

因此,在更改_s时,您处理与s完全相同的对象,因此您也可以使用s获取这些更改后的值。

相反,您需要两个不同的对象,基本上是克隆:

enter image description here

有几个克隆片段可用。在jQuery中,它就像$.extend({}, obj)一样简单,例如,可以使用vanilla JavaScript this one

答案 1 :(得分:5)

var _s = s;未复制s,但同时使_ss引用同一对象。您需要创建一个新对象或将原始对象的属性复制到_s。您可以使用clone methods

Object.prototype.clone = function() {
  var newObj = (this instanceof Array) ? [] : {};
  for (i in this) {
    if (i == 'clone') continue;
    if (this[i] && typeof this[i] == "object") {
      newObj[i] = this[i].clone();
    } else newObj[i] = this[i]
  } return newObj;
};

...
var _s = s.clone(); // _s now does not reference the same object as s

答案 2 :(得分:3)

将对象分配给变量时,将复制对该变量的引用。该对象不以任何方式“克隆”。所以:

var a = {},
    b = a;

b.foo = 'bar';
alert(a.foo); // 'bar'

这是故意行为。 (作为一个侧面点,a == b如果ab是对象的唯一时间是它们是对相同对象的引用。)

如果你想故意克隆一个对象,那就有点棘手了。如果您有现代浏览器,则可以使用Object.create有效克隆对象:

var a = {},
    b = Object.create(a);

b.foo = 'bar';
alert(a.foo); // undefined

您可以使用该MDN页面中的方法将此行为修补到您的应用程序中:

if (!Object.create) {
    Object.create = function (o) {
        if (arguments.length > 1) {
            throw new Error('Object.create implementation only accepts the first parameter.');
        }
        function F() {}
        F.prototype = o;
        return new F();
    };
}

From MDN

因此,如果您使用此代码,则可以在方法的顶部执行此操作:

var s_ = Object.create(s);

然后您将处理单独的对象,并且您发现的问题不会发生。

答案 3 :(得分:1)

将引用视为与对象分离。

_s和s都是引用。在声明中,

var _s = s;

您正在将s中的引用值复制到_s。所以他们现在引用同一个对象。