1

我试图弄清楚是否有一种方法可以在其原型中将对象属性定义为动态值,该动态值可以在每次创建对象实例时更改。这是我能描述它的最好方式;我做了一个小提琴来展示我正在尝试做的事情(尽管它不起作用)。

var Response = {
    LCID: 321
};


Date.prototype.LCID = Number(0);
Date.prototype.LCID.valueOf = function() { return Response.LCID; };


document.write((new Date()).LCID);
Response.LCID = 456;
document.write((new Date()).LCID);

http://jsfiddle.net/tx2fW/2/

我想要实现的是,它Response.LCID可以在代码的整个生命周期内发生变化,正如你可以从我身上看到的那样,稍后在代码中改变它的值。每当我创建一个Date对象时,我希望 的值(new Date()).LCID是 的当前值Response.LCID,而不仅仅是我第一次创建时的值Date.prototype.LCID

有什么办法可以做到这一点?最大的限制是它必须在 JavaScript 1.5 中工作......虽然我很想知道它是否可以在最近的版本中完成。

4

3 回答 3

1

好的,这是使用该__defineGetter__方法完成的,但是我不确定它在所有浏览器上的表现如何,但这是我能找到实现您想要的唯一方法(我认为这一次就是您想要的)

http://jsfiddle.net/tx2fW/6/工作示例。

var Response = {
    LCID: 321
};

var d = Date.prototype;

d._LCID = Number(0);
d.getLCID = function() {
    if (d._LCID != Response.LCID) d._LCID = Response.LCID;
    return d._LCID ;
};
d.__defineGetter__("LCID", function() {
    return this.getLCID();
});

document.write((new Date()).LCID);
Response.LCID = 456;
document.write((new Date()).LCID);​

如需替代方案,__defineGetter__请参阅此帖子

于 2012-04-15T08:46:06.347 回答
1

Number(0) === 0. 修改原始值.valueOf.toString对原始值无效。

正确的方法是使用operator传递构造函数的实例Numbernew

var Response = {
    LCID: 321
};
Date.prototype.LCID = new Number();   // <-- Use the "new" operator
Date.prototype.LCID.valueOf = function() { return Response.LCID; };

带注释的演示和注释:http: //jsfiddle.net/tx2fW/7/

  • LCID是一个对象。typeof new Date().LCID === 'object'.
  • LCID是 的真实实例Numbernew Date().LCID instanceof Number === true
  • LCID等于 321:(new Date().LCID == 321) === true
  • LCID与 321: 不同(new Date().LCID === 321) === false
    (因为 LCID 是一个对象,而 321 是一个原始数值)。

PS。如果您不熟悉==vs ===,请参阅JavaScript 比较中应该使用哪个等号运算符 (== vs ===)?

于 2012-04-15T10:10:19.960 回答
0

经过更多的研究和实验,我能够真正解决这个问题。我曾尝试使用 Date 构造函数等,但我在最初的试验中运气不佳 - 显然是因为我忽略了 Date 对象是独一无二的这一事实,因为它的功能取决于它的调用方式(如一个函数或对象构造函数)。这意味着您不能只做,Date.prototype.constructor.apply(this, arguments)因为您将得到的只是一个字符串( Date 对象被作为函数调用)。

在找到这个线程并阅读它之后,我想出了以下代码,它创建了一个实际的 Date 对象(如果作为函数调用,则为字符串)并完美地模仿了内置的 Date 对象(就我的测试显示而言)。每次创建新的 Date 对象时,它都会获取在对象创建期间动态生成的 LCID 属性,这正是我所需要的。

Date = (function(orig) {
    var date = function(a, b, c, d, e, f, g) {
        var object = (this instanceof Object ? (arguments.length < 1 ? new orig() : (arguments.length < 2 ? new orig(a) : (arguments.length < 4 ? new orig(a, b || 0, c || 1) : new orig(a, b, c, d || 0, e || 0, f || 0, g || 0)))) : orig());
        object.LCID = Response.LCID;

        return object;
    };
    date.prototype = orig.prototype;

    return date;
})(Date);

我还创建了一堆测试用例,以确保与内置 Date 对象没有区别,或者使用此代码(注释掉此代码以查看使用内置 Date 对象的结果并进行比较)。

var Response = { 'LCID': 123 };


Date = (function(orig) {
    var date = function(a, b, c, d, e, f, g) {
        var object = (this instanceof Object ? (arguments.length < 1 ? new orig() : (arguments.length < 2 ? new orig(a) : (arguments.length < 4 ? new orig(a, b || 0, c || 1) : new orig(a, b, c, d || 0, e || 0, f || 0, g || 0)))) : orig());
        object.LCID = Response.LCID;
        return object;
    };
    date.prototype = orig.prototype;
    return date;
})(Date);


var x = new Date();
document.writeln(x);
document.writeln(x.LCID);
document.writeln(x.getFullYear());
document.writeln(typeof x);
document.writeln(Object.prototype.toString.call(x));
document.writeln(x instanceof Date);
document.writeln("<br/>");

Response.LCID = 456;

var y = new Date();
document.writeln(y);
document.writeln(y.LCID);
document.writeln(y.getFullYear());
document.writeln(typeof y);
document.writeln(Object.prototype.toString.call(y));
document.writeln(y instanceof Date);
document.writeln("<br/>");

document.writeln(Date());
document.writeln(new Date());
document.writeln(new Date(2012));
document.writeln(new Date(2012, 7));
document.writeln(new Date(2012, 7, 14));
document.writeln(new Date(2012, 7, 14, 9));
document.writeln(new Date(2012, 7, 14, 9, 45));
document.writeln(new Date(2012, 7, 14, 9, 45, 27));
document.writeln(new Date(2012, 7, 14, 9, 45, 27, 687));

这也可作为更新的小提琴:http: //jsfiddle.net/tx2fW/9/

于 2012-04-17T00:55:51.333 回答