抓耳挠腮

感觉已经解决的时候 经过多次以及大数据量测试 发觉各个方式的耗时都没有不同 就连一开始@二石兄
抛出的假象,为什么遍历次数多反而耗时少?的现象都不见了 ? 真是令人抓耳挠腮 返回重新看这个问题 重新测试 重新.... 南辕北辙的故事

看了 二师兄@假象,为什么遍历次数多反而耗时少?抛出的问题
惊讶的发现 还真是!

曾想起在之前的学习过程中,读到过 ES6 的 class 是一个基于原型链的一个语法糖

尝试使用原型链的方式定义这个函数


// es6 Class
class ParseArray {
  constructor(inputArray) {
      this.inputArray = inputArray
      this.outputArray = [{
          "sub_data": []
      }]
      this.loopLength = 0
  }
  loop(pId, items) {
      this.inputArray.forEach((item, idx) => {
          this.loopLength++
              if (item[1] === pId) {
                  items.push({
                      main_data: item.slice(2),
                      sub_data: []
                  })
                  delete this.inputArray[idx] // 录入后删掉该条数据 可降低循环次数
                  this.loop(item[0], items[items.length - 1].sub_data)
              }
      })
  }
}

console.time("es6class")
let val = new ParseArray(array.slice())
val.loop('', val.outputArray[0].sub_data)
// console.log(JSON.stringify(val.outputArray))
console.log('es6class', val.loopLength) // => 26
console.timeEnd("es6class")     // => loop: 3.64501953125ms


// es5 prototype


function ParseArrayEs5 () {
  this.loopLength = 0
  this.outputArray = []
  this.array2 = JSON.parse(JSON.stringify(array))
}

ParseArrayEs5.prototype.loop = function(pId, items) { // 注意 箭头表达式的this指向 与function的this指向不一致 function this指向function 箭头表达式this指向函数的上一级
  this.array2.forEach((item, idx) => {
    this.loopLength++
    if (item[1] === pId) {
        items.push({
            main_data: item.slice(2),
            sub_data: []
        })
        delete this.array2[idx] // 录入后删掉该条数据 可降低循环次数
        this.loop(item[0], items[items.length - 1].sub_data)
    }
  })
}

console.time("es5")

let outputArray666 = new ParseArrayEs5()
outputArray666.loop('', outputArray666.outputArray)
console.log('es5', outputArray666.loopLength) // => 26
console.timeEnd("es5")     // => loop: 0.2919921875ms

Class的运算效率居然差了这么多

Google 查了一下 常见的分析一般都是 new 一个 Class 要比 new 一个 工厂函数效率要低的多
测试用例也基本都是循环new Class
可是本例中只new了一次 照理说 new Class 的损耗只有第一次??

查看了其他文章中提及 Babel 会将ES6 代码转换为ES5 代码
这就去转换了一下

babel转码.png

仔细查看了一下 和别人文章中讲的一致 创建类时要比原型链复杂许多 具体可以搜索相关文章
但与本例情况不同 本例中Class 只new了一次 而 递归的部分 才是大头 把注意力放在 _createdClass 下的 value function loop 中
细看后发现

value: function loop(pId, items) {
            var _this = this; // 绑定this 
            this.inputArray.forEach(function (item, idx) {
                _this.loopLength++; // 如果没有临时变量来绑定this, 将会无法获取loopLength

这是function常用的绑定作用域的方式 用一个临时变量来解决 function 作用域 不一致的问题
但声明临时变量和绑定this是一项多余的动作
修改一下转码后的代码后

_createClass(ParseArray, [{
        key: "loop",
        value: function loop(pId, items) {
            // 删除 var _this = this;
            this.inputArray.forEach((item, idx) => { // 原 this.inputArray.forEach(function (item, idx) {
                this.loopLength++; // 由于修改了作用域 this 生效
                if (item[1] === pId) {
                    items.push({
                        main_data: item.slice(2),
                        sub_data: []
                    });
                    delete this.inputArray[idx]; // // 由于修改了作用域 this 生效
                    this.loop(item[0], items[items.length - 1].sub_data);
                }
            });
        }
    }]);


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容