JavaScript prototype属性详解:原型链、继承与内置类扩展
本文详细解析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 已被删除。ES6模块化中js文件怎么用import和export交互
2026-11-05 17:00:48
JS读取本地文件时报错或无响应的常见原因
2026-11-05 16:32:31
let、const与var的区别:JavaScript变量声明最佳实践
2026-11-05 14:16:38
JS中直接定义静态二维数组的字面量写法
2026-11-05 14:16:08
JS 怎么查找字符串中所有匹配项的位置
2026-11-05 14:15:53
