我很懒,我只想传 fn 和 dependencies 两个属性,不想做额外的事情。好吧,我们来重构一下构造函数:
var _setupTask = function(fn, level, name, dependencies) { if(typeof fn !== FUNCTION) { throw new Error('Invalid argument type: fn.'); } this.fn = fn; this.level = _validateLevel(level) ? level : LEVEL_NORMAL;
// detect type of name this.name = typeof name === STRING && name ? name : 't' + _id++;
// dependencies could be retrieved as an 'Object', so use instanceof instead. this.dependencies = dependencies instanceof Array ? dependencies : []; };
var T = SmartQueue.Task = function(task) { if(arguments.length > 1) { _setupTask.apply(this, arguments); } else { _setupTask.call(this, task.fn, task.level, task.name, task.dependencies); }
// init context/scope and data for the task. this.context = task.context || window; this.data = task.data || {}; };
如此一来,原来的构造方式可以继续工作,而上面的懒人可以这样传入一个“残废体”:
var task1 = new SmartQueue.Task({fn: obj.fn, dependencies: obj.dependencies});
当构造函数收到多个参数时,按之前的方案等同处理;否则,视唯一的参数为 Task 对象或“残废体”。这里通过 JavaScript 中的 apply/call 方法将新实例传给重构出来的 _setupTask 方法,作为该方法的上下文 (context, 也有称为 scope), apply/call 是 JavaScript 在方法之间传递上下文的法宝,要用心体会哦。同时,允许用户定义 task.fn 在执行时的上下文,并将自定义的数据传递给执行中的 fn.
经典的 JavaScript 对象三段式是什么?
- 定义对象的构造函数
- 在原型上定义属性和方法
- new 对象,拿来用
所以,下面要为 SmartQueue.Task 对象的原型定义属性和方法。上期分析过 Task (任务)有几个属性和方法,部分属性我们已经在 _setupTask 中定义了,下面是原型提供的属性和方法:
T.prototype = { enabled: true, register: function() { var queue = Q[this.level]; if(_findTask(queue, this.name) !== -1) { throw new Error('Specified name exists: ' + this.name); } queue.push(this); }, changeTo: function(level) { if(!_validateLevel(level)) { throw new Error('Invalid argument: level'); } level = parseInt(level, 10); if(this.level === level) { return; } Q[this.level].remove(this); this.level = level; this.register(); }, execute: function() { if(this.enabled) { // pass context and data this.fn.call(this.context, this.data); } }, toString: function() { var str = this.name; if(this.dependencies.length) { str += ' depends on: [' + this.dependencies.join(', ') + ']'; } return str; } };
如你所见,逻辑非常简单,也许你已经在一分钟内扫过了代码,嘴角不经意间露出一丝心领神会。不过,这里要说的是简单而且通常最不被重视的 toString 方法。在一些高级语言中,为自定义对象实现 toString 方法被作为最佳实践准则而推荐,为什么呢?因为 toString 可以很方便地在调试器中提供有用的信息,可以方便地将对象基本信息写入日志;在统一的编程模式中,实现 toString 可以让你少写一些代码。
出处:Alipay UED
责任编辑:bluehearts
上一页 JavaScript组件之旅:编码实现和算法 [1] 下一页 JavaScript组件之旅:编码实现和算法 [3]
◎进入论坛网页制作、WEB标准化版块参加讨论,我还想发表评论。
|