属性遮蔽:
如果在一个对象中定义了一个属性,而在该对象的原型中定义了一个同名的属性:
const myDate = new Date(1995, 11, 17);
console.log(myDate.getYear());
myDate.getYear = function () {
console.log("别的东西!");
};
展示结果:
当我们调用 getYear()
时,浏览器首先在 myDate
中寻找具有该名称的属性,如果 myDate
没有定义该属性,才检查原型。因此,当我们给 myDate
添加 getYear()
时,就会调用 myDate
中的版本,这叫做属性的“遮蔽”。
设置原型:
在 JavaScript 中,有多种设置对象原型的方法,比如:Object.create()
和构造函数。
1.Object.create():
Object.create()
方法创建一个新的对象,并允许指定一个将被用作新对象原型的对象。
const personPrototype = {
greet() {
console.log("hello!");
},
};
const carl = Object.create(personPrototype);
carl.greet();
结果展示:
创建了一个 personPrototype
对象,它有一个 greet()
方法。使用 Object.create()
来创建一个以 personPrototype
为原型的新对象。现在我们可以在新对象上调用 greet()
,而原型提供了它的实现。
使用构造函数:
1. 在 JavaScript 中,所有的函数都有一个名为 prototype
的属性。当你调用一个函数作为构造函数时,这个属性被设置为新构造对象的原型(在名为 __proto__
的属性中)。
2. 如果设置一个构造函数的 prototype
,可以确保所有用该构造函数创建的对象都被赋予该原型:
const personPrototype = {
greet() {
console.log(`你好,我的名字是 ${this.name}!`);
},
};
function Person(name) {
this.name = name;
}
Object.assign(Person.prototype, personPrototype);
// 或
// Person.prototype.greet = personPrototype.greet;
- 创建了一个
personPrototype
对象,它具有greet()
方法 - 创建了一个
Person()
构造函数,它初始化了要创建人物对象的名字
使用 Object.assign将 personPrototype
中定义的方法绑定到 Person
函数的 prototype
属性上。
在这段代码之后,使用 Person()
创建的对象将获得 Person.prototype
作为其原型,其中自动包含 greet
方法。
const reuben = new Person("Reuben");
reuben.greet(); // 你好,我的名字是 Reuben!
这也解释了为什么我们之前说 myDate
的原型被称为 Date.prototype
:它是 Date
构造函数的 prototype
属性。
完整代码:
const personPrototype = {
greet() {
console.log(`你好,我的名字是 ${this.name}!`);
},
};
function Person(name) {
this.name = name;
}
Object.assign(Person.prototype, personPrototype);
// 或
// Person.prototype.greet = personPrototype.greet;
const reuben = new Person("Reuben");
reuben.greet();
结果展示:
自有属性:
const personPrototype = {
greet() {
console.log(`你好,我的名字是 ${this.name}!`);
},
};
function Person(name) {
this.name = name;
}
Object.assign(Person.prototype, personPrototype);
// 或
// Person.prototype.greet = personPrototype.greet;
const reuben = new Person("Reuben");
reuben.greet();
1. Person
构造函数创建的对象有两个属性:
greet()
方法,在原型中设置name
属性,在构造函数中设置,在Person
对象中可以直接看到
2. 方法是在原型上定义的,数据属性是在构造函数中定义的。这是因为方法通常对我们创建的每个对象都是一样的,而我们通常希望每个对象的数据属性都有自己的值(就像每个人都有不同的名字)。
3. 直接在对象中定义的属性,如这里的name
,被称为自有属性。
①可以使用静态方法 Object.hasOwn()检查一个属性是否是自有属性:
const irma = new Person("Irma");
console.log(Object.hasOwn(irma, "name")); // true
console.log(Object.hasOwn(irma, "greet")); // false
②可以使用非静态方法 Object.hasOwnProperty(),推荐使用 Object.hasOwn()
方法。