820笔记(构造函数和原型)
构造函数和原型
对象的三种创建方式
- 字面量
var obj={}
- new 关键字
var obj = new Object()
- 构造函数创建
function Person(){
this.name='zs'
this.age=12
}
var p=new Person()
<script>
//1 字面量 一次只能创建一个对象
var obj = { name: 'zs', age: 23 } //一条数据,包含了两个字段
//2 利用new Object创建 一次只能创建一个对象
var obj1 = new Object()
console.log(obj1)
//两种方式向对象里添加内容
obj1.name = '笑笑'
obj1['age'] = 23
//3 利用构造函数创建对象 创建一类对象(有共同属性和方法的对象)
// 构造函数和普通函数的区别
// 构造函数的首字母要大写;构造函数必须用new来创建对象
// 一类学生 学生类 性别 年龄 成绩 学习
function Student(name, age, score) {
this.name = name
this.age = age
this.score = score
this.study = function () {
console.log('好好学习') //方法
}
}
var s1 = new Student('zs', 12, 100)
//先执行new Student创建一个对象,然后把这个对象给s1,再调用这个函数,给函数传递实参,给s1动态地添加属性
var s2 = new Student('ls', 32, 89)
</script>
构造函数存在的问题
每创建一个对象,就会生成一个新的函数,存在浪费内存的问题
解决方法:所有对象使用同一个函数,这样就节省了内存,怎么做呢?---原型
构造函数原型prototype
构造函数通过原型分配的函数,是所有对象共享的
javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个prototype属性就是一个对象,这个对象的所有属性和方法都会被构造函数所拥有
我们可以把那些不变的方法,直接定义在prototype对象上,这样所有的对象实例就可以共享这些方法
实例化对象
每一个实例对象都可以访问它构造函数的原型对象中的成员
<script>
/*
实例成员 就是构造函数内部通过this添加的成员
*/
function Star(uname, age) {
this.uname = uname //这个uname就是一个实例成员
this.age = age
this.sing = function () {
console.log('唱歌')
}
}
//实例化对象 new创建的对象就是一个实例
var ldh = new Star('刘德华', 18) //实例成员只能通过实例化的对象来访问
console.log(ldh.uname)
console.log(ldh.age)
</script>
通过原型动态添加对象
一般情况下,我们把公共的属性定义到构造函数里;公共的方法放在原型对象上
function Star(uname, age) {
this.uname = uname //这个uname就是一个实例成员
this.age = age //构造函数给的自身的属性
}
//使用原型对象创建一次就可以了
//通过动态的方式给原型对象添加成员
Star.prototype.sing=function(){
console.log('唱歌')
}
var zxy=new Star('张学友',28)
zxy.sing() //sing在原型对象里
对象原型
1 实例对象都会有一个属性 _proto_ 指向构造函数的prototype原型对象
2 之所以我们对象可以使用构造函数prototype原型的属性和方法,就是因为对象有_proto_属性的存在
3 _proto_对象原型和原型对象prototype是等价的
4 对象原型的意义在于为对象的查找机制提供了一个方向,或者说是一条路线
5 _proto_是一个非标准的属性。在开发过程中,不可以使用这个属性 _proto_,它只是内部指向原型对象prototype
<script>
function Star(uname, age) {
this.uname = uname //这个uname就是一个实例成员
this.age = age
}
Star.prototype.sing = function () {
console.log('唱歌')
}
var ldh = new Star('刘德华', 18)
var zxy = new Star('张学友', 26)
ldh.sing()
zxy.sing()
//对象身上系统自己添加一个_proto_指向我们构造函数的原型对象prototype
console.log(ldh._proto_ === star.prototype) //true
/* 方法的查找机制
首先先看ldh对象身上是否有sing方法,如果有就执行这个对象上的sing;如果没有sing,因为有_prototype_的存在,就去构造函数原型对象prototype上找sing这个方法
*/
</script>
constructor 构造函数
对象原型(_proto_)和构造函数(prototype)原型对象里面都有一个属性,constructor属性我们称为构造函数,因为它指回构造函数本身
constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数
一般情况下,对象的方法都在构造函数的原型对象中设置,如果有多个对象的方法,我们可以给原型对象采取对象的形式赋值,但是这样会覆盖构造函数原型对象原来的内容,这样修改后的原型对象constructor就不再指向当前构造函数了。此时,我们可以在修改后的原型对象中,添加一个constructor指向原来的构造函数
<script>
function Star(uname, age) {
this.uname = uname //这个uname就是一个实例成员
this.age = age
}
//如果有多个对象的方法,可以给原型对象采取对象的形式进行赋值
Star.prototype = {
//constructor值改变了
//我们可以在修改后的原型对象中,添加一个constructor指向原来的构造函数
constructor: Star,
sing: function () {
console.log('唱歌')
},
movie: function () {
console.log('电影')
},
}
var ldh = new Star('刘德华', 18)
var zxy = new Star('张学友', 26)
console.log(ldh._proto_)
console.log(Star.prototype)
</script>
原型链
每一个实例对象有一个_proto_属性,指向构造函数的原型对象
构造函数的原型对象,也是一个对象
这样一层一层往上找,就形成了原型链