如何在 JavaScript 中使用类似 PHP 的魔术方法
JavaScript 魔术方法
这个脚本使用 Proxy 实现了在 JavaScript 中使用类似于 PHP 中的魔术方法。
示例
你可以这样使用它:
const Foo = magicMethods(class Foo {
constructor () {
this.bar = 'Bar'
}
__get (name) {
return `[[${name}]]`
}
})
const foo = new Foo
foo.bar // "Bar"
foo.baz // "[[baz]]"
如果你使用的是像 Babel 这样的 JavaScript 编译器,并启用了装饰器, 你还可以使用 magicMethods
函数作为装饰器:
@magicMethods
class Foo {
// ...
}
支持魔术方法
给定一个类 Class
和 instance
,以下是此脚本支持的魔术方法:
__get(name)
当尝试访问 instance[name]
,而 name
不是 instance
中的属性时,调用。
注意: 在 PHP中,检查 instance
中是否存在 name
不会使用任何自定义的 __isset()
方法。
__set(name, value)
当尝试使用instance[name] = ...
,而 instance
并未设置 name
属性时,调用该方法。
__isset(name)
当尝试通过调用 name in instance
来检查是否存在 name
是否存在时,调用该方法。
__unset(name)
当尝试通过 delete instance[name]
来取消 name
属性设置时,调用该方法。
其他方法
下面的魔术方法是通过该脚本提供支持的,但不支持在PHP:
static __getStatic(name)
类似于 __get()
,但是它用在 Class
而不是 instance
.
static __setStatic(name, value)
类似于 __set()
,但是用在 Class
中而不是 instance
。
为什么不支持魔术方法 X
?
它们不是没有必要就是不实用:
__construct()
不需要,JavaScript 早有constructor
。__destruct()
:JavaScript 中没有对象销毁的钩子机制。__call()
:与 PHP 相反,方法就像 JavaScript 中的属性一样,首先通过__get()
获取。要实现__call()
,你只需从get()
返回一个函数。__callStatic()
:与__call()
类似,但是具有__getStatic()
。__sleep()
,__wakeup()
:JavaScript 没有内置序列化与反序列化。你可以使用JSON.stringify()
与JSON.parse()
,但是它们没有机制自动触发的任何方法。__toString()
在早有对应 JavaScript 的toString()
__invoke()
:如果你试图调用一个非函数对象,JavaScript 将会抛出一个错误,这将无法避免。__set_state()
:JavaScript 中没有类似于var_export()
的东西。__clone()
:JavaScript 中内置克隆功能的钩子。__debugInfo()
: 无法挂接到console.log()
输出。
我可以使用魔术方法扩展类吗?
是的,在一定程度上:
class Bar extends Foo {}
// 或者,如果类 Bar 本身包含魔术方法:
const Bar = magicMethods(class Bar extends Foo {
// ...
})
但是遗憾的是,你无法从子类中访问父类中的属性:
const Foo = magicMethods(class Foo {
__get() {
return this.bar()
}
})
class Bar extends Foo {
bar() {
return 'value'
}
}
// 这个 *不会* 调用 B 的 bar() 方法,而是抛出一个类型错误:
(new Bar).something
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。