前言
今天我们要来聊的内容是JavaScript中的原型和原型链。原型是JS中重要的一部分,同时当我们了解原型的概念,学会原型时,也能使我们编程减少代码重复,大大提高我们编程的效率。那么继续往下看吧!
正文
- 1.原型是函数上的一个属性,它定义了构造函数制造的对象的公共祖先。
看到这句话可能有点懵,那让我们通过一段代码来解释吧
js
function Person(){
this.name = 'tom'
}
let p = new Person()
console.log(p);
这段代码打印结果是{ name: 'tom' }
。这是为什么呢?因为当我们用 new
关键字来创建一个对象实例时,它会调用构造函数并初始化该对象。在这个构造函数中,通过 this.name = 'tom'
给对象添加了一个 name
属性,并将其值设为 'tom'
。因此,当我们打印这个对象时,会显示 { name: 'tom' }
。
js
Person.prototype.lastName = 'zhu'
Person.prototype.say = function(){
console.log('hello');
}
function Person(){
this.name = 'tao'
}
let p1 = new Person() // 隐式具有 lastName say
p1.say()
在这一段代码中我们在构造函数的部分并未添加lastname属性,可是当我们查找这个属性时是能打印出来的,同时p1
可以访问通过原型继承的 lastName
属性和 say
方法。当调用 p1.say()
时,它会执行原型上的 say
方法,并打印 'hello'
。
那么原型能有什么作用呢?
- 1.构造函数 new 出来的对象会 隐式继承到 构造函数原型上的属性
js
// 在构造函数之外为 Car 添加原型属性
Car.prototype.name = 'su7';
Car.prototype.lang = '5000';
Car.prototype.height = '1400';
function Car(color, owner) {
this.color = color;
this.owner = owner;
}
let tian = new Car('black', 'tiantian');
let xuan = new Car('green', 'xuanxuan');
console.log(tian.name); // 输出: 'su7
在这段代码中我们用了构造函数Car,它接受 color
和 owner
作为参数,并将它们分别赋值给新创建的实例的 color
和 owner
属性。然后我们又创建了两个不同的实例对象。我们通过 Car
构造函数的原型添加了 name
属性,这样所有 Car
实例都可以访问它。所以 console.log(tian.name)
输出 'su7'
。 这样做的优点是所有 Car
实例对象共享相同的属性,而不需要在每个实例中单独定义它们。提高了我们的代码效率。
- 2.实例对象可以修改显示继承到的属性,但是无法修改隐式继承到的属性(原型上的)
js
Car.prototype.product = 'xiaomi'
function Car(){
this.name = 'su7'
}
let car = new Car()
car.name = '保时捷'
car.product = 'HUAWEI'
// car.nickname = '小红'
// delete car.product
// delete Car.prototype.product
console.log(car.product)
在这段代码中,我们修改了 car
实例对象的 name
属性为 '保时捷'
,并添加了一个新的 product
属性 'HUAWEI'
。因为实例对象上已经存在一个名为 product
的属性(被赋值为 'xiaomi'
),所以这个赋值操作会覆盖原型上的 product
属性。由于实例对象上已经有一个 product
的属性,它会覆盖原型上的同名属性。所以最后的打印结果是 'HUAWEI'
在这一点中我们同时还需要注意这两点:
1.实例对象无法给原型新增属性
2.实例对象无法删除原型上的属性
js
Car.prototype.product = 'xiaomi'
function Car(){
this.name = 'su7'
}
let car = new Car()
delete car.product
// delete Car.prototype.product
在这段代码中如果执行delete car.product
,那么最后打印的product还是xiaomi
,这是因为果这个属性来自原型,那么原型上的属性仍然存在,对实例对象是不可见的。
- 3.对象的隐式原型 === 创造它的构造函数的显式原型
js
function Person(){
}
let p = new Person()
console.log(Person.prototype); // 函数的原型 显示原型
console.log(p._proto._); //p._proto._ 对象的原型 隐式原型
// Person.prototype === p._proto._
函数的原型(显示原型) :在 JavaScript 中,每个函数都有一个特殊的属性 prototype
,它指向一个对象,称为函数的原型。这个原型对象是在函数定义时自动创建的。
对象的原型(隐式原型) :console.log(p.__proto__);
这行代码打印了 p
实例对象的原型,也称为隐式原型。`
在 JavaScript 中,所有通过构造函数创建的实例对象都会继承自该构造函数的原型。因此,Person.prototype === p.__proto__
表达了函数的原型和对象的原型之间的关系。而且js引擎在查找属性时,会先查找对象显示具有的属性,找不到,再查找对象的隐式原型(proto)
总结
在这篇文章中我们这篇文章中介绍了什么是原型以及原型的一些特点。
原型的意义:可以提取公有属性,简化代码的执行。
实例对象会通过自己的隐式原型去继承构造函数显示原型上的属性和方法
今天的内容就到这里啦,如果这篇文章对你们有帮助,辛苦你们把小赞点起来^_^