我正在阅读书中的第5.5章。我仍然难以看到“我们可以使用章节中的可能性函数来组合各部分中的对象”。
对象是由具有“on”和“fire”功能的事件系统组成的吗?
本书以下部分的代码:
var eventuality = function (that) {
var registry = {};
that.fire = function (event) {
// Fire an event on an object. The event can be either
// a string containing the name of the event or an
// object containing a type property containing the
// name of the event. Handlers registered by the 'on'
// method that match the event name will be invoked.
var array,
func,
handler,
i,
type = typeof event === 'string' ?
event : event.type;
// If an array of handlers exist for this event, then
// loop through it and execute the handlers in order.
if (registry.hasOwnProperty(type)) {
array = registry[type];
for (i = 0; i < array.length; i += 1) {
handler = array[i];
// A handler record contains a method and an optional
// array of parameters. If the method is a name, look
// up the function.
func = handler.method;
if (typeof func === 'string') {
func = this[func];
}
// Invoke a handler. If the record contained
// parameters, then pass them. Otherwise, pass the
// event object.
func.apply(this,
handler.parameters || [event]);
}
}
return this;
};
that.on = function (type, method, parameters) {
// Register an event. Make a handler record. Put it
// in a handler array, making one if it doesn't yet
// exist for this type.
var handler = {
method: method,
parameters: parameters
};
if (registry.hasOwnProperty(type)) {
registry[type].push(handler);
} else {
registry[type] = [handler];
}
return this;
};
return that;
}
答案 0 :(得分:7)
Crockford先生在这里的意思是你可以实现特定的功能,例如on
和fire
函数,通过调用创建它们的函数对象将事件处理添加到任何对象({{1在这种情况下)将该对象作为参数。
这里的“部分”是eventuality
功能对象中包含的“事件处理部分”。您可以想象添加其他功能的不同部分。这里的想法是您可以使用此系统将此功能添加到您需要的单个对象。这个概念称为Mixin(1)。
另请阅读第5章的最后一段:
通过这种方式,构造函数可以从一组零件中组装对象。 JavaScript的松散输入在这里是一个很大的好处,因为我们不会担心关注类的谱系的类型系统。
(1)谢谢你Zecc。
答案 1 :(得分:1)
据我了解,本书这一部分的目的是说明JavaScript的强大功能 - 您可以轻松地使用各种“强大的JavaScript组件”构建一个对象。
正如他所说
例如,我们可以创建一个函数 可以添加简单的事件处理 任何对象的功能。它增加了一个 方法,火法和私人法 事件登记册
答案 2 :(得分:0)
答案 3 :(得分:0)
以下是我自己的测试结果。如果您复制代码并将其粘贴到名为'test.js'的文件中,然后在命令行中通过'node test.js'(必须已经安装了节点)运行它,您将得到相同的结果。我的工作是通过跟踪带有不言自明的注释的流程向您展示如何利用eventuality()。
唯一我不理解的地方是线路; “fund = this [func]”(以“???”作为评论)。看来“func = registry [func]”对我来说更有意义,因为注册表对象是处理程序注册的地方,而不是eventuality函数对象(即'this')。
var eventuality = function(that) {
var registry = {};
that.fire = function(event) {
var type = typeof event === 'string' ? event : event.type;
console.log('fire(): fired on event, "' + type + '"');
if (registry.hasOwnProperty(type)) {
var array = registry[type];
for (var i = 0; i < array.length; ++i) {
var handler = array[i];
console.log('fire(): handler found at loop ' + i);
var func = handler.method;
var pars = handler.parameters;
if (typeof func === 'string') {
console.log('fire(): the found func is a string');
func = this[func]; // ???
} else {
// Invoke the handler with parameters.
console.log('fire(): the found method is NOT a string');
func.apply(this, [pars]);
}
}
}
return this;
};
that.on = function(type, method, parameters) {
// Register an event. Make a handler record. Put it in a handler array, making
// one if it doesn't yet exist for this type.
var handler = {
method: method,
parameters: parameters
};
if (registry.hasOwnProperty(type)) {
// If already registered:
registry[type].push(handler);
} else {
// If it's first time:
console.log('on(): "' + type + '" event registered');
registry[type] = [handler];
}
return this;
}
return that;
};
var dog_is_hungry = {
type: 'is_hungry'
};
var dog_needs_to_poo = {
type: 'needs_to_poo'
};
var dog_methods = {
feed: function() {
console.log('Event processed by the handler, dog_methods.feed(): ');
for (var i = 0; i < arguments.length; ++i) {
console.log(' Feed the dog with the "' + arguments[i].food + '"');
}
},
walk: function() {
console.log('Event processed by the handler, dog_methods.walk(): ');
for (var i = 0; i < arguments.length; ++i) {
console.log(' Walk the dog to the "' + arguments[i].place + '"');
}
}
};
var myDog = {
name: 'Lucky',
age: 2
}
var myDogEHM = eventuality(myDog); // EHM - events handling manager
console.log('My dog is named ' + myDogEHM.name);
console.log('My dog is aged ' + myDogEHM.age);
// Register the event-handlers
myDogEHM.on(dog_is_hungry.type, dog_methods.feed, {
food: 'rice and meat'
});
myDogEHM.on(dog_needs_to_poo.type, dog_methods.walk, {
place: 'park'
});
// Events to be handled
myDogEHM.fire(dog_is_hungry);
myDogEHM.fire(dog_needs_to_poo);
以下是输出:
My dog is named Lucky
My dog is aged 2
on(): "is_hungry"
event registered
on(): "needs_to_poo"
event registered
fire(): fired on event, "is_hungry"
fire(): handler found at loop 0
fire(): the found method is NOT a string
Event processed by the handler, dog_methods.feed():
Feed the dog with the "rice and meat"
fire(): fired on event, "needs_to_poo"
fire(): handler found at loop 0
fire(): the found method is NOT a string
Event processed by the handler, dog_methods.walk():
Walk the dog to the "park"
答案 4 :(得分:0)
我进一步修改了Daniel C Deng的例子,以进一步解释这个[func]的使用。此代码在Chrome中的JavaScript控制台中运行。
var eventuality = function(that) {
var registry = {};
that.fire = function(event) {
var type = typeof event === 'string' ? event : event.type;
console.log('fire(): fired on event, "' + type + '"');
if (registry.hasOwnProperty(type)) {
var array = registry[type];
for (var i = 0; i < array.length; ++i) {
var handler = array[i];
console.log('fire(): handler found at loop ' + i);
var func = handler.method;
var pars = handler.parameters;
if (typeof func === 'string') {
console.log('fire(): the found func is a string');
func = dog_methods_2[func];
//javascript turn string into object reference.
//https://stackoverflow.com/questions/10953303/javascript-interpret-string-as-object-reference
}
// Invoke the handler with parameters.
//console.log('fire(): the found method is NOT a string');
func.apply(this, [pars]);
}
}
return this;
};
that.on = function(type, method, parameters) {
// Register an event. Make a handler record. Put it in a handler array, making
// one if it doesn't yet exist for this type.
var handler = {
method: method,
parameters: parameters
};
if (registry.hasOwnProperty(type)) {
// If already registered:
registry[type].push(handler);
} else {
// If it's first time:
console.log('on(): "' + type + '" event registered');
registry[type] = [handler];
}
return this;
}
return that;
};
var dog_is_hungry = {
type: 'is_hungry'
};
var dog_needs_to_poo = {
type: 'needs_to_poo'
};
var dog_is_thirsty = {
type: 'needs_to_drink'
};
var dog_methods = {
feed: function() {
console.log('Event processed by the handler, dog_methods.feed(): ');
for (var i = 0; i < arguments.length; ++i) {
console.log(' Feed the dog with the "' + arguments[i].food + '"');
}
},
walk: function() {
console.log('Event processed by the handler, dog_methods.walk(): ');
for (var i = 0; i < arguments.length; ++i) {
console.log(' Walk the dog to the "' + arguments[i].place + '"');
}
},
strings: ["drink"]
};
var dog_methods_2 = {
drink: function() {
console.log(" The dog drinks " + arguments[0].drink + ".");
}
}
var myDog = {
name: 'Lucky',
age: 2
}
var myDogEHM = eventuality(myDog); // EHM - events handling manager
console.log('My dog is named ' + myDogEHM.name);
console.log('My dog is aged ' + myDogEHM.age);
// Register the event-handlers
myDogEHM.on(dog_is_hungry.type, dog_methods.feed, {
food: 'rice and meat'
});
myDogEHM.on(dog_needs_to_poo.type, dog_methods.walk, {
place: 'park'
});
// Events to be handled
myDogEHM.fire(dog_is_hungry);
myDogEHM.fire(dog_needs_to_poo);
myDogEHM.on(dog_is_thirsty.type, dog_methods.strings[0], {
drink: 'water'
});
myDogEHM.fire(dog_is_thirsty);
这是输出:
My dog is named Lucky
My dog is aged 2
on(): "is_hungry" event registered
on(): "needs_to_poo" event registered
fire(): fired on event, "is_hungry"
fire(): handler found at loop 0
Event processed by the handler, dog_methods.feed():
Feed the dog with the "rice and meat"
fire(): fired on event, "needs_to_poo"
fire(): handler found at loop 0
Event processed by the handler, dog_methods.walk():
Walk the dog to the "park"
on(): "needs_to_drink" event registered
fire(): fired on event, "needs_to_drink"
fire(): handler found at loop 0
fire(): the found func is a string
The dog drinks water.