原型和原型链
三个重要的点
构造函数
构造函数是我们平常所看到的函数,当任意一个普通函数用于创建一类对象时,它就被称作构造函数。例如人类,动物类....
function Person(name,age){
this.name=name;
this.age=age;
//我就是构造函数
}
他有几个特点
1.this指向实例化的对象。
2.存在 prototype原型属性,存放原型对象
3.通过New来实例化对象
4.实例化对象可以获取到构造函数内的值或者方法。
5.构造函数首字母大写用于区分于普通函数
实例对象
通过var per = new Person() new出来的对象就是实例对象
实例出来的对象可以使用构造函数的方法和属性。
function Person(name,age){
this.name=name;
this.age=age;
this.sayHi(){
console.log('Hi')
}
//我就是构造函数
}
var per = Person("小明",18)//创建实例对象
console.log(per.name)//小明
console.log(per.sayHi())//Hi
原型对象
每一个构造函数都有一个原型属性(prototype),里面存放的对象就是原型对象。
主要用于存放公共的内容,用于继承。
function Person (age) {
//构造函数
this.age = age
}
Person.prototype = {
//构造函数的原型属性。
this.sex= '男'
this.sayHi = function () {
console.log('sayHi')
}
}
var per = Person();//实例对象
console.log(per.age) //实例对象获取了构造函数的内容;
console.log(per.sex);
per.sayHi() //实例对象获取了原型的属性和方法
实例对象、原型对象和构造函数之间的关系
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
深入理解继承
function Person (name, age) {
//这是构造函数
this.name = name;
this.age = age;
this.sayHi = function () {
console.log('sayHi')
}
}
Person.prototype.sex = '男' //原型对象 即构造函数的Person.prototype
Person.prototype.eat = function () {
console.log('eat')
}
var per =new Person('小米',18);//实例化构造函数的对象 ,必须new
//观察打印内容可以发现原型对象是在__proto__中的,实例对象直接可以看到
console.log(per)
//实例对象可以获取构造函数中的属性和方法
console.log(per.name)
console.log(per.age)
per.sayHi()
//实例对象可以获取到原型对象的值和方法
console.log(per.sex)
per.eat();
//通过原型链实现简单的继承。
function Student () {}
//这一行的意思是Student的原型指向变成了new Person() 的实例对象。可以访问到实例对象能访问到的所有。例如构造函数的属性和原型对象的属性
Student.prototype = new Person('小白',20)
var stu = new Student();
console.log(stu.name)//小白
stu.eat()//eat因为是原型方法
//如果换成这样那么Student指向Person的原型对象。原型对象中没有构造函数的属性,所以不能获取构造函数的属性,只能后去到原型对象中的属性
Student.prototype = Person.prototype
var stu = new Student();
console.log(stu.name)//undefined
stu.eat()//eat因为是原型方法
//改变函数的指向
// 如果在函数原型改变指向之前赋予函数原型,那并灭有什么卵用,必须在改变指向后赋值(属性函数)
//使用原型实现继承的缺陷在于由于实例化了对象Person所以接下来获取的name,age都是固定值,都是小白和20,所以就需要借用构造函数来继承
//借用构造函数继承。
function Student1 (name, age, scorce) {
this.scorce = scorce;
Person.call(this, name, age)
}
var stu1 = new Student1 ('13',13,13)
var stu2 = new Student1 ('23',23,23)
var stu3 = new Student1 ('33',33,33)
console.log(stu1.name,stu1.age,stu1.scorce)
console.log(stu2.name,stu2.age,stu2.scorce)
console.log(stu3.name,stu3.age,stu3.scorce)
stu1.sayHi()//可以使用到构造函数中的方法,但是无法使用到原型函数中的方法(stu1.eat())
//所以借用函数继承的缺陷在于无法使用到原型函数中的方法
//试想可不可以用借用构造函数和原型来实现一个完美的继承?
function Student2 (name, age, scorce) {
this.scorce = scorce;
Person.call(this, name, age)
}
//赋值的时候,原型对象内容一样,所以可以获取到原型对象的内容。
Student2.prototype = Person.prototype
var stu11 = new Student2 ('13',13,13)
var stu21 = new Student2 ('23',23,23)
var stu31 = new Student2 ('33',33,33)
console.log(stu11.name,stu11.age,stu11.scorce)
console.log(stu21.name,stu21.age,stu21.scorce)
console.log(stu31.name,stu31.age,stu31.scorce)
stu11.sayHi()
stu11.eat()