讲师中心 微信公众号

工具推荐

视频效率加速
Seko
Seko

AI短剧一键生成成片

updream

一键生成高质量推广成片

Laper
Laper

剧本策划到成片协作

剧云
剧云

中文短剧剧本制作平台

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

夏杰同学_3200

夏杰同学_3200

发布时间:2025-08-23 14:40:01

|

404人浏览过

|

来源于php中文网

原创

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

  1. 只遍历可枚举属性: 这是最主要的问题。JavaScript中很多内置方法(比如
    Array.prototype
    上的
    map
    、
    forEach
    ,或者
    Object.prototype
    上的
    toString
    、
    hasOwnProperty
    )都是不可枚举的。这意味着它们在
    for...in
    循环中根本不会出现。你试试看
    for (let key in []) { console.log(key); }
    ,你会发现什么都打不出来,尽管数组有很多方法。
  2. 遍历自身和继承的属性:
    for...in
    会遍历对象自身以及原型链上所有可枚举的属性。这意味着它会把原型链上继承来的属性也列出来。如果你只是想知道“这个对象有哪些方法”,那它会给你一堆你可能不想要的信息,而且你还得手动判断哪些是它自己的,哪些是继承的,以及更重要的是,哪些是函数。
  3. 无法区分属性来源:
    for...in
    本身并不会告诉你这个属性是对象自己的,还是从原型链上继承来的。你得额外用
    hasOwnProperty()
    来判断,但这又回到了问题1,因为它同样受限于可枚举性。

所以,

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

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

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

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

CDP浏览器大师
CDP浏览器大师

CDP浏览器大师:通过Chrome DevTools Protocol驱动已登录浏览器实现自动化任务,解决反爬封号、选择器失效、SPA路由难导航、固定sleep不准四大痛点。核心能力包括UA伪装、WebGL/Canvas指纹混淆、智能等待、动态选择器以及可视化调试。

下载

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

Object.prototype.hasOwnProperty.call(obj, propName)
。这个方法会检查
obj
是否拥有名为
propName
的“自有”属性(own property),不包括继承来的属性。之所以用
call
来调用,是为了防止
obj
本身覆盖了
hasOwnProperty
方法(虽然不常见,但总有那么些刁钻的场景)。

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

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

  1. 拿到
    instance
    的直接原型(
    MyClass.prototype
    )。
  2. 拿到
    MyClass.prototype
    的直接原型(
    Object.prototype
    )。
  3. 直到原型链的尽头(
    null
    )。

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

Object.getOwnPropertyNames(protoObj)
和
Object.getOwnPropertySymbols(protoObj)
就派上用场了。这两个方法只会返回
protoObj
“自身”的属性名(包括不可枚举的),而不会去管
protoObj
自己又继承了什么。

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

current
原型对象使用
Object.getOwnPropertyNames(current)
和
Object.getOwnPropertySymbols(current)
,就能准确地获取到该层原型对象上“自有”的所有属性名。然后,我们再对这些属性名进行筛选,找出那些值是
function
类型的,这就是该层原型对象所贡献的方法。这种方式,巧妙地利用了
getOwnPropertyNames
的特性,每次都只看当前这一层“自己”的东西,避免了继承的干扰。

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

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

  1. Object.prototype
    的原型是
    null
    :
    这是原型链的终点。你的遍历循环必须能正确处理
    Object.getPrototypeOf(Object.prototype)
    返回
    null
    的情况,否则会进入无限循环或者报错。我上面提供的
    while (current)
    循环就是为了处理这个。
  2. Symbol
    属性和方法:
    JavaScript中除了字符串键名属性,还有
    Symbol
    作为键名的属性。
    Object.getOwnPropertyNames()
    只会返回字符串键名的属性,而不会返回
    Symbol
    键名的属性。如果你的方法使用了
    Symbol
    作为键名(比如
    Symbol.iterator
    ),那就必须额外使用
    Object.getOwnPropertySymbols()
    来获取它们。我的解决方案里已经考虑到了这一点。
  3. constructor
    属性:
    几乎所有对象都会有一个
    constructor
    属性指向它们的构造函数。这个属性通常也会出现在原型链上。在很多场景下,我们获取“方法”时并不希望包含
    constructor
    ,因为它不是一个常规意义上的“行为”方法。我的代码中加入了
    if (prop !== 'constructor')
    的判断来过滤掉它,你可以根据自己的需求决定是否保留。
  4. 属性描述符: 属性不仅有值,还有可写(writable)、可枚举(enumerable)、可配置(configurable)等特性。
    Object.getOwnPropertyDescriptor()
    可以获取这些详细信息。虽然在判断是否为函数时,直接
    typeof obj[prop] === 'function'
    通常可行,但如果属性是一个
    getter
    或
    setter
    ,直接访问
    obj[prop]
    可能会触发副作用,或者在某些特殊情况下(如
    Proxy
    )抛出错误。使用
    descriptor.value
    来判断会更稳妥一些,虽然增加了代码的复杂性。
  5. 性能考量: 对于非常深的原型链,或者需要频繁地对大量对象执行此操作时,每次都遍历整个原型链可能会有轻微的性能开销。如果你的应用场景允许,并且对象结构相对稳定,可以考虑对结果进行缓存。
  6. __proto__
    的滥用:
    早期或者一些非标准的环境中,可能会直接使用
    obj.__proto__
    来访问和修改原型。虽然它在现代浏览器中广泛支持,但它并不是标准的访问原型链的方式,并且在生产代码中不推荐直接使用。始终坚持使用
    Object.getPrototypeOf()
    和
    Object.setPrototypeOf()
    来操作原型链,这更符合规范,也更安全。
  7. 宿主对象(Host Objects)的特殊性: 在浏览器环境或Node.js环境中,有些内置对象(如DOM元素、
    window
    对象)的行为可能与普通JavaScript对象有所不同。它们的一些属性可能无法通过标准方法访问或操作,或者在尝试获取其描述符时抛出错误。我的代码中加入了
    try...catch
    来处理这种情况,避免程序中断。

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

热门AI工具

更多
VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

569

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1698

2024.03.01

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

354

2023.09.25

php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

838

2025.12.04

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1918

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

3144

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6364

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

6489

2023.11.24

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

0

2026.11.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Vue.js 开发基础教程
Vue.js 开发基础教程

共33课时 | 8.5万人学习

深入剖析redis教程
深入剖析redis教程

共55课时 | 9.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn