js如何获取原型链上的所有方法

要获取javascript对象原型链上的所有方法,必须沿原型链逐层遍历,使用object.getownpropertynames和object.getownpropertysymbols获取每层的自有属性(包括不可枚举的),再通过object.getownpropertydescriptor筛选出值为函数且非constructor的属性,最终去重返回;1. 使用while循环通过object.getprototypeof向上遍历直到null;2. 每层调用object.getownpropertynames和object.getownpropertysymbols获取所有字符串和symbol键名;3. 遍历所有键名,用object.getownpropertydescriptor判断属性值是否为函数并排除constructor;4. 使用try…catch避免因宿主对象或proxy导致的异常;5. 利用set去重后转为数组返回。该方法能完整获取原型链上所有方法,解决了for…in无法访问不可枚举属性、无法区分自有与继承属性等问题,适用于绝大多数标准与非标准场景。

js如何获取原型链上的所有方法

要获取JavaScript对象原型链上的所有方法,核心思路是沿着原型链向上遍历,在每一层原型对象上,分别找出其自身定义的所有属性(包括不可枚举的),然后筛选出其中类型为函数的那些。这比你想象的要复杂一点点,因为简单的

for...in

循环并不能满足要求。

js如何获取原型链上的所有方法

解决方案

要完整地获取一个对象原型链上的所有方法,你需要一个循环来向上追溯原型链,并结合

Object.getOwnPropertyNames()

Object.getOwnPropertySymbols()

来捕获每一层原型上的自有属性,最后筛选出函数。

function getAllPrototypeMethods(obj) {    const methods = new Set(); // 使用Set避免重复    let current = obj;    // 循环向上遍历原型链,直到current为null(Object.prototype的原型是null)    while (current) {        // 获取当前原型对象自身的所有字符串属性名(包括不可枚举的)        const propNames = Object.getOwnPropertyNames(current);        // 获取当前原型对象自身的所有Symbol属性名        const symbolProps = Object.getOwnPropertySymbols(current);        // 合并所有属性名        const allProps = [...propNames, ...symbolProps];        allProps.forEach(prop => {            // 尝试获取属性描述符,以判断是否是函数            // 这么做更严谨,因为直接obj[prop]可能会触发getter或报错            try {                const descriptor = Object.getOwnPropertyDescriptor(current, prop);                if (descriptor && typeof descriptor.value === 'function') {                    // 确保不是构造函数本身(通常我们不关心这个)                    if (prop !== 'constructor') {                        methods.add(prop);                    }                }            } catch (e) {                // 某些特殊属性可能无法获取描述符,这里简单忽略                // 比如一些宿主对象或Proxy对象                console.warn(`无法获取属性描述符: ${String(prop)}`, e);            }        });        // 向上移动到下一个原型        current = Object.getPrototypeOf(current);    }    return Array.from(methods); // 返回一个数组}// 示例用法:class MyClass {    constructor() {        this.data = 'test';    }    methodA() { return 'A'; }    methodB() { return 'B'; }    static staticMethod() { return 'static'; } // 静态方法不在原型链上}Object.prototype.globalMethod = function() { return 'global'; }; // 添加一个可枚举的全局方法Array.prototype.myArrayMethod = function() { return 'myArray'; }; // 添加一个不可枚举的数组方法const instance = new MyClass();const arr = [];console.log('MyClass实例的方法:', getAllPrototypeMethods(instance));// 预期输出可能包括:methodA, methodB, toString, valueOf, hasOwnProperty, isPrototypeOf, etc.console.log('Array实例的方法:', getAllPrototypeMethods(arr));// 预期输出可能包括:push, pop, shift, unshift, myArrayMethod, map, filter, etc.console.log('普通对象的方法:', getAllPrototypeMethods({}));// 预期输出可能包括:toString, valueOf, hasOwnProperty, isPrototypeOf, etc.// 清理测试用的全局方法,避免污染环境delete Object.prototype.globalMethod;delete Array.prototype.myArrayMethod;

这段代码基本上涵盖了大部分情况,它会沿着原型链一层层地“剥开”每个原型对象,找出它们“自己”定义的所有方法。我个人觉得,理解原型链这事儿,就像在挖宝藏,一层一层往下刨,每层都有惊喜,也有‘坑’。

js如何获取原型链上的所有方法

为什么直接使用

for...in

循环无法获取原型链上的所有方法?

说实话,直接用

for...in

来干这事儿,多半是要碰壁的。它确实能遍历对象的属性,但有几个关键的局限性,导致它无法胜任“获取所有原型链方法”的任务:

只遍历可枚举属性: 这是最主要的问题。JavaScript中很多内置方法(比如

Array.prototype

上的

map

forEach

,或者

Object.prototype

上的

toString

hasOwnProperty

)都是不可枚举的。这意味着它们在

for...in

循环中根本不会出现。你试试看

for (let key in []) { console.log(key); }

,你会发现什么都打不出来,尽管数组有很多方法。遍历自身和继承的属性:

for...in

会遍历对象自身以及原型链上所有可枚举的属性。这意味着它会把原型链上继承来的属性也列出来。如果你只是想知道“这个对象有哪些方法”,那它会给你一堆你可能不想要的信息,而且你还得手动判断哪些是它自己的,哪些是继承的,以及更重要的是,哪些是函数。无法区分属性来源:

for...in

本身并不会告诉你这个属性是对象自己的,还是从原型链上继承来的。你得额外用

hasOwnProperty()

来判断,但这又回到了问题1,因为它同样受限于可枚举性。

所以,

for...in

更适合于遍历那些你明确知道是可枚举的、或者你不在乎它是不是继承来的属性,比如一个配置对象的键值对。对于原型链上的方法查找,它就显得力不从心了。

js如何获取原型链上的所有方法

如何区分对象自身的属性和原型链上的方法?

区分对象自身的属性和原型链上的方法,这在JavaScript中是个非常基础但又极其重要的概念。核心思想就是“看它是不是直接长在对象身上的”。

最直接、最常用的方法就是使用

Object.prototype.hasOwnProperty.call(obj, propName)

。这个方法会检查

obj

是否拥有名为

propName

的“自有”属性(own property),不包括继承来的属性。之所以用

call

来调用,是为了防止

obj

本身覆盖了

hasOwnProperty

方法(虽然不常见,但总有那么些刁钻的场景)。

然而,对于我们这个“获取原型链上所有方法”的需求,思路稍微有点不同。我们不是要区分一个实例对象

instance

的自有属性和它原型上的方法。我们是要:

拿到

instance

的直接原型(

MyClass.prototype

)。拿到

MyClass.prototype

的直接原型(

Object.prototype

)。直到原型链的尽头(

null

)。

在拿到每一个“原型对象”的时候,我们就要问:“这个原型对象自己有哪些属性?”这时候,

Object.getOwnPropertyNames(protoObj)

Object.getOwnPropertySymbols(protoObj)

就派上用场了。这两个方法只会返回

protoObj

“自身”的属性名(包括不可枚举的),而不会去管

protoObj

自己又继承了什么。

所以,在遍历原型链时,对每个

current

原型对象使用

Object.getOwnPropertyNames(current)

Object.getOwnPropertySymbols(current)

,就能准确地获取到该层原型对象上“自有”的所有属性名。然后,我们再对这些属性名进行筛选,找出那些值是

function

类型的,这就是该层原型对象所贡献的方法。这种方式,巧妙地利用了

getOwnPropertyNames

的特性,每次都只看当前这一层“自己”的东西,避免了继承的干扰。

获取原型链方法时,需要注意哪些常见陷阱或特殊情况?

在实际操作中,获取原型链上的方法确实会遇到一些小“坑”和需要注意的地方:

Object.prototype

的原型是

null

这是原型链的终点。你的遍历循环必须能正确处理

Object.getPrototypeOf(Object.prototype)

返回

null

的情况,否则会进入无限循环或者报错。我上面提供的

while (current)

循环就是为了处理这个。

Symbol

属性和方法: JavaScript中除了字符串键名属性,还有

Symbol

作为键名的属性。

Object.getOwnPropertyNames()

只会返回字符串键名的属性,而不会返回

Symbol

键名的属性。如果你的方法使用了

Symbol

作为键名(比如

Symbol.iterator

),那就必须额外使用

Object.getOwnPropertySymbols()

来获取它们。我的解决方案里已经考虑到了这一点。

constructor

属性: 几乎所有对象都会有一个

constructor

属性指向它们的构造函数。这个属性通常也会出现在原型链上。在很多场景下,我们获取“方法”时并不希望包含

constructor

,因为它不是一个常规意义上的“行为”方法。我的代码中加入了

if (prop !== 'constructor')

的判断来过滤掉它,你可以根据自己的需求决定是否保留。属性描述符: 属性不仅有值,还有可写(writable)、可枚举(enumerable)、可配置(configurable)等特性。

Object.getOwnPropertyDescriptor()

可以获取这些详细信息。虽然在判断是否为函数时,直接

typeof obj[prop] === 'function'

通常可行,但如果属性是一个

getter

setter

,直接访问

obj[prop]

可能会触发副作用,或者在某些特殊情况下(如

Proxy

)抛出错误。使用

descriptor.value

来判断会更稳妥一些,虽然增加了代码的复杂性。性能考量: 对于非常深的原型链,或者需要频繁地对大量对象执行此操作时,每次都遍历整个原型链可能会有轻微的性能开销。如果你的应用场景允许,并且对象结构相对稳定,可以考虑对结果进行缓存。

__proto__

的滥用: 早期或者一些非标准的环境中,可能会直接使用

obj.__proto__

来访问和修改原型。虽然它在现代浏览器中广泛支持,但它并不是标准的访问原型链的方式,并且在生产代码中不推荐直接使用。始终坚持使用

Object.getPrototypeOf()

Object.setPrototypeOf()

来操作原型链,这更符合规范,也更安全。宿主对象(Host Objects)的特殊性: 在浏览器环境或Node.js环境中,有些内置对象(如DOM元素、

window

对象)的行为可能与普通JavaScript对象有所不同。它们的一些属性可能无法通过标准方法访问或操作,或者在尝试获取其描述符时抛出错误。我的代码中加入了

try...catch

来处理这种情况,避免程序中断。

总的来说,获取原型链上的方法,需要你对JavaScript的原型机制、属性特性以及一些内置API有比较深入的理解。这事儿看起来简单,但要做到滴水不漏,还是得细心。

以上就是js如何获取原型链上的所有方法的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1517347.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月20日 10:42:33
下一篇 2025年12月20日 10:42:41

相关推荐

  • CSS mask属性无法获取图片:为什么我的图片不见了?

    CSS mask属性无法获取图片 在使用CSS mask属性时,可能会遇到无法获取指定照片的情况。这个问题通常表现为: 网络面板中没有请求图片:尽管CSS代码中指定了图片地址,但网络面板中却找不到图片的请求记录。 问题原因: 此问题的可能原因是浏览器的兼容性问题。某些较旧版本的浏览器可能不支持CSS…

    2025年12月24日
    900
  • 为什么设置 `overflow: hidden` 会导致 `inline-block` 元素错位?

    overflow 导致 inline-block 元素错位解析 当多个 inline-block 元素并列排列时,可能会出现错位显示的问题。这通常是由于其中一个元素设置了 overflow 属性引起的。 问题现象 在不设置 overflow 属性时,元素按预期显示在同一水平线上: 不设置 overf…

    2025年12月24日 好文分享
    400
  • 网页使用本地字体:为什么 CSS 代码中明明指定了“荆南麦圆体”,页面却仍然显示“微软雅黑”?

    网页中使用本地字体 本文将解答如何将本地安装字体应用到网页中,避免使用 src 属性直接引入字体文件。 问题: 想要在网页上使用已安装的“荆南麦圆体”字体,但 css 代码中将其置于第一位的“font-family”属性,页面仍显示“微软雅黑”字体。 立即学习“前端免费学习笔记(深入)”; 答案: …

    2025年12月24日
    000
  • 为什么我的特定 DIV 在 Edge 浏览器中无法显示?

    特定 DIV 无法显示:用户代理样式表的困扰 当你在 Edge 浏览器中打开项目中的某个 div 时,却发现它无法正常显示,仔细检查样式后,发现是由用户代理样式表中的 display none 引起的。但你疑问的是,为什么会出现这样的样式表,而且只针对特定的 div? 背后的原因 用户代理样式表是由…

    2025年12月24日
    200
  • inline-block元素错位了,是为什么?

    inline-block元素错位背后的原因 inline-block元素是一种特殊类型的块级元素,它可以与其他元素行内排列。但是,在某些情况下,inline-block元素可能会出现错位显示的问题。 错位的原因 当inline-block元素设置了overflow:hidden属性时,它会影响元素的…

    2025年12月24日
    000
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200
  • 为什么使用 inline-block 元素时会错位?

    inline-block 元素错位成因剖析 在使用 inline-block 元素时,可能会遇到它们错位显示的问题。如代码 demo 所示,当设置了 overflow 属性时,a 标签就会错位下沉,而未设置时却不会。 问题根源: overflow:hidden 属性影响了 inline-block …

    2025年12月24日
    000
  • 为什么我的 CSS 元素放大效果无法正常生效?

    css 设置元素放大效果的疑问解答 原提问者在尝试给元素添加 10em 字体大小和过渡效果后,未能在进入页面时看到放大效果。探究发现,原提问者将 CSS 代码直接写在页面中,导致放大效果无法触发。 解决办法如下: 将 CSS 样式写在一个单独的文件中,并使用 标签引入该样式文件。这个操作与原提问者观…

    2025年12月24日
    000
  • 为什么我的 em 和 transition 设置后元素没有放大?

    元素设置 em 和 transition 后不放大 一个 youtube 视频中展示了设置 em 和 transition 的元素在页面加载后会放大,但同样的代码在提问者电脑上没有达到预期效果。 可能原因: 问题在于 css 代码的位置。在视频中,css 被放置在单独的文件中并通过 link 标签引…

    2025年12月24日
    100
  • 为什么在父元素为inline或inline-block时,子元素设置width: 100%会出现不同的显示效果?

    width:100%在父元素为inline或inline-block下的显示问题 问题提出 当父元素为inline或inline-block时,内部元素设置width:100%会出现不同的显示效果。以代码为例: 测试内容 这是inline-block span 效果1:父元素为inline-bloc…

    2025年12月24日
    400
  • 如何直接访问 Sass 地图变量的值?

    直接访问 sass 地图变量的值 在 sass 中,我们可以使用地图变量来存储一组键值对。而有时候,我们可能需要直接访问其中的某个值。 可以通过 map-get 函数直接从地图中获取特定的值。语法如下: map-get($map, $key) 其中: $map 是我们要获取值的 sass 地图变量。…

    2025年12月24日
    000
  • 我如何编写 CSS 选择器

    CSS 方法有很多,但我都讨厌它们。有些多(顺风等),有些少(BEM、OOCSS 等)。但归根结底,它们都有缺陷。 当然,人们使用这些方法有充分的理由,并且解决的许多问题我也遇到过。因此,在这篇文章中,我想写下我自己的关于如何保持 CSS 井井有条的指南。 这并不是一个任何人都可以开始使用的完整描述…

    2025年12月24日
    000
  • css中的浏览器私有化前缀有哪些

    css中的浏览器私有化前缀有:1、谷歌浏览器和苹果浏览器【-webkit-】;2、火狐浏览器【-moz-】;3、IE浏览器【-ms-】;4、欧朋浏览器【-o-】。 浏览器私有化前缀有如下几个: (学习视频分享:css视频教程) -webkit-:谷歌 苹果 background:-webkit-li…

    2025年12月24日
    300
  • 如何利用css改变浏览器滚动条样式

    注意:该方法只适用于 -webkit- 内核浏览器 滚动条外观由两部分组成: 1、滚动条整体滑轨 2、滚动条滑轨内滑块 在CSS中滚动条由3部分组成 立即学习“前端免费学习笔记(深入)”; name::-webkit-scrollbar //滚动条整体样式name::-webkit-scrollba…

    2025年12月24日
    000
  • css如何解决不同浏览器下文本兼容的问题

    目标: css实现不同浏览器下兼容文本两端对齐。 在 form 表单的前端布局中,我们经常需要将文本框的提示文本两端对齐,例如: 解决过程: 立即学习“前端免费学习笔记(深入)”; 1、首先想到是能不能直接靠 css 解决问题 css .test-justify { text-align: just…

    2025年12月24日 好文分享
    200
  • 关于jQuery浏览器CSS3特写兼容的介绍

    这篇文章主要介绍了jquery浏览器css3特写兼容的方法,实例分析了jquery兼容浏览器的使用技巧,需要的朋友可以参考下 本文实例讲述了jQuery浏览器CSS3特写兼容的方法。分享给大家供大家参考。具体分析如下: CSS3充分吸收多年了web发展的需求,吸收了很多新颖的特性。例如border-…

    好文分享 2025年12月24日
    000
  • 360浏览器兼容模式的页面显示不全怎么处理

    这次给大家带来360浏览器兼容模式的页面显示不全怎么处理,处理360浏览器兼容模式页面显示不全的注意事项有哪些,下面就是实战案例,一起来看一下。  由于众所周知的情况,国内的主流浏览器都是双核浏览器:基于Webkit内核用于常用网站的高速浏览。基于IE的内核用于兼容网银、旧版网站。以360的几款浏览…

    好文分享 2025年12月24日
    000
  • 如何解决css对浏览器兼容性问题总结

    css对浏览器的兼容性有时让人很头疼,或许当你了解当中的技巧跟原理,就会觉得也不是难事,从网上收集了ie7,6与fireofx的兼容性处理方法并 整理了一下.对于web2.0的过度,请尽量用xhtml格式写代码,而且doctype 影响 css 处理,作为w3c的标准,一定要加 doctype声名.…

    好文分享 2025年12月23日
    000
  • 关于CSS3中选择符的实例详解

    英文原文: www.456bereastreet.com/archive/200601/css_3_selectors_explained/中文翻译: www.dudo.org/article.asp?id=197注:本文写于2006年1月,当时IE7、IE8和Firefox3还未发行,文中所有说的…

    好文分享 2025年12月23日
    000
  • 阐述什么是CSS3?

    网页制作Webjx文章简介:CSS3不是新事物,更不是只是围绕border-radius属性实现的圆角。它正耐心的坐在那里,已经准备好了首次登场,呷着咖啡,等着浏览器来铺上红地毯。            CSS3不是新事物,更不是只是围绕border-radius属性实现              …

    好文分享 2025年12月23日
    000

发表回复

登录后才能评论
关注微信