任何人都可以解释 JavaScript 在调用方法以选择运行哪个函数时所经历的过程吗?我可以找到的大多数在线资源都解释了如何使用 JavaScript 对象实现特定行为,但没有解释方法调度在 JavaScript 中的工作原理。
1 回答
“方法分派”实际上只是属性查找,因为 JavaScript 中的“方法”只是通过对象属性使用的函数。(更多关于我的博客:神话方法)
当你写:
obj.prop
JavaScript 引擎查看obj对象以查看它是否具有名称为 的属性"prop"。如果是,则使用该属性的值。如果没有,引擎会查找原型对象obj以查看它是否具有具有该名称的属性。如果是这样,它使用它的值。如果不是,它会查看该对象的原型。冲洗,重复,直到它用完原型对象。
在某些允许方法重载的语言中,没有任何类型的“方法签名”匹配。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"。确实如此,因此使用了该属性(函数)的值。()after 它调用该函数,该函数返回,"My own"我们就完成了。
console.log(t.test()); // Logs "Thing#test"
对于表达式t.test,引擎t会查看它是否有一个名为 的属性"test"。它没有,所以引擎会查看t的原型。t的原型是Thing.prototype,它是在表达式期间分配给它的new Thing。Thing.prototype有一个"test"属性,所以使用那个(函数)的值。然后()after 它调用该函数,该函数返回 string "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
"foo"引擎在t、t的原型或t' 原型的原型上找不到。现在它没有原型了,所以表达式的t.foo结果是undefined. 然后我们尝试通过调用它(),我们不能这样做,因为undefined它不是一个函数。