原型是 JavaScript 中的一个重要概念,它涉及到对象之间的继承关系和属性的共享。在 JavaScript 中,每个函数都有一个 prototype 属性,这个属性指向一个对象,即该函数的原型。通过构造函数创建的对象实例会继承构造函数的原型上的属性和方法。
原型(显式原型)
定义:原型是函数天生就有的属性(prototype),它定义了构造函数制造出来的对象的公共祖先 ,通过该构造函数创建的对象,可以隐式的继承函数原型上的属性和方法
js
Person.prototype.say = function(){
console.log('jxb 真好吃');
}
function Person(){
this.name = '冷少'// this是一个对象
this.age = 18
}
let p = new Person()
let p2 = new Person()
console.log(p.say==p2.say); //打印true,拥有公共祖先
可以看到p.say==p2.say是true,利用prototype,构造函数定义出来的对象是一样的。
js
Person.prototype.say = function(){ //prototype 函数自带的属性,函数原型,不会添加到Person
console.log('jxb 真好吃');
}
function Person(){
this.name = '冷少'// this是一个对象
this.age = 18
}
let p = new Person() //实例对象显式的继承了构造函数添加到this上的属性,隐式的继承函数原型上的属性和方法
let p2 = new Person()
p.say()//打印console.log(p);里面没有say,但是可以用p来调用
console.log(p);
实例对象显式的继承了构造函数添加到this上的属性,隐式的继承函数原型上的属性和方法,所有无法打印p,只有this定义的属性。
意义:可以提取公有属性,简化代码执行
js
Car.prototype = {
name:'BMW',
long:4900,
height:1400
}
function Car(ower,color){
// this.name = 'BMW'
// this.long = 4900
// this.height = 1400
this.ower = ower
this.color = color
}
let car = new Car('李总','red')
let car2 = new Car('戴总','pink')
代替了this,简化了代码,用node打印看不到,浏览器可以看到
原型上的属性修改只能原型自己操作,实例对象无权修改
js
Car.prototype.name = 'BMW'
Car.prototype.long = 4900
Car.prototype.height = 1400
function Car(ower,color){
this.ower = ower
this.color = color
}
let car = new Car('李总','red')
let car2 = new Car('戴总','pink')//实例对象
car.name = '奔驰'
// delete Car.prototype.name
delete car.name
console.log(car);
console.log(Car.prototype.name);
第11行代码无法修改原型定义的name第13行代码无法删除原型定义的name,12行代码才能删除。
对象原型(隐式原型)
实例对象的隐式原型 == 构造函数的显式原型
js
function Bus(){
}
function Car(){
}
let car = new Car()
// constructor 构造器属性,用于记录对象是由谁创建的
console.log(car.constructor);
这段代码我们会发现car是Car创造的
再如果我们修改一下代码
js
<script>
function Bus(){
}
Car.prototype ={ // 实例对象上的constructor 为什么因为这个改成了Bus
constructor :Bus //看看有没有这段代码时的con
}
function Car(){
}
let car = new Car()//
// constructor 构造器属性,用于记录对象是由谁创建的
console.log(car.constructor);
可以发现
Car被修改成了Bus,这说明构造函数的显式原型和实例对象的隐式原型肯定有关系,所以实例对象的隐式原型 == 构造函数的显式原型。
new
- 创建this对象
- 执行构造函数中的逻辑
- 让this的隐式原型==构造函数的显式原型
- 返回这个this对象
用一段代码解释new的这些作用
js
Person.prototype.say = function(){
console.log('hello');
}
function Person(){
this.name ='袁总'
this.age = 18
//使用new后创建一个this对象
// var this={
// name :'袁总',
// age:18,
// __proto__:Person.prototype 让this的隐式原型==构造函数的显式原型
// }
// return this
}
let p = new Person()
p.say()
原型链
顺着对象的隐式原型不断地向上查找上一级的隐式原型,直到找到目标或者null,这种查找关系,叫做原型链
js
function Foo(){}
let foo = new Foo()
//下面是查找规律
foo.__proto__ === Foo.prototype //实例对象隐式原型等于构造函数显式原型
Foo.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ ===null
console.log(foo.toString());
这段代码会显示如下内容
在 Object.prototype找到了foo.toString()
网易面试题:所有的对象身上都有隐式原型?
绝大多数有,有的没有,如下就没有隐式原型
但是可以通过继承属性,这样会变成隐式原型
总结起来,原型和原型链是 JavaScript 中非常重要的概念,它们提供了一种灵活的方式来实现对象之间的继承和共享属性和方法。深入理解原型和原型链对于 JavaScript 开发者来说是非常重要的,它能够帮助我们更好地利用 JavaScript 的特性,编写出高效和可维护的代码。