提炼出一个常见的习语

Abstracting out a common idiom

本文关键字:一个 常见 习语      更新时间:2023-09-26

在此代码中

if (direction === 'up') {
    for (key in elements) {
        if (elements.hasOwnProperty(key)) {
            elements[key].style.opacity = statics.elapsed / max_time;
        }
    }
} else if (direction === 'down') {
    for (key in elements) {
        if (elements.hasOwnProperty(key)) {
            elements[key].style.opacity = (max_time - statics.elapsed) / max_time;
        }
    }
}

我想抽象出一个常见的习语:

for (key in elements) {
    if (elements.hasOwnProperty(key)) {
        // function using elements[key] and outside parameters
    }
}

所以我可以简单地写

manyElements(element, function () {
});

我将如何编写函数原型作为起点。我的猜测是。

function manyElements (elements, the_function) {
    for (key in elements) {
        if (elements.hasOwnProperty(key)) {
            the_function();
        }
    }
}

但我需要访问外部参数,传递这些参数的最佳方式是什么?一般来说,抽象出这些代码是个好主意吗?

似乎我必须单独传递每个参数,以达到创建通用函数的目的。

除了相关性,我不喜欢不使用外部库。这里的每个答案是lodash实现:

代码段1

  function forEach(collection, callback, thisArg) {
    if (callback && typeof thisArg == 'undefined' && isArray(collection)) {
      var index = -1,
          length = collection.length;
      while (++index < length) {
        if (callback(collection[index], index, collection) === false) {
          break;
        }
      }
    } else {
      each(collection, callback, thisArg);
    }
    return collection;
  }

代码段2

var each = createIterator(eachIteratorOptions); 

代码段3

  function createIterator() {
    var data = {
      'arrayLoop': '',
      'bottom': '',
      'hasDontEnumBug': hasDontEnumBug,
      'isKeysFast': isKeysFast,
      'objectLoop': '',
      'nonEnumArgs': nonEnumArgs,
      'noCharByIndex': noCharByIndex,
      'shadowed': shadowed,
      'top': '',
      'useHas': true
    };
    // merge options into a template data object
    for (var object, index = 0; object = arguments[index]; index++) {
      for (var key in object) {
        data[key] = object[key];
      }
    }
    var args = data.args;
    data.firstArg = /^[^,]+/.exec(args)[0];
    // create the function factory
    var factory = Function(
        'createCallback, hasOwnProperty, isArguments, isString, objectTypes, ' +
        'nativeKeys, propertyIsEnumerable',
      'return function(' + args + ') {'n' + iteratorTemplate(data) + ''n}'
    );
    // return the compiled function
    return factory(
      createCallback, hasOwnProperty, isArguments, isString, objectTypes,
      nativeKeys, propertyIsEnumerable
    );
  }

首先,有些库已经完成了这项工作,比如lodash或underlinehttp://lodash.com/docs#forEach作用

其次,您可以使用Object.keys(elements).forEach(function(key){…})来简化代码。

第三,您可能需要了解JavaScript函数——它们可以作为参数传递给其他函数,然后被调用。像这样:

function do(something) {
 ...
 something(item);
 ...
}
do(function (arg) { console.log(arg); });

如果您在代码中多次这样做,那么将其抽象出来并没有错。您几乎已经得到了答案:只需将所需的参数传递回传递给manyElements的函数即可。我会同时传递键和值,因为在某些地方可能需要键(例如,将赋值更改为其他值)。

function manyElements (elements, the_function) {
    for (key in elements) {
        if (elements.hasOwnProperty(key)) {
            the_function(key, elements[key]);
        }
    }
}

用法如下:

if (direction === 'up') {
    manyElements(elements, function (key, value) {
        value.style.opacity = statics.elapsed / max_time;
    });
} else if (direction === 'down') {
    manyElements(elements, function (key, value) {
        value.style.opacity = (max_time - statics.elapsed) / max_time;
    });
}

不过,我不会调用manyElements函数,因为这个名称并不能真正解释函数的作用。像forEachProperty这样的东西可能更自我记录。