目录
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个原型对象的指针。
1.构造函数的定义:
构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 一起使用。一般情况下我们会把公共的属性定义到构造函数里面,而公共的方法放到原型对象身上。
在 JS 中,使用构造函数时要注意以下两点:
1.构造函数用于创建某一类对象,其首字母要大写
2.构造函数要和 new 一起使用才有意义
new 在执行时会做四件事情
①在内存中创建一个新的空对象。
②让 this 指向这个新的对象。
③执行构造函数里面的代码,给这个新对象添加属性和方法。
④返回这个新对象(所以构造函数里面不需要 return )。
2.constructor 构造函数
构造函数(prototype)原型对象里面都有一个属性 constructor 属性 ,constructor 我们称为构造函数,因为它指回构造函数本身。
function Person(name, age) {
this.name = name;
this.age = age;
}
console.log(Person.prototype); // 这里调用的是构造函数的原型对象
3.原型prototype。
在js中我们所说的原型通常是针对函数而言的,构造函数也是函数。函数是一个对象只要是对象就有自己的属性,在js 中我们所创建的对象自带一个属性prototype,我们把prototype称为原型,【或者可以称为显式原型】这个prototype指向了一个对象,我们就称为原型对象,【通常直接将propotype直接当成原型对象】
原型里面有一个constructor构造函数,指向Person构造函数
- 每个函数都有
prototype
属性,被称作原型。prototype
原型指向一个对象,故也称作原型对象
4.prototype和__proto__
其实这是两个维度的东西。
prototype
的维度是函数,而__proto__
的维度是对象。
__proto__
是每个对象都有的属性,我们通常把它称为"隐式原型"
把prototype
称为"显式原型"。
因为函数也是一个对象,所以函数里面有prototype和__proto__两个属性
4.1 __proto__
:
- 通常被称作隐式原型,每个对象都拥有该属性。
[[prototype]]
其实就是__proto__
。
补充:[[prototype]]
其实就是隐式原型__proto__
,因为各大浏览器厂家不同,所以取了别名罢了,大家只需记住这个和__proto__
一样即可。
function Person (name) {}
Person.prototype.name = '婷宝'
Person.prototype.say = function () {
console.log("你好!!")
}
let obj = new Person() // 初始化构造函数 【new 创建一个新的对象,新的实例 Person 实例】
console.log(obj.name) // 婷宝
obj.say()
console.log(obj) // Person{}
console.log(obj.__proto__ === Person.prototype) // true
function Person (name) {
this.name = name
}
Person.prototype.name = '婷宝'
Person.prototype.say = function () {
console.log("你好!!")
}
let obj = new Person('6666') // 初始化构造函数 【new 创建一个新的对象,新的实例 Person 实例】
console.log(obj.name) // 婷宝
obj.say()
console.log(obj) // Person{}
console.log(obj.__proto__ === Person.prototype) // true
上面的例子说明了,当对象想要获取某个属性的时候,先判断自己的属性中有没有,之后再去__proto__属性中找。而这个时候__proto__
与Person
的prototype
是相等的
上面的查找的过程形成的一条线索就叫做原型链,大家可以把原型链拆开来理解:原型和链。
- 原型就是我们的
prototype
- 链就是
__proto__
,它让整个链路连接起来。
原型的作用是什么?
共享方法
只有当实例本身不存在对应的属性或方法时,才会去找原型对象上的对应属性或方法
构造函数通过原型分配的函数是所有对象所共享的。
// var queue = new Queue()
function Person(name, age) {
this.name = name;
this.age = age;
}
// 在原型上添加属性或者方法
Person.prototype.sex = '男'
var person1 = new Person('Mlke', 10) // person1就是实例
console.log(Person.prototype); // 这里调用的是构造函数的原型对象
console.log(person1.sex);
5.实例对象
继承的本质就是复制,即重写原型对象,代之以一个新类型的实例。
var person1 = new Person('Mlke', 10) // person1就是实例
console.log(person1.constructor); //这里可以通过实例的constructor访问构造函数
// 但是由于继承的特性,我们说constructor本质上是原型对象的属性
person1就是实例 (复制品),所以实例对象中的属性和方法继承了构造函数指向原型对象
总结:
创建构造函数的时候会有一个(prototype)原型 ,指向一个对象所以我们一般称为原型对象,
原型对象上面的所有方法都会被构造函数的实例继承(例如上面的person1),所以我们一般把公共的属性和方法定义在prototype上【构造函数原型的作用——共享数据】
在实例person1 中,我们通过 person1.constructor 访问对应的构造函数,但是实例中的属性和方法在自身没有定义的情况下都是从原型对象上面继承的,所以我们说constructor是原型对象中的属性