为什么字符串变量可以在JS中通过调用使用forEach方法?

时间:2016-10-27 01:53:44

标签: javascript



var rst = 0;   
var num = 0;
Array.prototype.forEach.call(num + '', function(v){ rst += +v; });




你可以从上面看到。 num是一个数字,然后我们将其num+''转换为字符串。控制台显示没有错误。

令我困惑的是,num是一个字符串,为什么它可以使用forEach方法?

2 个答案:

答案 0 :(得分:2)

在所有符合标准的JS实现中,任何类似数组的对象都可以使用Array.prototype中的函数,包括字符串:

var arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 }; // same as 'abc'

Array.prototype.forEach.call(arrayLike, function(val) {
  console.log(val);  
});

答案 1 :(得分:1)

您没有调用可能是String原型成员的forEach函数。您明确调用Array原型forEach并告诉它将thisArg视为Array。根据您的运行时环境,forEach的实现可能取决于浏览器/环境,但最坏的情况是它什么都不做,并默默地返回undefined

这是webkit的一些来源。有一些特定于数组的代码,但一般来说没有理由它几乎不能用于任何事情。

EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec)
{
    JSObject* thisObj = exec->hostThisValue().toObject(exec);
    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    JSValue function = exec->argument(0);
    CallData callData;
    CallType callType = getCallData(function, callData);
    if (callType == CallTypeNone)
        return throwVMTypeError(exec);

    JSValue applyThis = exec->argument(1);

    unsigned k = 0;
    if (callType == CallTypeJS && isJSArray(thisObj)) {
        JSFunction* f = jsCast<JSFunction*>(function);
        JSArray* array = asArray(thisObj);
        CachedCall cachedCall(exec, f, 3);
        for (; k < length && !exec->hadException(); ++k) {
            if (UNLIKELY(!array->canGetIndexQuickly(k)))
                break;

            cachedCall.setThis(applyThis);
            cachedCall.setArgument(0, array->getIndexQuickly(k));
            cachedCall.setArgument(1, jsNumber(k));
            cachedCall.setArgument(2, thisObj);

            cachedCall.call();
        }
    }
    for (; k < length && !exec->hadException(); ++k) {
        PropertySlot slot(thisObj);
        if (!thisObj->getPropertySlot(exec, k, slot))
            continue;

        MarkedArgumentBuffer eachArguments;
        eachArguments.append(slot.getValue(exec, k));
        eachArguments.append(jsNumber(k));
        eachArguments.append(thisObj);

        if (exec->hadException())
            return JSValue::encode(jsUndefined());

        call(exec, function, callType, callData, applyThis, eachArguments);
    }
    return JSValue::encode(jsUndefined());
}