【发布时间】:2013-11-24 23:59:19
【问题描述】:
谁能解释当调用一个方法来选择运行哪个函数时 JavaScript 所经历的过程?我可以找到的大多数在线资源都解释了如何使用 JavaScript 对象实现特定行为,但没有解释方法调度在 JavaScript 中的工作原理。
【问题讨论】:
标签: javascript methods dispatch
谁能解释当调用一个方法来选择运行哪个函数时 JavaScript 所经历的过程?我可以找到的大多数在线资源都解释了如何使用 JavaScript 对象实现特定行为,但没有解释方法调度在 JavaScript 中的工作原理。
【问题讨论】:
标签: javascript methods dispatch
“方法调度”实际上只是属性查找,因为 JavaScript 中的“方法”只是通过对象属性使用的函数。 (更多关于我的博客:Mythical methods)
当你写作时:
obj.prop
JavaScript 引擎会查看obj 对象以查看它是否具有名称为"prop" 的属性。如果是,则使用该属性的值。如果没有,引擎会查找obj 的原型对象,以查看 it 是否具有具有该名称的属性。如果是这样,它使用它的值。如果不是,它会查看 那个 对象的原型。冲洗,重复,直到用完原型对象。
在某些允许方法重载的语言中,没有任何类型的“方法签名”匹配。 JavaScript 没有方法重载。给定名称的对象只能附加一个属性。
我们来看一个例子:
function Thing() {
}
Thing.prototype.test = function() {
return "Thing#test";
};
var t = new Thing();
t.own = function() {
return "My own";
};
现在让我们一起玩t:
console.log(t.own()); // Logs "My own"
对于表达式t.own,引擎会查看t 以查看它是否具有名为"own" 的属性。确实如此,因此使用了该属性(函数)的值。之后的()调用该函数,该函数返回"My own",我们就完成了。
console.log(t.test()); // Logs "Thing#test"
对于表达式t.test,引擎会查看t 以查看它是否具有名为"test" 的属性。它没有,所以引擎查看t 的原型。 t 的原型是 Thing.prototype,它是在表达式 new Thing 期间分配给它的。 Thing.prototype 有一个 "test" 属性,所以使用那个(一个函数)的值。然后是(),在它调用那个函数之后,返回字符串"Thing#test"。
console.log(t.toString()); // Logs "[object Object]"
引擎查看t,没有找到"toString"属性,所以它查看t的原型,也没有找到"toString"属性,所以它查看t的原型的原型(即Object.prototype)。 确实有一个"toString" 属性,它的值是一个函数。然后()调用该函数,该函数返回"[object Object]"。
最后,为了完整性:
console.log(t.foo()); // Throws an error
引擎在t、t 的原型或t 的原型的原型上找不到"foo"。现在它没有原型了,所以表达式t.foo 的结果是undefined。然后我们尝试通过() 调用它,因为undefined 不是函数,所以我们不能这样做。
【讨论】: