js中的原型对象
我们创建的每个函数都有一个prototype
(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。
所以说,无论我们什么时候创建了一个新函数,就会一组特定的规则为该函数创建一个prototype
属性,这个属性指向函数的原型对象。在默认情况下,所有的原型对象都会自动获得一个constructor
(构造函数)属性,如下所示:
function Person() {
}
Person.prototype.name = 'Zhangsan';
Person.prototype.sayName = function () {
console.log(this.name);
}
这里的Person.prototype.constructor
默认指向Person
。
js中提供一种方法,可以通过isPrototypeOf()
这个方法来确定对象是否有的相同的原型属性。
var person = new Person();
Person.prototype.isPrototypeOf(person); //true
虽然可以通过对象实例访问保存在原型中的值,但是却不能通过该对象实例重写原型中的值。
var person1 = new Person();
var person2 = new Person();
person1.name = 'Lisi';
console.log(person1.name); //Lisi
console.log(person2.name); //Zhangsan
虽然person1
输出的是Lisi
,但其实修改的是其对象实例中的属性,即为其实例上添加了一个属性,然后就屏蔽了原型对象中保存的属性,所以这里person1
输出为Lisi
,同时person2
实例输出为Zhangsan
。当然,可以使用delete
删除实例上的属性,之后就可以访问其原型上的属性了。
delete person1.name
当使用字面量的方式来书写原型对象时,会导致其constructor
属性不在指向原函数,但是可以手动指明的方式来声明。
function Person() {
}
Person.prototype = {
constructor: Person,
name: 'Zhangsan',
sayName: function () {
console.log(this.name)
}
}
var person1 = new Person();
console.log(person1.sayName())
但是,原生的constructor
是不可枚举的(什么是可枚举?就是说可以通过for-in
循环或者Object.keys()
中拿到对象的属性),那么可以使用Object.defineProperty()
来声明属性。
Object.defineProperty(Person.prototype, 'constructor', {
enumerable: false,
value: Person
})
这样就没什么问题了。
还有一点需要注意,新建实例后,再重写原型,将会切断现有实例与原型之间的联系,故新实例无法调用原型上的方法,如下的实例将会出现错误。
function Person() {
}
var person = new Person();
Person.prototype = {
name: 'Zhangsan',
sayName: function () {
console.log(this.name)
}
}
Object.defineProperty(Person.prototype, 'constructor', {
enumerable: false,
value: Person
})
console.log(person.sayName()) //error
如果您觉得本文对您有用,欢迎捐赠或留言~
- 本博客所有文章除特别声明外,均可转载和分享,转载请注明出处!
- 本文地址:https://www.leevii.com/?p=927