根据我的理解,如果对象具有valueOf
函数,则在对象需要转换为基元时将使用它。如果对象具有toString
函数,则在对象需要转换为字符串时将使用该函数。因此,当您使用+
时,首先应使用valueOf
(如果存在),然后使用toString
。
这似乎是做什么的:
var obj1 = {
valueOf: () => 0
};
var obj2 = {
toString: () => 'a'
};
var obj3 = {
valueOf: () => 0,
toString: () => 'a'
};
obj1 + obj1; // -> 0
obj2 + obj2; // -> 'aa'
obj3 + obj3; // -> 0
现在,日期正在实施valueOf
和toString
,例如obj3
,但当您执行date + date
时,您会得到一个字符串!
使用任何其他算术运算符将日期视为执行操作的数字并返回有效数字。
以下是一些代码来证明我的困惑:
var date = new Date(2017,1,1);
date - date; // -> 0
date * date: // -> 2.20790950849296e+24
date / date; // -> 1
date % date; // -> 0
date + date; // -> "Wed Feb 01 2017 00:00:00 GMT+0100 (CET)Wed Feb 01 2017 00:00:00 GMT+0100 (CET)"
答案 0 :(得分:0)
如果第一个操作数是字符串,procedure TCustomDialog.FormPaint(Sender: TObject);
var
Rect: TRect;
BorderColor: TColor;
BrushColor: TColor;
begin
// Rect for Form's borders;
Rect.Left := 0;
Rect.Top := 0;
Rect.Right := ClientWidth;
Rect.Bottom := ClientHeight;
BorderColor := HtmlToTColor('#ffffff');
BrushColor := HtmlToTColor('#ffffff');
// Here I set the colors of Canvas.Pen (border) and Canvas.Brush (Filling),
// similar to Bootstrap themes/classes (Default, Success, Warning, Danger);
case DialogType of
dtInformation:
begin
BorderColor := HtmlToTColor(Header_Color_Pen_Information);
BrushColor := HtmlToTColor(Header_Color_Brush_Information);
end;
dtSuccess:
begin
BorderColor := HtmlToTColor(Header_Color_Pen_Success);
BrushColor := HtmlToTColor(Header_Color_Brush_Success);
end;
dtWarning:
begin
BorderColor := HtmlToTColor(Header_Color_Pen_Warning);
BrushColor := HtmlToTColor(Header_Color_Brush_Warning);
end;
dtError:
begin
BorderColor := HtmlToTColor(Header_Color_Pen_Error);
BrushColor := HtmlToTColor(Header_Color_Brush_Error);
end;
end;
with Canvas do
begin
Pen.Color := BorderColor;
Pen.Width := Form_Pen_Width;
// Draw rounded borders for Form;
RoundRect(1, 1, Rect.Right - 1, Rect.Bottom - 1, Form_Border_Radius - 1, Form_Border_Radius - 1);
// Rect for Dialog's Header;
Rect.Left := Component_Gutter;
Rect.Top := Component_Gutter;
Rect.Right := ClientWidth - Component_Gutter;
Rect.Bottom := Form_Header_Height;
RoundRect(Component_Gutter, Component_Gutter, ClientWidth - Component_Gutter, Form_Header_Height,
Form_Border_Radius - 2, Form_Border_Radius - 2);
Brush.Color := BrushColor;
FillRect(Rect);
end;
end;
运算符将充当JS中的连接符。由于+
产生一个字符串,因此在这种情况下它将作为连接符。
答案 1 :(得分:0)
这是因为Date
有一个异国情调的@@toPrimitive
,它更喜欢字符串数字。见#sec-date.prototype-@@toprimitive
Date对象在内置ECMAScript对象中是唯一的 对待"默认"等同于" string",所有其他内置 ECMAScript对象处理"默认"等同于"数字"。
答案 2 :(得分:0)
借助 Symbol.toPrimitive 属性(用作函数值),可以将对象转换为原始值。
使用字符串参数提示调用该函数,该参数指定结果原语值的首选类型。提示参数可以是"数字","字符串"和"默认"。
日期对象的语法:Date()[Symbol.toPrimitive](hint);
如果提示是"字符串"或"默认",@@ toPrimitive尝试调用toString方法。如果toString属性不存在,它会尝试调用valueOf方法,如果valueOf也不存在,@@ toPrimitive会抛出TypeError。
如果提示是" number",@@ toPrimitive首先尝试调用valueOf,如果失败,则调用toString。
var date = new Date(2017,1,1);
console.log('hint is "number":',+date + +date); // using unary plus operator
console.log('hint is "default":',date + date); // no hint (falls to hint == 'string')
console.log('hint is "string":',`${date + date}`); // using template literals

+
运算符是所有算术运算符中最混乱的运算符。如果没有提示将Date实例转换为数字,它将充当字符串连接符