笔者近期学习到原型这一块内容,发现原型里面的知识点非常的多,故进行一点小小总结,希望能初步理解原型。
原型
原型的定义
定义:函数 function 对象的一个属性,定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承原型的属性和方法。原型也是对象(里面有一个constructor属性返回父代)。
我们先来看一个很普通的函数
function Person() {
}
console.log(Person)
复制代码
在谷歌v8引擎中是这样解析的
很明显,Person()
里面为空,那么我们再运行如下代码
function Person() {
}
console.log(Person.prototype)
复制代码
结果
我们可以看到输出了一个名为 constructor
的对象,这里能够说明,prototype
是函数自带的一个属性且不为空,指向 constructor
,继续点开
constructor
里面放的是父代 Person()
,里面有 prototype
属性, prototype
里还有一个 constructor
对象。先别晕,抛开其它的属性以及嵌套。根据结果我们发现,几乎所有对象都有一个特殊的内置属性 Prototype
且值不为空(有特殊的 prototype
为空,后续学习过程再去了解),它指向另一个对象,另一个对象会指向其父代。
再回看原型的定义: 函数 function 对象的一个属性,定义了构造函数制造出的对象的公共祖先。这个属性指的就是 prototype
。
总结:
- Person.prototype — 原型
- 函数被定义出来天生就具备 prototype 属性
原型的运用
给原型加属性和方法会发生什么
试验1:
function Person() {}
Person.prototype.name = '老鱼'
Person.prototype.say = function () {
console.log('吃虾米');
}
var person = new Person()
console.log(person.name);//老鱼
person.say() // 吃虾米
复制代码
这里我们可以知道:通过该构造函数产生的对象,可以继承原型的属性和方法。
试验2:
function Person() {
this.name = '小王'
}
Person.prototype.name = '老鱼'
Person.prototype.say = function () {
console.log('吃虾米');
}
var person = new Person()
console.log(person.name); // 小王
person.say() // 吃虾米
复制代码
从这里可以看出,如果构造函数中有对应的属性,则输出构造函数中的属性。但是这里相对的又出现了一个问题:原型的属性被改变了吗?
试验2扩展:
function Person() {
this.name = '小王'
}
Person.prototype.name = '老鱼'
Person.prototype.say = function () {
console.log('吃虾米');
}
var person = new Person()
console.log(person)
复制代码
谷歌v8引擎运行得到下图
由此可见,原型中的属性并未改变, 实例不能直接修改原型上的属性。
总结:
- 实例对象显式具备的属性从构造函数来,隐式具备的属性从构造函数的原型来
- 实例不能直接修改原型上的属性
利用原型的特点和概念,可以提取共有属性
如果我们需要写一个构造函数,那么经常会出现这样的情景:部分属性值固定,部分可自定义,如下图
function Car(color, owner) {
this.height = 1000
this.leng = 4900
this.carName = 'BMW'
this.color = color
this.owner = owner
}
复制代码
前三个属性是固定的,后两个在创建对象时需赋值,那么当每次执行时,会重复调用前三行代码,如果我们运用原型,就能很好的优化。如下图
Car.prototype = {
height: 1000,
lang: 4900,
carName: 'BMW'
}
function Car(color, owner) {
// this.height = 1000
// this.lang = 4900
// this.carName = 'BMW'
this.color = color
this.owner = owner
}
var car = new Car('yellow', 'haonan')
var car1 = new Car('pink', 'huihui')
console.log(car.carName); //BMW
console.log(car1); //{ color: 'pink', owner: 'huihui' }
复制代码
我们可以看到依旧能打印出car.carName的值,且不用每次调用构造函数都需要调用前三行代码。但是打印car1只能显示color和owner,说明隐式具备的属性不调用则不会显示。
原型的删除和修改
例
function Person() {}
Person.prototype.lastName = '老鱼'
var person = new Person()
console.log(person.lastName) // 老鱼
Person.prototype.lastName = '虾米' // 修改
console.log(person.lastName)// 虾米
delete Person.prototype.lastName // 删除
console.log(person.lastName) // undefined
复制代码
注:实例不能直接修改或删除原型上的属性,即修改或删除必须带上prototype,不能写成Person.lastName = '虾米'
类型,必须写成例中Person.prototype.lastName = '虾米'
所示。
注:本文是博主初学JS所学知识,有错误之处在所难免,且有多处知识点未解释明白,欢迎大佬指正补充,本人也会定期更新新的文章以及修改前文错误,欢迎大家来评论区一起讨论学习~