Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

遍历原型链

  最近造的一些轮子中用到了奇奇怪怪的树形结构,甚至还有冒泡的概念。既然 JS 原型链本身是一个树形结构,为何不直接用呢?其实这个死我不止作过一次,之前实现基于冒泡的事件模型就使用过原型链遍历。而且作过一个数组继承的大死,结果被大家喷成狗了。
  然而我依然觉得遍历原形链在一些框架级代码的实现中很有用,于是继续作死,比如下面这么玩 <script> // 从 base 的原型链上取处所有 name 属性(如果有) let getPropertiesFromChain = function*(base, name) { for(let i = base; i; i = Object.getPrototypeOf(i)) { let desc = Object.getOwnPropertyDescriptor(i, name); // 如果是一个 getter 属性就调用它 // 然而此处的 call 应该传入 base 还是 i 视具体业务需求 if (desc) yield desc.get ? desc.get.call(base) : desc.value; } }; // 搞一个大新闻 class A { get value() { return 0; } } class B extends A { get value() { return 1; } } class C extends B { get value() { return 2; } } class D extends C { get value() { return 3; } } let x = new D(); // 取出 x 原型链中的所有 value 属性 let values = getPropertiesFromChain(x, 'value'); // 求和 let sum = [...values].reduce((s, i) => s + i); console.log(sum); // 6 </script>   上面的代码中,使用 getOwnPropertyDescriptor 来获取对象的属性是为了避免直接访问一个对象属性时从原型链取值。在这个流程中,最难处理的应该是 getter 属性,因为不知道用什么东西作为 getter 的 this 好。比如下面这种情况 class A { constructor() { this.$x = 0; } get x() { return this.$x; } } class B extends A { constructor(x) { super(); this.$x = x; } } let b = new B(123); console.log(...getPropertiesFromChain(b, 'x'));   这个例子中 getter 函数从 this 上取值,如果在 call 的时候传入的 this 不一样就会得到不同的结果。
网名:
34.203.245.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^