返回
JS 揭秘:探索 constructor、prototype、__proto__、[[Prototype]] 与原型链的神秘世界
前端
2024-01-23 00:22:24
constructor
constructor 是一个特殊的属性,指向创建该实例对象的函数。使用 instanceof
运算符可以检查一个实例对象是否由某个构造函数创建。
function Person(name) {
this.name = name;
}
const person = new Person('John');
console.log(person instanceof Person); // true
prototype
prototype 是一个指向构造函数的 [[Prototype]]
属性的指针,即它的父原型对象。每个构造函数都有一个 prototype
属性,它是一个对象,可以包含属性和方法,这些属性和方法可以被该构造函数创建的所有实例对象继承。
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}.`);
};
const person = new Person('John');
person.greet(); // Hello, my name is John.
proto
__proto__
是一个特殊的属性,它指向构造函数的 prototype
属性。可以通过 __proto__
属性来访问和修改原型对象中的属性和方法。
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}.`);
};
const person = new Person('John');
console.log(person.__proto__ === Person.prototype); // true
person.__proto__.greet.call(person); // Hello, my name is John.
[[Prototype]]
[[Prototype]]
是一个内部属性,指向构造函数的 prototype
属性。它是原型链中不可见的环节,不能直接访问或修改。
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}.`);
};
const person = new Person('John');
console.log(Object.getPrototypeOf(person) === Person.prototype); // true
原型链
原型链是一个从实例对象到根原型的对象链。当访问一个实例对象的属性或方法时,JavaScript 会沿着原型链向上查找,直到找到该属性或方法。如果找不到,则会返回 undefined
。
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}.`);
};
const person = new Person('John');
person.greet(); // Hello, my name is John.
person.__proto__.greet(); // Hello, my name is John.
Object.getPrototypeOf(person).greet(); // Hello, my name is John.
Symbol 是不是构造函数
Symbol
不是构造函数,因为它不能用 new
运算符创建实例对象。
const symbol = Symbol('foo');
console.log(typeof symbol); // symbol
constructor 属性是否只读
constructor
属性不是只读的,可以通过 Object.defineProperty()
方法修改它。
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}.`);
};
const person = new Person('John');
Object.defineProperty(person, 'constructor', {
value: Function,
writable: true,
configurable: true
});
console.log(person.constructor); // Function
prototype、proto、[[Prototype]] 的区别
prototype
是一个指向构造函数的[[Prototype]]
属性的指针。__proto__
是一个指向构造函数的prototype
属性的指针。[[Prototype]]
是一个指向构造函数的prototype
属性的指针。
原型链继承
原型链继承是 JavaScript 中实现继承的一种方式。当一个构造函数的 prototype
属性指向另一个构造函数的 prototype
属性时,这两个构造函数之间就建立了原型链继承关系。
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}.`);
};
function Student(name, major) {
Person.call(this, name);
this.major = major;
}
Student.prototype = Object.create(Person.prototype);
const student = new Student('John', 'Computer Science');
student.greet(); // Hello, my name is John.
原型委托
原型委托是 JavaScript 中访问原型对象属性和方法的一种机制。当访问一个实例对象的属性或方法时,JavaScript 会沿着原型链向上查找,直到找到该属性或方法。如果找不到,则会返回 undefined
。
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}.`);
};
const person = new Person('John');
person.greet(); // Hello, my name is John.
person.__proto__.greet(); // Hello, my name is John.
Object.getPrototypeOf(person).greet(); // Hello, my name is John.
总结
constructor
是一个指向创建该实例对象的函数的属性。prototype
是一个指向构造函数的[[Prototype]]
属性的指针。__proto__
是一个指向构造函数的prototype
属性的指针。[[Prototype]]
是一个指向构造函数的prototype
属性的指针。- 原型链是一个从实例对象到根原型的对象链。
Symbol
不是构造函数。constructor
属性不是只读的。prototype
、__proto__
和[[Prototype]]
之间的主要区别在于,prototype
是一个指向构造函数的[[Prototype]]
属性的指针,__proto__
是一个指向构造函数的prototype
属性的指针,[[Prototype]]
是一个指向构造函数的prototype
属性的指针。- 原型链继承是 JavaScript 中实现继承的一种方式。
- 原型委托是 JavaScript 中访问原型对象属性和方法的一种机制。