任何人都可以解释 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
它不是一个函数。