题目:
函数add可以实现连续的加法运算
函数add语法如下:
add(num1)(num2)(num3)…;
使用举例如下:
add(10)(10) = 20
add(10)(20)(50) = 80
add(10)(20)(50)(100) = 180
请使用js代码实现函数add
答案:
function add(n){
var sum=n,
fn=function(x){
sum+=x;
return fn;
};
fn.toString=function(){
return sum;
};
return fn;
}
alert(add(1)(2)+add(1)(2)(3)); //9
解释:
fn是一个function,类型为Object,
+会默认调用fn的toString方法,
这个toString方法不一定返回一个字符串,
本例中返回了一个数字。
规范:
Ecmascript 2015 P36
7.1 Type Conversion
The ECMAScript language implicitly performs automatic type conversion as needed.
To clarify the semantics of certain constructs it is useful to define a set of conversion abstract operations. The conversion abstract operations are polymorphic; they can accept a value of any ECMAScript language type or of a Completion Record value. But no other specification types are used with these operations.
Ecmascript 2015 P42
7.1.12 ToString (argument)
The abstract operation ToString converts argument to a value of type String according to Table 12:
Table 12 — ToString Conversions
Completion Record:
If argument is an abrupt completion, return argument.
Otherwise return ToString(argument.[[value]]).
Undefined:
Return "undefined".
Null :
Return "null".
Boolean :
If argument is true, return "true".
If argument is false, return "false".
Number :
See 7.1.12.1.
String :
Return argument.
Symbol :
Throw a TypeError exception.
Object :
Apply the following steps:
- Let primValue be ToPrimitive(argument, hint String).
- Return ToString(primValue).
Ecmascript 2015 P36
7.1.1 ToPrimitive (input, [, PreferredType])
The abstract operation ToPrimitive takes an input argument and an optional argument PreferredType. The abstract operation ToPrimitive converts its input argument to a non-Object type. If an object is capable of converting to more than one primitive type, it may use the optional hint PreferredType to favour that type.
Conversion occurs according to Table 9:
Table 9 — ToPrimitive Conversions
Completion Record :
If input is an abrupt completion, return input.
Otherwise return ToPrimitive(input.[[value]]) also passing the optional hint PreferredType.
Undefined :
Return input.
Null :
Return input.
Boolean :
Return input.
Number :
Return input.
String :
Return input.
Symbol :
Return input.
Object :
Perform the steps following this table.
When Type(input) is Object, the following steps are taken:
- If PreferredType was not passed, let hint be "default".
- Else if PreferredType is hint String, let hint be "string".
- Else PreferredType is hint Number, let hint be "number".
- Let exoticToPrim be GetMethod(input , @@toPrimitive).
- ReturnIfAbrupt(exoticToPrim).
- If exoticToPrim is not undefined, then
a. Let result be Call(exoticToPrim, input , «hint»).
b. ReturnIfAbrupt(result).
c. If Type(result) is not Object, return result.
d. Throw a TypeError exception. - If hint is "default", let hint be "number".
- Return OrdinaryToPrimitive(input ,hint ).
When the abstract operation OrdinaryToPrimitive is called with arguments O and hint, the following steps are taken:
- Assert: Type(O) is Object
- Assert: Type(hint) is String and it s value is either "string" or "number".
- If hint is "string", then
a. Let methodNames be «"toString", "valueOf"». - Else,
a. Let methodNames be «"valueOf", "toString"». - For each name in methodNames in List order, do
a. Let method be Get( O, name).
b. ReturnIfAbrupt(method).
c. If IsCallable( method) is true, then
i. Let result be Call(method, O).
ii. ReturnIfAbrupt(result).
iii. If Type(result) is not Object, return result. - Throw a TypeError exception.
**NOTE **
When ToPrimitive is called with no hint, then it generally behaves as if the hint were Number. However, objects may over-ride this behaviour by defining a @@toPrimitive method. Of the objects defined in this specification only Date objects (see 20.3.4.45) and Symbol objects (see 19.4.3.4) over-ride the default ToPrimitive behaviour.
Date objects treat no hint as if the hint were String.
Ecmascript 2015 P169
12.7.3 The Addition operator ( + )
NOTE
The addition operator either performs string concatenation or numeric addition.
Runtime Semantics: Evaluation 12.7.3.1
AdditiveExpression : AdditiveExpression + MultiplicativeExpression
- Let lref be the result of evaluating AdditiveExpression.
- Let lval be GetValue(lref ).
- ReturnIfAbrupt(lval ).
- Let rref be the result of evaluating MultiplicativeExpression.
- Let rval be GetValue(rref).
- ReturnIfAbrupt(rval).
- Let lprim be ToPrimitive(lval ).
- ReturnIfAbrupt(lprim).
- Let rprim be ToPrimitive( rval).
- ReturnIfAbrupt(rprim).
- If Type(lprim) is String or Type(rprim) is String, then
a. Let lstr be ToString(lprim).
b. ReturnIfAbrupt(lstr).
c. Let rstr be ToString(rprim).
d. ReturnIfAbrupt(rstr).
e. Return the String that is the result of concatenating lstr and rstr. - Let lnum be ToNumber(lprim).
- ReturnIfAbrupt(lnum).
- Let rnum be ToNumber(rprim).
- ReturnIfAbrupt(rnum).
- Return the result of applying the addition operation to lnum and rnum. See the Note below 12.7.5.
NOTE 1
No hint is provided in the calls to ToPrimitive in steps 7 and 9. All standard objects except Date objects handle the absence of a hint as if the hint Number were given; Date objects handle the absence of a hint as if the hint String were given. Exotic objects may handle the absence of a hint in some other manner.
NOTE 2
Step 11 differs from step 5 of the Abstract Relational Comparison algorithm (7.2.11), by using the logical-or operation instead of the logical-and operation.