原型
原型的由来
由于在构造函数中,使用构造函数可以创建多个对象,但是他存在一个问题就是,不同的实例的函数是不一样的,这就意味着每个实例对象都会占据一定的内存空间,这是没有必要的,会造成资源浪费,因此我们把一些不变的属性和方法放在原型对象中,原型对象中的方法都会被构造函数所拥有,因实例对象可以访问原型对象中的属性和方法
概念原文链接:https://blog.csdn.net/m0_67134595/article/details/128044853
原型对象
JavaScript规定每一个构造函数都有prototype属性,指向另一个对象,这个对象就是原型对象
原型对象的作用
最主要的作用就是用来存放实例对象的公有属性和公有方法。
构建函数的constructor
每一个原型对象都有一个constructor属性,指向该构造函数本身
它主要用来该对象是引用的哪个构造函数,它可以让原型对象重新指向原来的构造函数
结论一:任何函数function或者类也都有一个prototype原型对象属性,该prototype原型对象有属性constructor,指向函数自身
结论二:我们创建对象时对象就会生成一个__proto__,__proto__属性原名叫[[prototype]],所有实例对象都没有prototype,但是都有一个__proto__原型链对象,并且__proto__对象指向的是实例对象构造函数的原型对象
function Person(name,age){
this.name=name
this.age=age
this.getName=function(){
console.log("我叫"+name)
}
}
Person.prototype.age=20
let person=new Person("jack",1)
console.log(person.__proto__.age) //20
console.log(person.age) //1
console.log(person.__proto__===Person.prototype) //true
var 对象=new 函数()
对象.__proto__===函数.prototype
对象的__proto__的值对应构造函数的prototype的值
结论三:js中万物皆对象,所以实例对象、函数、prototype原型对象等都是对象,这些对象也有__proto__指向自己的构造函数。prototype原型对象的构造函数是Object
function Person(name,age){
this.name=name
this.age=age
this.getName=function(){
console.log("我叫"+name)
}
}
Person.prototype.age=20
let person=new Person("jack",1)
console.log(person.__proto__===Person.prototype)
console.log(person.__proto__.__proto__===Object.prototype) //true
console.log(Person.prototype.__proto__===Object.prototype) //true
console.log(person.__proto__.__proto__.__proto__) //null
console.log(Object.prototype.__proto__) //null
此处提问一个问题,为什么所有的对象都有toString()呢
person.toString()
let student={}
student.toString()
这是因为不管函数、对象等他们最终指向的原型对象都是Object,那么Object相当于他们的祖宗,所有Object有toString(),那么其他的肯定有。
结论四:函数也是对象,那么函数__proto__指向的是Function的原型对象,原型对象prototype的__proto__,最终都是指向Object的原型对象
function Person(name,age){
this.name=name
this.age=age
this.getName=function(){
console.log("我叫"+name)
}
}
Person.prototype.age=20
let person=new Person("jack",1)
console.log(Person.__proto__===Function.prototype)
console.log(Function.prototype.__proto__===Object.prototype)
console.log(Object.__proto__===Function.prototype)
原型有什么好处呢
- 可以共享变量和方法,节约占用空间(如下面代码)
- 可以对构造函数扩展变量和方法
function Person(name,age){
this.name=name
this.age=age
this.getName=function(){
console.log("我叫"+name)
}
}
var Stu1=new Person("小明",20)
var Stu2=new Person("小光",18)
// 指向两个不同的空间
console.log(Stu1.getName==Stu2.getName) //false
Person.prototype.count=100
Person.prototype.study=function(){
console.log("共享学习空间")
}
// 指向同一个空间
console.log(Stu1.study==Stu2.study) //true
这里中的say方法并不是自己的实例,为什么可以访问呢,就是因为每一个实例对象都有__proto__属性,指向构造函数的原型对象,所有实例对象可以访问到原型对象中的方法,就是因为__proto__属性的存在,__proto__属性是一个非标准的属性实际开发中并不使用,只是他的内部指向prototype
概念原文链接:https://blog.csdn.net/m0_67134595/article/details/128044853
原型链
每一个实例对象都有__proto__属性,指向构造函数的原型对象
构造函数的原型对象也具有__proto__属性,也指向他的原型对象这样一层一层就形成了原型链
原型链就是成员的查找机制
当一个对象访问一个属性或者时,先在自身中查找有没有该属性
没有的话就向它的原型对象中查找,也没有的话,就在原型对象的原型中查找
一直找到null,找不到就,变量的值为undefined,函数调用报错
概念原文链接:https://blog.csdn.net/m0_67134595/article/details/128044853