JavaScript 中的对象和原型链是理解其继承机制和动态特性的核心。以下是对这两个概念的详细解析:
JavaScript 中的对象是 键值对(key-value) 的集合,所有对象都是 Object
的实例。创建对象的方式包括:
const obj = { name: "Alice", age: 25 };
const obj = new Object();
obj.name = "Alice";
Object.create()
**(直接指定原型):const proto = { greet: () => "Hello!" };
const obj = Object.create(proto); // obj.__proto__ === proto
每个对象都有一个隐藏属性 [[Prototype]]
(可通过 Object.getPrototypeOf(obj)
获取),指向它的原型对象。当访问对象的属性时,若自身不存在,则会沿着原型链向上查找。
函数的 prototype
属性:
函数拥有一个显式的 prototype
属性(仅函数有),通过 new
调用构造函数时,新对象的 [[Prototype]]
会指向该 prototype
。
function Person(name) { this.name = name; }
Person.prototype.sayHello = function() { console.log("Hello!"); };
const alice = new Person("Alice");
alice.sayHello(); // 通过原型链找到方法
原型链终点:
所有原型链的终点是 Object.prototype
,其原型为 null
。
原型链是由对象的 [[Prototype]]
连接形成的链式结构,用于实现 继承 和 属性共享。
function Animal() {}
Animal.prototype.eat = function() { console.log("Eating..."); };
function Dog() {}
Dog.prototype = Object.create(Animal.prototype); // 继承 Animal
Dog.prototype.bark = function() { console.log("Woof!"); };
const dog = new Dog();
dog.eat(); // 通过原型链调用 Animal 的方法
dog.bark(); // 调用自身原型的方法
dog
→ Dog.prototype
→ Animal.prototype
→ Object.prototype
→ null
**instanceof
**:
检查构造函数的 prototype
是否在对象的原型链上。
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true
**Object.hasOwnProperty()
**:
判断属性是否为对象自身所有(非继承)。
console.log(dog.hasOwnProperty("name")); // false(假设未定义name)
修改原型:
Object.setPrototypeOf(obj, proto)
(谨慎使用,影响性能)。__proto__
(非标准,性能差)。class
语法class
是原型继承的语法糖,更直观地实现继承:
class Animal {
eat() { console.log("Eating..."); }
}
class Dog extends Animal {
bark() { console.log("Woof!"); }
}
const dog = new Dog();
dog.eat(); // 继承自 Animal
prototype
时,需修正 constructor
属性:Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog; // 修复 constructor 指向
prototype
、[[Prototype]]
、constructor
的关系是关键。class
语法简化继承逻辑。掌握这些概念,能够更高效地设计复杂的对象模型,并避免常见的原型陷阱。