深入理解 JavaScript 对象的 Property 与 Prototype 链
本文详细解析 JavaScript 中 Native Object 与 Host Object 的区别,重点阐述对象属性(Property)的读写机制以及原型(Prototype)链的工作原理。通过具体代码示例,说明赋值与取值操作在对象自身属性与原型链查找过程中的差异,揭示 JavaScript 面向对象编程的核心机制。
JavaScript 对象类型概述
ECMAScript 标准将对象划分为两类:一类是 Native Object,属于语言规范范畴;另一类是 Host Object,由运行环境提供,例如 document 对象。
Dom Node 等
Native Object 具有松散的结构,支持动态添加属性(property)。每个属性都包含一个名称和一个值,该值可以是另一个对象的引用。
或者是一个内置的数据类型(String、Number、Boolean、Null 或 Undefined)。
以下简单示例展示了 JavaScript 对象如何设置属性值以及如何读取属性值。
对象属性的赋值操作
赋值操作
创建对象属性非常简单,直接通过赋值操作即可完成属性的创建。
var objectRef = new Object(); //create a generic javascript object.
可以这样创建一个名为 testNumber 的属性。
objectRef.testNumber = 5;
/* - or:- */
objectRef["testNumber"] = 5;
如果复制的属性名称已经存在,则不会再次创建该属性,赋值操作仅仅是重新设置属性的值。
objectRef.testNumber = 8;
/* - or:- */
objectRef["testNumber"] = 8;
JavaScript 对象的原型(prototype)本身也可以是一个对象,并且可以拥有属性(property)。对 JS 对象 prototype 的赋值操作与普通对象属性的创建方式没有区别。
没什么不同。
对象属性的取值与原型链机制
取值操作
在取值操作中,property 和 prototype 的行为有所不同,先来看最简单的 property 取值操作。
/*为一个对象的属性赋值,如果这个对象没有这个属性,那么在赋值操作后,这个对象就有这个属性了 */
objectRef.testNumber = 8;
/* 读出这个属性的值 */
var val = objectRef.testNumber;
/* 现在val 就得到了刚才赋予objectRef的值8了*/
Prototype 链的工作原理
prototype揭密
所有对象都可以拥有 prototypes,prototypes 本身也是对象,因此它们也可以拥有自己的 prototypes。这样循环下去便形成了一个 prototype 链,当链中对应的 prototype 为 null 时中止(Object 的默认 prototype 是 null)。
这个链当他遇到链中队形的prototype是null时中止。(Object的默认的prototype是null)
var objectRef = new Object(); //create a generic javascript object.
创建一个新的 JS 对象时,该对象的 prototype 为 Null,因此 objectRef 的 prototype 链仅包含一个对象 Object.prototype。
我们在看下面的
/* 构建MyObject1这个类型的构造函数
MyObject1 - type.
*/
function MyObject1(formalParameter){
/* 为者对象创建一个属性名字叫testNumber
*/
this.testNumber = formalParameter;
}
/* 构建MyObject2这个类型的构造函数
MyObject2 - type:-
*/
function MyObject2(formalParameter){
/* 为者对象创建一个属性名字叫testString*/
this.testString = formalParameter;
}
/* 下一步的操作会用MyObject1对象替换掉MyObject2默认的prototype属性*/
MyObject2.prototype = new MyObject1( 8 );
/* 最后我们创建MyObject2类型的一个对象*/
var objectRef = new MyObject2( "String_Value" );
objectRef 这个 MyObject2 类型的对象拥有一个 prototype 链,链中的第一个对象是 MyObject1 对象。MyObject1 对象也有 prototype,
这个 prototype 是 Object 默认的 prototype,Object.prototype 的 prototype 是 null,至此这条 prototype 链结束。
当一个取值操作发生时,objectRef 的整个 prototype 链就开始工作
var val = objectRef.testString;
objectRef 这个对象有一个属性叫做 testString,那么这句会把 testString 的值赋给 val
var val = objectRef.testNumber;
在 objectRef 这个对象里并没有 testNumber 这个属性,但是 val 却得到了值 8,而不是 undefine。这是因为解释器在没有在当前对象找到要找
的属性后,就会去检查这个对象的 prototype。objectRef 的 prototype 是 MyObject1 对象,这个对象有 testNumber 这个属性,所以 val 得到 8 这个值。
var val = objectRef.toString;
现在 val 是个 function 的引用,这个 function 是 Object.prototype 的 property。由于 MyObject1 和 MyObject2 都没有定义 toString 这个 property
所以 Object.prototype 返回。
var val = objectRef.madeUpProperty;
最后 val 是 undefined,因为 MyObject1 和 MyObject2,还有 Object 都没有定义 madeUpProperty 这个 property,所以得到的是 undefine。
读写操作对原型链的影响
读操作会读取在 obj 自己和 prototype 链上发现的第一个同名属性值
写操作会为 obj 对象本身创建一个同名属性(如果这个属性名不存在
这就意味着 objectRef.testNumber = 3 会在 objectRef 对象上创建一个 property,名字是 testNumber。当下一次在要读取 testNumber 时
propertype 链就不会工作,仅仅会得到 objectRef 的 property 3,而 MyObject1 的 testNumber 属性并不会被修改。下面的可以验证
/* 构建MyObject1这个类型的构造函数
MyObject1 - type.
*/
function MyObject1(formalParameter){
/* 为者对象创建一个属性名字叫testNumber
*/
this.testNumber = formalParameter;
}
/* 构建MyObject2这个类型的构造函数
MyObject2 - type:-
*/
function MyObject2(formalParameter){
/* 为者对象创建一个属性名字叫testString*/
this.testString = formalParameter;
}
/* 下一步的操作会用MyObject1对象替换掉MyObject2默认的prototype属性*/
var obj1 = new MyObject1( 8 );
MyObject2.prototype = obj1;
/* 最后我们创建MyObject2类型的一个对象*/
var objectRef = new MyObject2( "String_Value" );
alert(objectRef.testNumber);
objectRef.testNumber = 5;
alert(objectRef.testNumber);
alert(obj1.testNumber);
JavaScript异步发送HTTP请求时怎么优雅地处理错误
2026-11-05 17:10:44
5款主流JS在线运行工具对比:CodePen、JSFiddle与StackBlitz怎么选
2026-11-05 17:04:04
JavaScript入门书籍避坑:这些书不适合初学者
2026-11-05 16:31:15
JS使用Math.round实现保留两位小数的原理与代码
2026-11-05 15:35:55
JavaScript 原生 Date 对象怎么实现日期加减
2026-11-05 14:30:00
