JS获取对象原型方法详解
时间:2025-08-07 23:36:33 166浏览 收藏
今日不肯埋头,明日何以抬头!每日一句努力自己的话哈哈~哈喽,今天我将给大家带来一篇《JS如何获取对象原型方法》,主要内容是讲解等等,感兴趣的朋友可以收藏或者有更好的建议在评论提出,我都会认真看的!大家一起进步,一起学习!
获取对象原型上的方法最直接的方式是使用 Object.getPrototypeOf() 取得原型对象,再通过 Object.getOwnPropertyNames() 配合 filter 筛选出函数类型的自有属性;2. 区分原型方法与实例方法的关键在于 hasOwnProperty() 检查,实例方法返回 true,原型方法则需沿原型链查找;3. 使用 for...in 时必须结合 hasOwnProperty() 防止遍历到继承属性,且无法获取不可枚举方法,而 Object.getOwnPropertyNames() 可覆盖所有自有属性;4. 避免修改内置对象原型,防止全局污染;5. 原型方法被所有实例共享,节省内存,而实例方法每个实例独有。
JavaScript中要获取一个对象原型上的方法,最直接的方式是先拿到这个对象的原型,然后遍历原型上的属性。你可以通过 Object.getPrototypeOf()
方法或者非标准的 __proto__
属性来获取原型对象,接着再用 Object.getOwnPropertyNames()
或 for...in
循环(配合 hasOwnProperty
检查)来列出这些方法。

解决方案
要获取原型上的方法,核心步骤是:首先获取到目标对象的原型对象,然后在这个原型对象上查找它“自己”定义的方法,而不是继承来的方法。
举个例子,我们有一个构造函数 Person
:

function Person(name) { this.name = name; } Person.prototype.sayHello = function() { console.log("Hello, my name is " + this.name); }; Person.prototype.walk = function() { console.log(this.name + " is walking."); }; // 假设我们还给Object.prototype添加了一个方法(不推荐,但用于演示) // Object.prototype.globalMethod = function() { console.log("Global!"); }; const person1 = new Person("Alice"); // 1. 获取原型对象 const personPrototype = Object.getPrototypeOf(person1); // 或者使用 person1.__proto__; 但推荐使用 Object.getPrototypeOf(),因为它更标准。 console.log("--- 获取原型上的自有方法 ---"); // 2. 遍历原型对象上的自有属性(方法也是属性) // Object.getOwnPropertyNames() 会返回所有自有属性的名称,包括不可枚举的 const prototypeMethods = Object.getOwnPropertyNames(personPrototype).filter(name => { // 确保是函数类型,并且是原型对象自身的属性,而不是继承自更上层原型链的 return typeof personPrototype[name] === 'function' && personPrototype.hasOwnProperty(name); }); console.log("原型上的方法名称:", prototypeMethods); // 应该输出 ['sayHello', 'walk'] // 如果你想获取方法本身,可以这样: prototypeMethods.forEach(methodName => { console.log(`方法名: ${methodName}, 方法体:`, personPrototype[methodName]); }); // 另一种方法,使用 for...in 循环,但需要额外检查 hasOwnProperty console.log("\n--- 使用 for...in 配合 hasOwnProperty ---"); for (let key in personPrototype) { // 确保是原型对象自身的属性,而不是继承自 Object.prototype 等 if (personPrototype.hasOwnProperty(key) && typeof personPrototype[key] === 'function') { console.log(`通过 for...in 找到的方法: ${key}`); } }
这里 Object.getOwnPropertyNames()
配合 filter
是一种非常干净且推荐的方式,因为它直接获取了原型对象自身的所有属性名,然后我们再筛选出函数类型的。for...in
循环会遍历原型链上所有可枚举的属性,所以必须配合 hasOwnProperty
来确保我们只拿原型对象自身的属性。
为什么我们需要获取原型上的方法?
有时候,我们确实需要探究一个对象背后,它那些“共享”的能力到底是什么。这不仅仅是为了满足好奇心,它在很多场景下都挺有用的。比如,你在调试一个复杂的库或者框架时,想知道一个特定类型的实例到底有哪些内置的行为,或者它从父类/原型那里继承了哪些方法。直接看实例本身可能只会看到它自己的属性,而那些共享的方法往往藏在原型链上。

再比如说,你想对某个特定类型的所有实例,统一地进行一些“增强”或者“监控”。你不可能去遍历所有实例然后给它们挨个打补丁,更优雅的方式是直接修改它的原型。但在修改之前,你可能需要知道原型上已经有哪些方法了,避免覆盖或者冲突。这就像你拿到一份蓝图,想在上面加点东西,总得先看看蓝图上原本画了些啥吧。
还有一些高级的元编程(meta-programming)场景,比如你想实现一个通用的日志记录器,自动记录某个类所有方法的调用。这时候,你就需要动态地获取这个类原型上的所有方法,然后用代理(Proxy)或者AOP(面向切面编程)的思路去包装它们。这听起来有点复杂,但核心就是“获取原型方法”这个基础操作。
获取原型方法时常见的陷阱和注意事项有哪些?
这里面确实有些小坑,一不留神就可能掉进去。
首先,__proto__
和 Object.getPrototypeOf()
的选择。虽然 __proto__
用起来很方便,但它曾经是一个非标准的属性,现在虽然在大多数浏览器和Node.js环境中都支持了,但从规范性和兼容性角度来说,Object.getPrototypeOf()
才是官方推荐和更稳妥的选择。尤其是当你在编写需要长期维护或者跨环境运行的代码时,坚持使用标准API总是没错的。
其次,hasOwnProperty
的重要性。当我们遍历原型对象时,比如使用 for...in
循环,它会遍历原型链上所有可枚举的属性,不仅仅是当前原型对象自己的。这意味着,如果你不加 hasOwnProperty
检查,你可能会意外地获取到 Object.prototype
上的方法(比如 toString
, valueOf
等)。这些通常不是我们想获取的“原型方法”,因为它们是所有对象都共有的。所以,prototypeObject.hasOwnProperty(key)
这一步是至关重要的,它确保你只拿到当前原型对象“自己”定义的属性。
再者,不可枚举属性的问题。for...in
循环只会遍历可枚举的属性。如果原型上有一些方法被定义为不可枚举(比如使用 Object.defineProperty
并且 enumerable: false
),那么 for...in
就无法发现它们。而 Object.getOwnPropertyNames()
就能获取到所有自有属性的名称,包括可枚举和不可枚举的。所以,如果你需要获取所有原型上的方法,包括那些“隐藏”的,Object.getOwnPropertyNames()
是更好的选择。
最后,一个大大的警告:不要轻易修改内置对象的原型。比如 Array.prototype
或者 String.prototype
。虽然技术上你可以这样做,但这样做会污染全局环境,可能导致与其他库或框架的冲突,或者在未来的JavaScript版本更新时出现不可预测的问题。这就像你在一个公共的交通枢纽里随意更改路标,虽然你觉得方便了自己,但可能会让其他人迷失方向。所以,获取原型方法通常是为了理解、分析或者在受控环境下进行操作,而不是为了肆意修改。
如何区分原型方法和实例方法?
区分原型方法和实例方法,其实就是看这个方法是直接定义在对象实例上,还是定义在它的原型链上。这在JavaScript里是个挺核心的概念,理解它能帮助你更好地掌握继承和内存管理。
一个实例方法,顾名思义,就是直接属于这个对象实例的。每次你创建一个新实例,如果这个方法是实例方法,那么每个实例都会有自己独立的一份这个方法的拷贝。比如:
function Car(make, model) { this.make = make; this.model = model; // 这是一个实例方法 this.drive = function() { console.log(`Driving the ${this.make} ${this.model}.`); }; } const myCar = new Car("Honda", "Civic"); const yourCar = new Car("Toyota", "Corolla"); myCar.drive(); // 输出: Driving the Honda Civic. yourCar.drive(); // 输出: Driving the Toyota Corolla. // 检查:实例方法直接在实例上 console.log(myCar.hasOwnProperty('drive')); // true
而原型方法呢,它是定义在构造函数的 prototype
对象上的。所有由这个构造函数创建的实例,都会共享同一个原型方法。它们自己本身并没有这个方法的副本,而是通过原型链去“查找”并调用它。这大大节省了内存,因为方法只需要存储一份。
function Bike(brand) { this.brand = brand; } // 这是一个原型方法 Bike.prototype.ride = function() { console.log(`Riding the ${this.brand} bike.`); }; const myBike = new Bike("Giant"); const yourBike = new Bike("Trek"); myBike.ride(); // 输出: Riding the Giant bike. yourBike.ride(); // 输出: Riding the Trek bike. // 检查:原型方法不在实例上,而是在其原型上 console.log(myBike.hasOwnProperty('ride')); // false console.log(Object.getPrototypeOf(myBike).hasOwnProperty('ride')); // true
所以,最直接的区分方式就是使用 hasOwnProperty()
方法。如果你想检查一个对象 obj
是否有一个名为 methodName
的实例方法,你就调用 obj.hasOwnProperty(methodName)
。如果返回 true
,那它就是实例方法。如果返回 false
,但 obj.methodName
依然能被调用(因为它在原型链上),那么它就是原型方法。
可以这样来判断:
function checkMethodType(obj, methodName) { if (obj.hasOwnProperty(methodName) && typeof obj[methodName] === 'function') { return "实例方法"; } let proto = Object.getPrototypeOf(obj); while (proto) { if (proto.hasOwnProperty(methodName) && typeof proto[methodName] === 'function') { return "原型方法"; } proto = Object.getPrototypeOf(proto); } return "不是方法或不存在"; } console.log(checkMethodType(myCar, 'drive')); // 实例方法 console.log(checkMethodType(myBike, 'ride')); // 原型方法 console.log(checkMethodType({}, 'toString')); // 原型方法 (来自 Object.prototype) console.log(checkMethodType(myCar, 'brake')); // 不是方法或不存在
这个 checkMethodType
函数的逻辑就是:先看是不是自己的属性,如果不是,就沿着原型链往上找,直到找到或者原型链尽头。
今天关于《JS获取对象原型方法详解》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
500 收藏
-
301 收藏
-
349 收藏
-
301 收藏
-
171 收藏
-
233 收藏
-
465 收藏
-
343 收藏
-
271 收藏
-
405 收藏
-
417 收藏
-
466 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习