2013-04-10 3 views
12

Я бы ожидал, что родная версия будет быстрее.Производительность - Array.forEach по сравнению с реализованной версией

Что дает?

http://jsperf.com/native-vs-implmented-0

Реализация

function each (obj, func, context) { 
    var kindex, 
     length; 
    for (kindex = 0, length = obj.length; kindex < length; kindex++) { 
     func.call(context, obj[kindex], kindex, obj); 
    } 
} 

Test Cases

// implemented 
each([0,1,2,3], function(val){ 
    val++; 
}) 

против

// native 
[0,1,2,3].forEach(function(val){ 
    val++ 
}) 

ответ

7

Ну, вот как Array.forEach реализован внутри страны. Как вы видите, есть много проверок, а не прямо, как ваша реализация.

См https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach

if (!Array.prototype.forEach) { 
  
  Array.prototype.forEach = function forEach(callback, thisArg) { 
  
    var T, k; 
  
    if (this == null) { 
      throw new TypeError("this is null or not defined"); 
    } 
  
    // 1. Let O be the result of calling ToObject passing the |this| value as the argument. 
    var O = Object(this); 
  
    // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length". 
    // 3. Let len be ToUint32(lenValue). 
    var len = O.length >>> 0; // Hack to convert O.length to a UInt32 
  
    // 4. If IsCallable(callback) is false, throw a TypeError exception. 
    // See: http://es5.github.com/#x9.11 
    if ({}.toString.call(callback) !== "[object Function]") { 
      throw new TypeError(callback + " is not a function"); 
    } 
  
    // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. 
    if (thisArg) { 
      T = thisArg; 
    } 
  
    // 6. Let k be 0 
    k = 0; 
  
    // 7. Repeat, while k < len 
    while(k < len) { 
  
      var kValue; 
  
      // a. Let Pk be ToString(k). 
      //   This is implicit for LHS operands of the in operator 
      // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk. 
      //   This step can be combined with c 
      // c. If kPresent is true, then 
      if (Object.prototype.hasOwnProperty.call(O, k)) { 
  
        // i. Let kValue be the result of calling the Get internal method of O with argument Pk. 
        kValue = O[ k ]; 
  
        // ii. Call the Call internal method of callback with T as the this value and 
        // argument list containing kValue, k, and O. 
        callback.call(T, kValue, k, O); 
      } 
      // d. Increase k by 1. 
      k++; 
    } 
    // 8. return undefined 
  }; 
} 
+2

Вот как он подгоняется так близко, насколько это возможно в ECMAScript. Я бы не зашел так далеко, чтобы сказать, что это делается внутри. – 2013-04-10 16:04:21

+1

«Этот алгоритм точно такой, который указан в ECMA-262, 5th edition» от mozilla. – NimChimpsky

+0

вправо ... скорее всего, он будет написан на компилированном языке, когда он будет реализован в браузере ... – 2013-07-04 00:47:21

6

forEach() делает больше, чем ваша реализация. Если вам не нужны дополнительные усилия, которые выполняет официальный алгоритм, простая реализация, такая как ваша, действительно предпочтительнее, когда требуется необработанная скорость.

«Официальный» алгоритм описан в the MDN reference for Array.forEach.

+1

* "контекст привязки" * Вы предлагаете, что родной '.forEach()' на самом деле делает что-то похожее на родной '.bind()'? Если это так, это не так. Он просто устанавливает значение 'this' функции, которую он вызывает. – 2013-04-10 16:01:10

+0

@amnotiam, вы правы, я отредактирую свой ответ :) – robertklep

+0

... что он делает «больше», чем моя «простая реализация»? – 2013-07-04 00:50:07

Смежные вопросы