1

我正在使用 Omniture 标记,并且页面上有许多事件。在omniture 中,基础对象是sOmniture 全局创建的对象。

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"

如果用户单击,foobars_.prop1提交栏上设置对象属性。

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

谁能解释一下作业是如何工作的,这样我以后就不会犯这个错误了?有没有一种快速的方法可以正确地做到这一点?

4

4 回答 4

7

你首先拥有的是一个对象和一个引用它的变量:

在此处输入图像描述

然后你要做的是为同一个对象设置另一个变量:

在此处输入图像描述

因此,在更改时_s,您正在处理与完全相同的对象s,因此您也会获得这些更改后的值s

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

在此处输入图像描述

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

于 2011-08-29T17:28:16.220 回答
5

var _s = s;不是复制s,而是使两者都_s引用s同一个对象。您将需要创建一个新对象或将原始对象的属性复制到 _s 中。您可以使用以下克隆方法:

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
于 2011-08-29T17:24:18.427 回答
3

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

var a = {},
    b = a;

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

这是故意行为。(顺便说一句,a == bifabare 对象的唯一情况是它们是否是对同一对象的引用。)

如果你想故意克隆一个对象,那就有点棘手了。如果你有一个现代浏览器,你可以用来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();
    };
}

来自 MDN

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

var s_ = Object.create(s);

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

于 2011-08-29T17:27:57.937 回答
1

考虑与对象分离的引用。

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

var _s = s;

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

于 2011-08-29T17:28:19.943 回答