JavaScript prototype属性详解:原型链、继承与内置类扩展

作者:青柠时间:2026-10-25 09:30:53浏览:467

本文详细解析JavaScript中prototype属性的核心机制。涵盖原型链查找规则、类与实例的属性差异、内置对象(如Array)的扩展方法,以及hasOwnProperty在遍历中的应用。通过代码示例说明原型赋值、继承链构建及常见陷阱,帮助开发者掌握JS面向对象编程的关键技术。

JavaScript prototype属性概述

该属性较为特殊,JavaScript中的继承机制通常依赖此属性实现。


在JavaScript中,所有实体如字符串、数组、变量及函数均被视为对象,这支持了类似['a','b','c'].push('d')的操作。类本身也是对象,可定义其属性和方法:


代码示例如下:

 
function Test(){};
Test.str = 'str';
Test.fun = function(){return 'fun';};
var r1 = Test.str; // str
var r2 = Test.fun(); // fun
var inst = new Test();
var r3 = inst.str; // undefined
var r4 = inst.fun(); // undefined

prototype属性的存在性与类型检查

prototype是类的一个属性。默认情况下,所有JavaScript类都具备prototype属性,但类的实例不具备。


代码示例如下:

 
function Test(){};
var p1 = typeof(String.prototype); // object
var p2 = typeof(Test.prototype); // object
var p3 = typeof(new Test().prototype); // undefined
var p4 = typeof(Object.prototype); // object
var p5 = typeof(new Object().prototype); // undefined

原型链查找机制:取值与赋值差异

取值与赋值机制


当JavaScript中访问对象不存在的属性或方法时,引擎会查找该对象对应类的prototype属性。若prototype中也没有,则继续向上查找其父类的prototype,直至找到目标或prototype为null。


代码示例如下:

 
function Test(){};
Test.test = 'str';
function pt1()
{ this.test1 = 'pt1'; };
function pt2()
{ this.test2 = 'pt2'; };
pt2.prototype.test3 = 'test3';
pt2.prototype.test1 = 'test4';
pt1.prototype = new pt2();
Test.prototype = new pt1();
var inst = new Test();
var p1 = inst.test; // undefined
var p2 = inst.test1; // pt1 而不是 test4
var p3 = inst.test2; // pt2
var p4 = inst.test3; // test3

相比之下,赋值操作更为简单。它不会向上查找prototype中的属性,而是直接在当前实例上赋值,若不存在则创建新属性。


内置类的扩展与注意事项

内置类的增强


JavaScript中不能直接替换内置类的prototype,但可以通过修改其属性来改变内置类的行为。


代码示例如下:

 
Array.prototype = {push:function(){alert('test1');}}; // 无效
Array.prototype.push = function(){alert('test2');}; // 有效
var test = new Array('a','b','c');
test.push('d'); // test2

支持一次插入多个元素的Array.push函数:


代码示例如下:

 
Array.prototype.pushs = function()
{ 
var pos = this.length;
for(var i=0; i<arguments.length; i++)
{ 
this[++pos] = arguments[i];
} 
return this.length;
} 
var test = new Array('a','b','c');
test.pushs('d','e');

值得注意的是,为内置类prototype添加的函数,在使用for循环遍历属性时也会被枚举出来:


代码示例如下:

 
var str;
for(var i in test)
{ 
str += (' ' + i); // '0 1 2 3 4 5 pushs' 包含自定义pushs函数。
} 

但可以通过hasOwnProperty()方法进行过滤:


代码示例如下:

 
var str;
for(var i in test)
{ 
if(test.hasOwnProperty(i)) // 过滤掉pushs函数。
{ str += (' ' + i); }
} 
]

修改prototype值的潜在风险

注意事项


前文提到,prototype是类的属性。修改prototype中的属性值可能导致不可预知的后果。


代码示例如下:

 
function Test(){}
Test.prototype.num = 3;
var inst1 = new Test();
var inst2 = new Test();
Test.prototype.num = 4; // 所有指向Test.prototype.num的值。
var p1 = inst1.num; // 4
var p2 = inst2.num; // 4
inst1.num = 5; // 赋值操作,为inst对象创建独立的num属性。
Test.prototype.num = 6; // 所有指向Test.prototype.num的值。
var p3 = inst1.num; // 5 返回刚创建的inst1.num的值,而非Test.prototype.num。
var p4 = inst2.num; // 6
delete Test.prototype.num;
var p5 = inst1.num; // 5 inst1.num依然存在。
var p6 = inst2.num; // undefined Test.prototype.num 已被删除。
作者最新文章