JS 简述原型链特征,设置和获取的方式
时间: 2025-08-06 10:05:25 浏览: 6
<think>我们正在讨论JavaScript的原型链。根据引用,我们知道:
1. 引用类型皆为对象(引用[1])。
2. 原型链是JavaScript中实现继承和属性查找的核心机制(引用[3])。
3. 每个函数都有一个prototype属性,指向函数的原型对象(引用[4])。
4. 对象可以通过`__proto__`(非标准,但许多环境支持)或`Object.getPrototypeOf()`来获取原型(引用[2][3])。
用户的问题:原型链的特征是什么,以及如何设置和获取原型链。
一、原型链的特征:
1. 继承性:原型链允许对象继承另一个对象的属性和方法。当访问一个对象的属性时,如果该对象没有,则会沿着原型链向上查找,直到找到或到达原型链顶端(null)。
2. 动态性:原型对象上的属性和方法可以被动态修改,这些修改会影响到所有继承自该原型的对象。
3. 原型链的顶端是`Object.prototype`,而`Object.prototype`的原型是`null`(引用[3])。
4. 每个对象(除了null)都有一个原型(`__proto__`属性),而每个函数都有一个`prototype`属性(指向原型对象),该原型对象有一个`constructor`属性指回函数(引用[3][4])。
二、如何获取原型链?
1. 使用`Object.getPrototypeOf(obj)`:这是标准方法,返回指定对象的原型(即内部`[[Prototype]]`属性的值)。
2. 使用非标准的`obj.__proto__`:虽然许多环境支持,但不建议在生产代码中使用,因为它不是标准的一部分(引用[3]提到过)。
三、如何设置原型链?
1. 使用`Object.create(proto)`:创建一个新对象,并将指定的对象`proto`作为新对象的原型(引用[2])。
2. 使用构造函数:通过`new`操作符创建对象时,新对象的原型指向构造函数的`prototype`属性(引用[3][4])。
3. 使用`Object.setPrototypeOf(obj, proto)`:设置一个指定对象的原型(即内部`[[Prototype]]`属性)到另一个对象或null。但注意,修改对象的原型可能会影响性能,应谨慎使用。
四、示例说明:
1. 创建对象并设置原型链:
```javascript
// 使用Object.create
let parent = { name: "Parent" };
let child = Object.create(parent); // child的原型是parent
console.log(child.name); // "Parent" (通过原型链继承)
// 使用构造函数
function Parent() { this.name = "Parent"; }
function Child() {}
Child.prototype = new Parent(); // 设置Child的原型为Parent的实例
let c = new Child();
console.log(c.name); // "Parent"
// 使用Object.setPrototypeOf
let obj = {};
Object.setPrototypeOf(obj, parent);
console.log(obj.name); // "Parent"
```
2. 获取原型链:
```javascript
let proto = Object.getPrototypeOf(child); // 返回parent对象
console.log(proto === parent); // true
// 或者使用非标准的__proto__
console.log(child.__proto__ === parent); // true (但不推荐)
```
五、注意事项:
1. 原型链查找是递归的,直到找到属性或遇到null为止。
2. 避免循环原型链,例如:设置A的原型为B,而B的原型又指向A,这会导致无限循环,应避免。
六、总结:
原型链的特征包括继承性、动态性和链式结构。设置原型链可以使用`Object.create`、构造函数和`Object.setPrototypeOf`。获取原型链使用`Object.getPrototypeOf`(推荐)或非标准的`__proto__`。
§§相关问题§§
1. 原型链污染是什么?如何避免?
2. 在JavaScript中,如何实现继承?
3. `Object.create(null)`创建的对象有什么特点?
4. 如何检查一个属性是对象自身的还是继承的?</think>### JavaScript原型链的特征与操作
#### 一、原型链的核心特征
1. **链式继承结构**
所有对象(除`null`外)通过`[[Prototype]]`(通过`__proto__`访问)形成链式结构,实现属性和方法的继承[^3]。
**示例**:
```javascript
const arr = [1, 2];
arr.__proto__ === Array.prototype; // true
arr.__proto__.__proto__ === Object.prototype; // true
```
2. **动态属性继承**
原型对象的属性修改会实时影响所有基于它的实例[^3]:
```javascript
function Person() {}
Person.prototype.name = "Alice";
const p1 = new Person();
Person.prototype.name = "Bob";
console.log(p1.name); // "Bob"(动态继承)
```
3. **原型链终点是`null`**
原型链顶端为`Object.prototype`,其`__proto__`指向`null`[^3]:
$$ \text{对象} \rightarrow \text{Object.prototype} \rightarrow \text{null} $$
4. **构造函数与原型互指**
函数的`prototype`属性指向原型对象,原型对象的`constructor`指回函数[^4]:
```javascript
function Foo() {}
Foo.prototype.constructor === Foo; // true
```
#### 二、获取原型链的方法
1. **`Object.getPrototypeOf(obj)`(推荐)**
标准方法,返回对象的原型[^3]:
```javascript
const obj = {};
Object.getPrototypeOf(obj) === Object.prototype; // true
```
2. **`obj.__proto__`(非标准但通用)**
非标准属性,但被主流环境支持[^3]:
```javascript
const arr = [];
arr.__proto__ === Array.prototype; // true
```
3. **`obj.constructor.prototype`**
通过构造函数获取原型(需确保`constructor`未被覆盖):
```javascript
function Bar() {}
const b = new Bar();
b.constructor.prototype === Bar.prototype; // true
```
#### 三、设置原型链的方法
1. **`Object.create(proto)`**
创建新对象并指定原型[^2]:
```javascript
const parent = { x: 10 };
const child = Object.create(parent); // child的原型设为parent
console.log(child.x); // 10(继承属性)
```
2. **`Object.setPrototypeOf(obj, proto)`**
动态修改现有对象的原型(可能影响性能)[^2]:
```javascript
const obj1 = { a: 1 };
const obj2 = { b: 2 };
Object.setPrototypeOf(obj1, obj2);
console.log(obj1.b); // 2(通过原型链访问)
```
3. **构造函数模式**
通过`new`操作符自动绑定原型[^3]:
```javascript
function Animal(name) {
this.name = name;
}
Animal.prototype.eat = function() { console.log("Eating") };
const cat = new Animal("Cat");
cat.eat(); // "Eating"(从原型继承方法)
```
#### 四、关键注意事项
1. **性能影响**
避免在频繁调用的代码中使用`Object.setPrototypeOf()`,可能触发引擎优化失效[^2]。
2. **原型污染防护**
禁止直接修改`Object.prototype`,防止全局污染[^2]:
```javascript
// 危险操作示例
Object.prototype.admin = true; // 所有对象都会继承admin属性
```
3. **检查自有属性**
使用`obj.hasOwnProperty(key)`区分自有属性和继承属性[^3]:
```javascript
const obj = { a: 1 };
console.log(obj.hasOwnProperty("a")); // true
console.log(obj.hasOwnProperty("toString")); // false(继承自Object.prototype)
```
---
### 总结
- **特征**:链式继承、动态更新、终点为`null`、构造函数与原型互指。
- **获取原型**:优先用`Object.getPrototypeOf()`,其次`__proto__`。
- **设置原型**:创建时用`Object.create()`,修改用`Object.setPrototypeOf()`或构造函数。
阅读全文
相关推荐




















