简介:你无法在两个或两个以上互相(双向)委托的对象之间创建循环委托。如果你把 B 关联到 A 然后试着把 A 关联到 B,就会出错。很遗憾(并不是非常出乎意料,但是有点烦人)这种方法是被禁止的。如果你引用了一个 两边都 ...
你无法在两个或两个以上互相(双向)委托的对象之间创建循环委托。如果你把 B 关联到 A 然后试着把 A 关联到 B,就会出错。很遗憾(并不是非常出乎意料,但是有点烦人)这种方法是被禁止的。如果你引用了一个 两边都不存在的属性或者方法,那就会在 [[Prototype]] 链上产生一个无限递归的循环。 但是如果所有的引用都被严格限制的话,B 是可以委托 A 的,反之亦然。因此,互相委托 理论上是可以正常工作的,在某些情况下这是非常有用的。之所以要禁止互相委托,是因为引擎的开发者们发现在设置时检查(并禁止!)一次无限 循环引用要更加高效,否则每次从对象中查找属性时都需要进行检查。 调试 我们来简单介绍一个容易让开发者感到迷惑的细节。通常来说,JavaScript 规范并不会控 制浏览器中开发者工具对于特定值或者结构的表示方式,浏览器和引擎可以自己选择合适 的方式来进行解析,因此浏览器和工具的解析结果并不一定相同。比如,下面这段代码的 结果只能在 Chrome 的开发者工具中才能看到。
我们看代码的最后一行:表达式 a1 的输出是 Foo {}。如果你在 Firefox 中运行同样的代码 会得到 Object {}。为什么会这样呢?这些输出是什么意思呢?Chrome 实际上想说的是“{} 是一个空对象,由名为 Foo 的函数构造”。Firefox 想说的是“{} 是一个空对象,由 Object 构造”。之所以有这种细微的差别,是因为 Chrome 会动态跟踪并把 实际执行构造过程的函数名当作一个内置属性,但是其他浏览器并不会跟踪这些额外的信息。看起来可以用 JavaScript 的机制来解释 Chrome 的跟踪原理:function Foo() {} var a1 = new Foo(); a1.constructor; // Foo(){} a1.constructor.name; // "Foo"Chrome 是不是直接输出了对象的 .constructor.name 呢?令人迷惑的是,答案是“既是又 不是”。思考下面的代码: 
即使我们把 a1.constructor.name 修改为另一个合理的值(Gotcha),Chrome 控制台仍然会 输出 Foo看起来之前那个问题(是否使用 .constructor.name ?)的答案是“不是”;Chrome 在内 部肯定是通过另一种方式进行跟踪。除了这个 bug,Chrome 内部跟踪(只用于调试输出)“构造函数名称”的方法是 Chrome 自身的一种扩展行为,并不包含在 JavaScript 的规范中。如果你并不是使用“构造函数”来生成对象,比如使用本章介绍的对象关联风格来编写代 码,那 Chrome 就无法跟踪对象内部的“构造函数名称”,这样的对象输出是 Object {}, 意思是“Object() 构造出的对象”。 当然,这并不是对象关联风格代码的缺点。当你使用对象关联风格来编写代码并使用行 为委托设计模式时,并不需要关注是谁“构造了”对象(就是使用 new 调用的那个函数)。 只有使用类风格来编写代码时 Chrome 内部的“构造函数名称”跟踪才有意义,使用对象 关联时这个功能不起任何作用。本文仅代表作者个人观点,不代表巅云官方发声,对观点有疑义请先联系作者本人进行修改,若内容非法请联系平台管理员,邮箱2522407257@qq.com。更多相关资讯,请到巅云www.yx10011.com学习互联网营销技术请到巅云建站www.yx10011.com。 |