在ES6之前,面向对象是通过构造函数来实现的
构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new
一起使用,我们可以把对象中的一些公有的属性和方法抽取出来,然后封装到这个函数里面。
在 JS 中,使用构造函数时要注意以下两点:
1、构造函数用于创建某一类对象,其首字母要大写
2、构造函数要和 new
一起使用才有意义
- new在执行时会做四件事情:
1、在内存中创建一个新的空对象
2、让this
指向这个新的对象
3、执行构造函数里面的代码,给这个新对象添加属性和方法
4、返回这个新对象(所以构造函数里不需要return
)
构造函数中的属性和方法称为成员,成员分为两大类,
1、实例成员:实例成员就是构造函数内部通过this添加的成员
例如:
function Star(name,age){
this.name = name
this.age = age
this.sing = function(){
console.log('我会唱歌')
}
}
let ldh = new Star('刘德华',30)
//这里的this.name this.age this.sing
就是实例成员
实例成员只能通过实例化的对象来访问,例如:
console.log(ldh.name)
ldh.sing( )
如果写为Star.name
就是错误的,是访问不到的。因为不可以通过构造函数来访问实例成员
2、静态成员:在构造函数本身上添加的成员称为静态成员
例如:
Star.sex = '男'
这个 sex 就是一个静态成员
静态成员只能通过构造函数来访问,例如:
console.log(Star.sex) //男
console.log(ldh.sex) //undefined ,不能通过实例对象来访问!
构造函数原型---prototype
- 构造函数通过原型分配的函数是所有对象所共享的
prototype
- JavaScript规定,每一个构造函数都有一个prototype 属性,指向另一个对象,(即每一个函数里面,都有一个prototype 对象)注意:这个prototype 就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
- prototype的作用:可以把那些不变的方法,直接定义到prototype对象上,这样所有的对象的实例就可以共享这些方法了。
语法:
例:
function Car(name,color){
this.name = name
this.color = color
}
Car.prototype.run = function(){
console.log('不变的方法定义到prototype上实现共享')
}
let bmw = new Car('宝马','red')
let benz = new Car('奔驰','blue')
bmw.run()
benz.run()
一般情况下,公共属性定义到构造函数里面,公共的方法定义到原型对象即(prototype)身上
对象原型 __proto__
:
-
对象都会有一个属性
__proto__
,指向构造函数的 prototype 原型对象,之所以对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象身上有__proto__
原型的存在 -
__proto__
对象原型 和 构造函数的 prototype 原型对象是等价的 -
__proto__
对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条线路,但是它是一个非标准属性,因此在实际开发中,不可以使用这个属性,它只是内部指向原型对象prototype
constructor 构造函数 :
对象原型(
__proto__
)和 构造函数(prototype
)原型对象里面都有一个constructor
属性 ,constructor
我们称为构造函数,因为它指回构造函数本身。constructor 主要作用是告诉我们,一个对象是通过哪个构造函数创建出来的,并且在一些特殊情况下它可以让原型对象重新指向原来的构造函数,例:
Star.prototype = {
constructor:Star
run:function(){
console.log('123')
},
stop:function(){
console.log('456')
}
}
使用以上写法取代 Star.prototype.run = function(){ }
和 Star.prototype.stop = function(){ } 时, 相当于把一个对象赋值给了原来的原型对象
prototype ,这样就覆盖了原来的 prototype ,此时的 prototype 中就没有了 constructor
属性,此时,就必须利用constructor 指回原来的构造函数。
即:如果我们修改了原来的原型对象,且给原型对象赋的值是一个对象,就必须利用constructor
指回原来的构造函数。
构造函数 、实例 、原型对象 三者之间的关系
原型链
构造函数的原型对象也是一个对象,所有它也有 __proto__
,指向的是Object.prototype
JavaScript的成员查找机制(规则):
按原型链的机制查找:
1、当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
2、如果没有就查找它的原型(也就是__proto__
指向的prototype原型对象)
3、如果还没有就查找原型对象的原型(Object 的原型对象)
4、依次类推一直找到 Object 为止(null)