在原型链之前要先对JavaScript的构造函数有所了解。
其中重要的部分是函数的成员的设置和静态成员的访问。
构造函数是为了创建对象,当然创建对象还有其他两种方法,一种是使用字面量{}创建对象,一种是用new Object()创建对象。
//字面量 {}
var person1 = {
name: 'aa',
age: 6, gender: '男',
classRoom: '⾼⼀' ,
study: function () {
console.log('study')
}
}
//new Object()
var obj = new Object()
//这是一个空对象,可以通过以下代码追加对象
obj.name="a"
但两种方法一次只能创建一个,当我们创建比较多的信息时,比如下面的的情况:
里面很多的属性和方法是相同的,因此利用函数的方法封装相同的代码,我们把这个函数叫做构造函数。
为什么要单独起名构造函数,而不是函数?因为这个函数不一样,里面封装的不是普通代码,而是对象。构造函数是把对象里面一些相同的属性和方法抽象出来,封装到函数里面。
function 构造函数名(){
this.属性 = 值;
this.方法=function(){}
}
function Person(){}
new Person()
构造函数的执行过程其实也就是new操作符的基本过程
let person1 = {};
构造函数中,不要显式返回任何值,如果定义了返回值,会使new关键字失效
其实在JavaScript中,
JavaScript 的构造函数中可以添加一些成员,可以在构造函数本身上添加,也可以在构造函数内部的 this 上添加。通过这两种方式添加的成员,就分别称为静态成员和实例成员。
function Person(name, classRoom) {
this.name = name
this.classRoom = '⾼⼀'
this.study = function () {
console.log("study")
}
}
let l = new Person('Laura')
l.age = 18
Person.gender = 'female'
console.log(l) //Person { name: 'Laura', classRoom: '⾼⼀', age: 18 }
构造函数存在浪费内存的问题。
当创建一个对象时,由于有复杂数据类型函数,需要再开辟一个内存空间存储复杂数据类型。创建多个对象,就要开辟多个内存空间存储同一函数,Laura.study===Yujin.study
是false,因为存储的地址不相同,这是不科学的,因为代码一样,但存在在不同的内存空间中。
用原型来解决。
function Person(name, classRoom) {
this.name = name
this.classRoom = '⾼⼀'
}
Person.prototype.study = function () {
console.log('study')
}
let l = new Person('Laura')
let y = new Person('Yujin')
l.study()
对象都会有一个属性__proto__,指向构造函数的prototype原型对象,之所以对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型的存在。
• __proto__对象原型和原型对象 prototype 是等价的
• __proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性来调用函数和赋值(可以y. __proto__
),它只是内部指向原型对象 prototype,所以不能y. __proto__.study()
,会报错,直接y.study()就可以了。
对象原型(proto)和构造函数(prototype)原型对象里面都有一个属性constructor,constructor 称为构造函数,因为它指回构造函数本身。
constructor主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。
一般情况下,对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象constructor就不再指向当前构造函数了。
function Person(name, classRoom) {
this.name = name
this.classRoom = '⾼⼀'
}
Person.prototype = {
study: function () {
console.log('study')
},
sing: function () {
console.log('sing')
}
}
let l = new Person('Laura')
let y = new Person('Yujin')
l.study() //输出study
此时,我们可以在修改后的原型对象中,添加一个constructor指回原来的构造函数。
Person.prototype = {
constructor: Person,
study: function () {
console.log('study')
},
sing: function () {
console.log('sing')
}
}
图中由相互关联的原型组成的链状结构就是原型链(右侧蓝色斜线)
听黑马的b站课再加一些自己学习时候的困惑和思考。