目录
“原型”在我们一般人的眼里就是原来的模型的意思,那么请想一下,原来的模型,是否为一个对象呢?没错,可以将原型看作是一个实体,实体的东西就可以作为一个面对你的东西,也即为对象。原来的对象都是空空的,什么都没有,需要往里面加东西才能让这个对象丰满。
这里举个例子:就像我们人一样,生下来,全身空荡荡,需要衣服来保暖,需要学习来充实自己的能力,这里的能力就可以看作是对象里面的属性了,能力可以让我们找到更好的工作,属性也是如此,可以让对象充实,做出相关的操作和返回。这就是我理解的原型。
当然也不是说其他看不见的就不是对象了,相关请继续了解:https://blog.csdn.net/qq_39178993姚希瑶的博客_CSDN博客-前端,Matlab,ACM easy领域博主
首先,我们应该先明白,只要是函数,都会有自己的一个prototype和__proto__属性,也就是我们每个函数都有的能力,这里的构造函数故名思意就知道,是一个构造什么东西的函数,这里构造什么在下文的三、实例对象中就可以知道,同其他函数一样,他就是一个拥有自己名字的普通函数。
衔接上文中的被构造的东西,这里被构造的东西就是现在所解释的实例对象,这里实例对象同样是一个函数,他就相当于是构造函数的儿子一样,我们的实例对象创建函数为: new Object()
,为什么这样说呢,看到他的呈现方式可能会让你茅塞顿开,为了方便我把构造函数和实例对象一同写在下方(代码比较简单,望理解):
//类-构造函数-函数对象
function Person() {
};
//向Person函数对象中添加work属性,打印输出work()...
Person.prototype.work = function() {
console.log("work()...")
}
//p为Person构造函数构造出来的实例对象
let p1 = new Person();
console.log(p.work);//打印结果为work()...
此时我们们的实例对象函数p1里面并没有work这个属性,但是当p1调work时候却能够打印出Person里面的属性(方法),那这是怎么回事呢,接下来的两点将会给你答案,我们这里只需要知道p1是Person构造函数构造出来的就行,也就是Person儿子。
那么在上面的代码中并没有原型对象存在里面,这是因为只要有了一个构造函数,就会产生该构造函数的原型对象,只是在代码中并未呈现,因为每个函数都会有proto的属性,该属性访问的是他父类的原型,这里p1的父类是Person构造函数,也就是说proto指向的是原型对象的,而原型对象是该类构造函数出现的同时就产生相同名字的一个对象,那么构造函数里面的属性也都指向原型对象,就造成了无论是构造函数Person还是实例对象p1,都是可以访问到原型对象里面的属性的,原型对象里的属性因此变为了公共属性。
1. 原型链:
当访问一个实例对象的某个属性时,会先在这个实例对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,(因为实例对象里面的__proto__属性指向的是构造函数的prototype属性的)如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,这就被称为原型链。
2. 原型链图解
<script src>
//1.只要是函数,都会具有prototype属性(浏览器自动解析加载出来的属性)
//2.这个prototype属性都对应着一个对象,这个对象就是我们所谓的原型对象。
//3.prototype里面存的是原型对象里面constructor的地址。而prototype属性指向的是我们的原型对象。
//4.如果函数作为普通函数进行调用,prototype没有任何作用。
function Person() {
}
function myClass() {
}
console.log(Person.prototype == myClass.prototype);//false,证明每一个函数都具有自己的prototype属性
</script>
<script src>
function myClass() {
}
//向myClass的原型中添加一个属性a
myClass.prototype.a = 123;
console.log(myClass.prototype.a);
//向myClass的原型中添加一个方法
myClass.prototype.sayHello = function(){
alert("Hello!")
}
var mc = new myClass;//通过myClass创建的实例mc
//向mc中添加属性a
mc.a = "我是mc中的a";
console.log(mc.a);
mc.sayHello();
var mc2 = new myClass;//同样是通过myClass创建的实例mc2
console.log(mc2.a);
console.log(mc.__proto__ == myClass.prototype);// //myClass具有prototype属性,并且mc是myClass创建的,所以mc里面的__proyo__属性等于myClass里面的prototype属性,而且他们两个都是指向同一个原型对象
console.log(mc2.__proto__ == myClass.prototype);//证明只要是同一个构造函数创建的,他们的__proto__都指向同一个原型对象。
//原型对象表示一个公共的区域,所有同一个构造函数里的实例都可以指向(访问到)这个原型对象。
//1.可以将对象中共有的内容,统一设置到原型对象中
//2.原型对象里面含有constrctor和__proto__属性
//3.( myClass.prototype.a = 123;)当我们访问对象的一个属性或者方法时,会先在自身去寻找,找不到就去原型对象中找,如果有就直接使用。(自己有就不用别人的)
//4.在原型对象中设置的属性和方法,只要实例对象没有设置相同的属性或者方法,都可以去原型对象中找。
//5.原型对象也是对象,它也有自己的原型对象,所以当我们访问对象的一个属性或者方法时,会先在自身去寻找,找不到就去原型对象中找,
// 如果原型里面还是没有就去原型的原型中去找,如果原型的原型中还是找不到就会归于最终的null。
console.log(mc.__proto__.__proto__);//(这就是原型中的原型)
</script>
<script>
//创建一个构造函数
function myClass() {
}
//向muClass原型对象中添加一个name属性
myClass.prototype.name = "我是原型对象中的xxx"
var mc = new myClass;
console.log(mc.name);
//使用in来检查对象中是否含有某个属性时,如果对象中没有,但是原型对象中有,就返回true
console.log("name" in mc);
</script>