4

我怎么能用一个数字“划分”一个对象?

4

5 回答 5

5

延迟更新
鉴于我的答案包含一些不完整且有时完全错误的信息,我认为最好纠正我的错误。虽然晚了,但还是这样:

几乎所有 JS 对象都有2 3 个共同的方法:valueOf()对于日期对象,它映射回getTime()方法,该方法返回一个数字。这个数字是自 1970 年 1 月 1 日以来的毫秒数,许多编程语言使用这个日期作为日期的基础。它被称为 Unix Timestamp,日期被称为 Unix Epoch。万一你想知道。
另一种方法是toString,它返回一个字符串(显然)。
第三种方法是hasOwnProperty,它可以在原型链中追溯到Object.prototype,但这对于这个问题并不重要。

每当您比较 2 个值(对象与否)时,JS 都会强制两个操作数的类型,以便可以安全地比较这两个值(例如,1 == '1'将字符串强制'1'为 a Number)。
这种类型强制也适用于将对象或原始值连接到搅拌中,或者将表达式评估为奇异值时(例如,在您的控制台中, type new Date;,您会明白我的意思)。
对象的默认行为Date是被强制转换为字符串,toString方法被调用。

因此,Date实例没有什么不同。它们是对象,这意味着变量的值将是对对象的引用。但是,在您的表达式/语句中,您在/对象上使用算术运算符 ( )。在这种情况下,字符串没有多大意义,因此 JS 回退到该valueOf方法(有点,Date可以通过多种方式将 's 强制转换为数字)。这确实产生了 a Number,可以毫不费力地进行划分。当使用比较运算符、和时,
可以预期(并且确实可以观察到)相同的行为。 这意味着在大多数情况下,比较日期并使用它们生成输出是轻而易举的事:><<=>=

var d1 = new Date();
var d2 = new Date(1234567890123);
if (d1 > d2)
{
   //do stuff
}

写完整的话是这样的:

Date.prototype.valueOf = Date.prototype.getTime; //<-- this isn't how its done, but think of the valueOf method as doing something similar

if (d1.getTime() > d2.getTime()) //OR:
if (d1.valueOf() > d2.valueOf())

除了比较之外,还有其他优点:

var d3 = new Date(d1 - 1000); //new date, 1 second before d1

但是有一个权衡/陷阱:
与 JS 中的所有对象一样,使用==or===进行相等性检查一开始有点奇怪:

var a = new Date();
var b = new Date(a.valueOf());
console.log(a.toString() === b.toString());//true
console.log(a.valueOf() === b.valueOf());//true, to the milisecond
console.log(a == b);//false!
console.log(a === b);//false!!

就像我说的:分配给对象的变量实际上并不保存该对象的值,而是引用它。由于两者都a引用b同一个对象的不同实例,所以它们是不相等的。同样因为它们都是对象(类型相同),所以没有类型强制。
把它想象成两座房子,除了地址之外,其他方面都是 100% 相等的。如果没有强制,你实际上是在说:
“Fiction Street 1 和 Fiction Street 2 上有一个房子。这两个房子相等吗?” 答案是响亮的不。

要解决此问题,您必须明确要求 JS通过手动将它们强制转换为另一种类型来比较这些房屋的外观。这比听起来容易得多:

console.log(a.valueOf() == b.valueOf());//true
//or shorter, still:
console.log(+(a) == +(b));
//coerce to strings, either call toString, or:
console.log((''+a) == (''+b));

同样,这乍一看似乎很愚蠢,但是通过这种方式,您至少可以测试两个变量是否确实引用了同一个实例。假设我们有 2 个对象占用内存,当我们真的只需要 1 个时,我们可以释放对这些实例之一的引用以进行 GC:

if (a !== b && +(a) === +(b))
{//their values are the same, but different instances
    b = a;//now b references the same object as a
}
console.log(a === b);//true
console.log(+(a) === +(b));// true again

请注意,现在仍然有一些奇怪的东西会Date特别影响对象。尝试猜测以下语句会记录什么:

a.setTime(a.getTime() + 1000);//add 1 second
console.log(a == (b + 1000));
console.log(a === (b + 1000));
console.log((a-1000) == b);
console.log((a-1000) === +b);

答案是:假、假、假、真。怎么来的?
第一种情况很简单:+运算符被重载,它还连接字符串,并且Date对象的默认行为是对toString自身的,因此b+1000被评估为b.toString() + '1000'.
接下来,使用类型和值检查===几乎总是错误的,因为没有强制进行。然后,通过使用未重载的算术运算符
减去 1000意味着左操作数仍将被计算为一个数字。然而,右操作数仍将恢复为被强制为字符串的错误行为。他们不相等。-
最后一个示例将右操作数显式强制为一个数字,并产生 true。

要解决true上述所有情况,以下是要写的内容

console.log(+a == (+b + 1000));
console.log(+a === (+b + 1000));
console.log((a-1000) == +b);
console.log((a-1000) === +b);

简单地显式地强制你的Date实例,你应该没问题

于 2012-08-17T14:23:02.883 回答
4

因为当您使用除法运算符时,new Date()将隐式转换为数字(表示从 1970 年 1 月 1 日开始的该日期的总毫秒数)。该+运算符将不起作用,因为+在字符串中表示连接,而不是求和,并且当您尝试对 Date 求和时,它不会返回毫秒,但该日期的 toString()*会起作用,但由于 String 没有*运算符,它将起作用. 例如,尝试new Date() * 2.

有关 Date 全局对象的更多详细信息,请查看此处:https ://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date

编辑:我说日期将在带有 / 的表达式中转换为字符串,当然我错了。我已经更正了答案。下面有一些评论可以更清楚地说明我的答案。String 到 Number 的行为仍然有效,即表示有效数字的 String 可以进行乘法、除法和减法运算,但由于 sum 运算符用于连接字符串,因此不能相加。看一看:

console.log( "10" + "1" );
console.log( "10" - "1" );
console.log( "10" * "2" );
console.log( "10" / "3" );

console.log( 10 + "1" );
console.log( 10 - "1" );
console.log( 10 * "2" );
console.log( 10 / "3" );

console.log( "10" + 1 );
console.log( "10" - 1 );
console.log( "10" * 2 );
console.log( "10" / 3 );
于 2012-08-17T14:11:08.793 回答
4

当你对一个对象执行算术运算时,它的valueOf函数被隐式调用。

尝试以下操作以获得可以实际划分的对象:

function Foo() {

    this.valueOf = function() {
        return 500;
        };

    }

var bar = new Foo();
console.log(bar/1000); // -> 0.5
于 2012-08-17T14:24:11.383 回答
1

在除法之前日期对象将被转换为数字,这将给出从 1970 年 1 月 1 日开始的毫秒数

new Date()/1000 => Number(new Date()) / 1000 = some number

于 2012-08-17T14:14:31.930 回答
0

大多数语言实际上用自己的内部语言将日期表示为一个数字。Javascript 使用的约定是自 1970 年 1 月 1 日以来的毫秒数,许多其他语言也有类似的约定。这与您可以以与计时方法相同的方式简单地相互减去日期的原因相同。

于 2012-08-17T14:11:48.863 回答