1

我有一个对象文字:

var tasks = {};

我基本上添加了这样的东西:

function addTask(task) {
  tasks[task.id] = task
}

我想修改它,以便我可以start在每个任务上调用一个函数。所以:

var tasks = {};
tasks.__proto__.start = function(key) {
  // do stuff with this[key]
}

function addTask(task) {
  tasks[task.id] = task
  tasks.start(task.id)
}

我听说最好避免使用proto对象并且它会减慢执行速度。但是我没有重新分配它,我正在附加它。

有没有被认为更好的替代方案?

4

2 回答 2

4

实际上没有必要为此使用原型。您不会创建许多需要在更高级别抽象出通用功能的实例,您只需在tasks对象上添加一个方法即可。

const tasks = {
  start(key) {
    const task = this[key]
    // do stuff with task
  }
}

// example call
tasks.start('123'); 

如果要确保与现有密钥没有冲突,可以使用Symbol代替。

const startSymbol = Symbol('start');
const tasks = {
  [startSymbol](key) {
    const task = this[key]
    // do stuff with task
  }
}

// example call
tasks[startSymbol]('123'); 

您也可以只使用一个独立的函数来执行此操作,类似于您的addTask函数:

function start(tasks, key) {
  const task = tasks[key]
  // do stuff with task
}

// example call
start(tasks, '123')

拥有这个独立的功能可能会更好,因为您不必担心任务键和方法名称之间的冲突。

您还可以创建一个执行此分离的包装器对象:

const taskManager = {

  tasks: {} // map of key to task

  // methods
  add(task) {
    this.tasks[task.id] = task;
    this.start(task.id);
  }
  start(key) {
    const task = this.tasks[key];
    // do stuff with task
  }
}

// example usage
taskManager.start('123')

这种方法的优点是你tasks被封装在一个容器中,对它们进行操作,限制了tasks应该使用的范围,并更清楚地(向程序员建议)哪些函数应该用于任务。

如果您计划拥有多个任务管理器,那么在这里使用原型可能是有意义的:

class TaskManager {
  constructor() {
    this.tasks = {}  // map of key to task
  }

  // methods
  add(task) {
    this.tasks[task.id] = task;
    this.start(task.id);
  }
  start(key) {
    const task = this.tasks[key];
    // do stuff with task
  }
}

// example usage
new TaskManager().start('123')
于 2017-08-07T19:45:39.017 回答
3

从性能和浏览器兼容性的角度来看,这都不是一个好主意。

请参阅Mozilla 文档中的这些警告:

警告:根据现代 JavaScript 引擎优化属性访问的本质,在每个浏览器和 JavaScript 引擎中,更改对象的 [[Prototype]] 是一项非常缓慢的操作。更改继承对性能的影响是微妙而广泛的,并且不仅限于在 obj 中花费的时间。proto = ... 语句,但可以扩展到可以访问 [[Prototype]] 已更改的任何对象的任何代码。如果您关心性能,则应避免设置对象的 [[Prototype]]。相反,使用 Object.create() 创建一个具有所需 [[Prototype]] 的新对象。

--

警告:虽然 Object.prototype。proto现在在大多数浏览器中都得到支持,它的存在和确切行为仅在 ECMAScript 2015 规范中作为遗留功能进行了标准化,以确保 Web 浏览器的兼容性。为了获得更好的支持,建议只使用 Object.getPrototypeOf() 代替。

于 2017-08-07T19:49:14.253 回答