原型对象的定义
prototype显式原型
每一个构造函数,都会被解析器添加一个属性prototype
(显式原型属性),这个属性默认指向着一个Object
对象,这个对象就称为原型对象。
function Student()//创建一个构造函数
{
}
console.log("Student.prototype的数据类型为:",typeof(Student.prototype));//"object"
console.log(Student.prototype);//原型对象
__proto__隐式原型
当函数作为构造函数函数调用prototype
时,它所创建的对象中都有一个隐含的属性,指向该构造函数的原型对象,我们可以通过__proto__
(隐式原型属性)来访问。
function Student()//创建一个Student构造函数
{
}
var stu1 = new Student();//通过Student构造函数创建的一个实例对象stu1
var stu2 = new Student();//通过Student构造函数创建的一个实例对象stu2
var stu3 = new Student();//通过Student构造函数创建的一个实例对象stu3
console.log(stu1.__proto__ === Student.prototype);//true
console.log(stu2.__proto__ === Student.prototype);//true
console.log(stu3.__proto__ === Student.prototype);//true
所以实例指向大概就如下图所示
原型对象就相当于一个公共的区域,所有同一个类的实例,都可以访问到这个原型对象,可以将对象中共有的内容统一设置到原型对象中。
一般是添加属性(方法),作用:所有的实例对象自动拥有原型中的属性(方法)
例如:
//向Student的原型中添加属性a
Student.prototype.a = 10;
//向Student的原型中添加方法show()
Student.prototype.show = function()
{
alert("人生大舞台,谁用谁精彩!!!");
}
console.log(Student.prototype);
这样就成功添加进去,并且每个实例对象都可以访问
console.log(stu1.a);//10
console.log(stu2.a);//10
console.log(stu3.a);//10
console.log(stu1.show());//人生大舞台,谁用谁精彩!!!
大概如下图所示
- 当我们访问一个对象实例的属性或方法时,它会优先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象寻找,如果找到则直接使用。
//向stu1中添加属性a
stu1.a = 250;
console.log(stu1.a);//250
console.log(stu2.a);//10
console.log(stu3.a);//10
constructor属性
原型对象中有一个属性constructor,它指向函数对象
console.log(Student.prototype.constructor === Student);//true
一个完整的逻辑图
原型链
原型对象也是对象,那么它是不是也有原型呢?
所以举个例子:
console.log(stu1.__proto__.__proto__);//Object
答案也是有原型的,而且其中还有两个常用的方法,也就是说很多常用但是不需要我们自己定义的方法例如toStrint()
和hasOwnProperty()
就放在这个原型当中,这个对象就是Object
的原型对象。
hasOwnProperty()
方法可以用来检查对象自身是否含有该属性,只有当对象自身含有属性时,才会返回true。
语法:
hasOwnProperty("属性名")
那么如果我们再往这个原型对象,检查是否还有原型呢?
console.log(stu1.__proto__.__proto__.__proto__);//null
答案是null
也就是说在往Object
的原型对象上面就没有原型了。故此,原型链的尽头就是Object函数的原型对象。
所以我们可以将上面的图更新为:
如何查找对象属性(方法)
访问一个对象属性时:
- 先从自身属性中查找,找到返回
- 如果没有,在沿着·
__proto__
这条链向上查找,找到返回 - 如果最终没找到,返回
undefined
- 故此原型链也叫隐式原型链
- 可以理解为:
- 如果没有在自身找到,就去原型的对象中寻找,如果原型对象中有,则使用。
- 如果没有则去原型的原型中寻找,直到找到Object对象的原型
- 如果
Object对象
的原型中仍然没有,就返回undefined
。
例如在stu1
实例自身中创建一个test1
:
function Student()//创建一个构造函数
{
}
var stu1 = new Student();//通过Student构造函数创建的一个实例对象stu1
//向stu1的原型中添加属性test1
stu1.test1 = function()
{
console.log("我是自己的方法!");
}
stu1.test1();//我是自己的方法!
然后再往Student()
的原型里面添加一个test2
function Student()//创建一个构造函数
{
}
var stu1 = new Student();//通过Student构造函数创建的一个实例对象stu1
//向Student的原型中添加属性test2
Student.prototype.test2 = function()
{
console.log("我是Student原型中的方法!");
};
stu1.test2();//我是Student原型中的方法!
如果里面没有任何地方都没有test3
,则会报undefined
function Student()//创建一个构造函数
{
}
var stu1 = new Student();//通过Student构造函数创建的一个实例对象stu1
//向Student的原型中添加属性test2
Student.prototype.test2 = function()
{
console.log("我是Student原型中的方法!");
};
//stu1.test3();//加括号会报不是一个函数的错
console.log(stu1.test3);//undefined
故此查找对象属性(方法)大概如图所示: