原型
原型的由来
由于在构造函数中,使用构造函数可以创建多个对象,但是他存在一个问题就是,不同的实例的函数是不一样的,这就意味着每个实例对象都会占据一定的内存空间,这是没有必要的,会造成资源浪费,因此我们把一些不变的属性和方法放在原型对象中,原型对象中的方法都会被构造函数所拥有,因实例对象可以访问原型对象中的属性和方法
function Preson(name.age) {
this.name=name
this.age=age
this.say = function () {
console.log('hello')
}
}
var p1 = new Preson('zs',18)
var p2 = new Preson('ls',16)
console.log(p1.say===p2.say) // false
原型对象
JavaScript规定每一个构造函数都有prototype属性,指向另一个对象,这个对象就是原型对象
原型对象的作用
最主要的作用就是用来存放实例对象的公有属性和公有方法。
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.say = function () {
console.log("Hello");
}
let p1 = new Person('xiaoming', 20);
let p2 = new Person('xiaohong', 19);
p1.say() // Hello
p2.say() // Hello
这里中的say方法并不是自己的实例,为什么可以访问呢,就是因为每一个实例对象都有__proto__属性,指向构造函数的原型对象,所有实例对象可以访问到原型对象中的方法,就是因为__proto__属性的存在,__proto__属性是一个非标准的属性实际开发中并不使用,只是他的内部指向prototype
console.log(p1.__proto__===Person.prototype) // true
由此得来以下图
构造函数的constructor属性
每一个原型对象都有一个constructor属性,指向该构造函数本身
它主要用来该对象是引用的哪个构造函数,它可以让原型对象重新指向原来的构造函数
function Person() {
}
console.log(Person===Person.prototype.constructor) //true
原型链
每一个实例对象都有__proto__属性,指向构造函数的原型对象
构造函数的原型对象也具有__proto__属性,也指向他的原型对象这样一层一层就形成了原型链
原型链就是成员的查找机制
当一个对象访问一个属性或者时,先在自身中查找有没有该属性
没有的话就向它的原型对象中查找,也没有的话,就在原型对象的原型中查找
一直找到null,找不到就,变量的值为undefined,函数调用报错