我正在使用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_的更改对全局对象有影响。
任何人都可以解释这项任务是如何运作的,所以我将来不会犯这个错误吗?有没有一种快速的方法来正确地做到这一点?
答案 0 :(得分:7)
您最初基本上拥有的是一个对象和一个引用它的变量:
您正在做的是将另一个变量设置为同一个对象:
因此,在更改_s
时,您处理与s
完全相同的对象,因此您也可以使用s
获取这些更改后的值。
相反,您需要两个不同的对象,基本上是克隆:
有几个克隆片段可用。在jQuery中,它就像$.extend({}, obj)
一样简单,例如,可以使用vanilla JavaScript this one。
答案 1 :(得分:5)
var _s = s;
未复制s
,但同时使_s
和s
引用同一对象。您需要创建一个新对象或将原始对象的属性复制到_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
如果a
和b
是对象的唯一时间是它们是对相同对象的引用。)
如果你想故意克隆一个对象,那就有点棘手了。如果您有现代浏览器,则可以使用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();
};
}
因此,如果您使用此代码,则可以在方法的顶部执行此操作:
var s_ = Object.create(s);
然后您将处理单独的对象,并且您发现的问题不会发生。
答案 3 :(得分:1)
将引用视为与对象分离。
_s和s都是引用。在声明中,
var _s = s;
您正在将s中的引用值复制到_s。所以他们现在引用同一个对象。