1、实例对象是通过构造函数来创建的——创建的过程叫实例化
2、如何判断对象是不是这个数据类型?
1)对象 instanceof 构造函数的名字(更常用)
2)通过构造器的方式:实例对象.构造器==构造函数的名字
console.dir(obj);//console.dir显示对象的结构
console.log(obj.constructor==Person);//true
console.log(obj.__proto__.constructor==Person);//true
console.log(obj.__proto__.constructor==Person.prototype.constructor);//true
判断对象是不是属于这种类型的两种方式
function Animal(name){
this.name=name;
}
var dog=new Animal('dog');
console.log(dog.constructor==Animal);//true
console.log(dog instanceof Animal);//true
总结:
构造函数可以实例化对象,其中有一个属性叫prototype,是构造函数的原型对象,构造函数的原型对象prototype中有一个constructor构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数
实例对象的原型对象(__ proto__)指向的是该构造函数的原型对象,构造函数的原型对象prototype中的方法是可以被实例对象直接访问的
实例对象中有__proto__这个属性,叫原型,也是一个对象,可以叫原型对象
这个属性是给浏览器使用的,不是标准的属性
构造函数中有prototype这个属性,也是原型对象,这个属性是给程序员使用的,是标准的属性
由于实例对象是通过构造函数来创建的,构造函数中有原型对象prototype,因此实例对象的__proto__指向了构造函数的原型对象prototype
function Person(name){
this.name=name;
}
Person.prototype={
//手动修改原型的指向
constructor:Person,
height:185,
color:'blueviolet',
code:function(){
console.log('coding more and...');
}
}
var obj=new Person('amethyst');
console.log(obj.name,obj.color);//amethyst blueviolet
obj.code();//coding more and...
通过原型添加方法,解决数据共享,节省内存空间
不仅方法可以共享,属性也可以共享
需要共享的数据写在原型中,不需要共享的数据写在构造函数中
function Person(name){
this.name=name;
}
//方法
Person.prototype.code=function(){
console.log('love coding');
}
//属性
Person.prototype.color='blueviolet';
var obj1=new Person('amethyst');
var obj2=new Person('lanlan');
console.log(obj1.code==obj2.code);//true
console.log(obj1.color);//blueviolet
obj1.code();//love coding
实例对象的方法是可以相互访问的
function Person(name){
this.name=name;
this.code=function(){
console.log('love coding');
}
this.play=function(){
console.log('code more,play less...');
this.code();
}
}
var obj=new Person('amethyst');
obj.play();//code more,play less... love coding
原型对象中的方法也是可以相互访问的
function Person(name){
this.name=name;
}
Person.prototype.code=function(){
console.log('love coding');
}
Person.prototype.play=function(){
console.log('code more,play less...');
this.code();
}
var obj=new Person('amethyst');
obj.play();//code more,play less... love coding
实例对象使用的属性或者方法,找到了直接使用,找不到则去找实例对象的__proto__指向的原型对象protootype中去找,找到了则使用,找不到则报错
function Person(name){
this.name=name;
this.code=function(){
console.log('构造方法中的code');
}
}
Person.prototype.code=function(){
console.log('原型对象中的code');
}
var obj=new Person('amethyst');
obj.code();//构造方法中的code
除了自定义的对象外,我们也可以为系统的对象添加方法,相当于改变源码
String.prototype.sayHi=function(){
console.log('Hi~'+this);
}
var str="amethyst";
str.sayHi();//Hi~amethyst
原型链是一种关系,实例对象和原型对象之间的关系,关系是通过原型__proto__来联系的
如果想要使用一些属性和方法,并且属性的值在每个对象中都是一样的,方法在每个对象中的操作也都是一样,那么,为了共享数据、节省内存空间,是可以把属性和方法通过原型的方式进行赋值的
构造函数中的this是实例对象,原型对象方法中的this是实例对象
function Person(name){
this.name=name;
console.log(this);//输出实例对象per
}
Person.prototype.code=function(){
console.log(this);//输出实例对象per
}
var per=new Person('amethyst');
per.code();
如果原型对象指向改变了,那么就应该在改变指向之后添加原型方法
function Person(name){
this.name=name;
}
Person.prototype.eat=function(){
console.log('eat less');
}
function Student(name){
this.name=name;
}
// //student的原型对象中添加方法——先在原型中添加方法
// Student.prototype.study=function(){
// console.log('study more');
// }
//student的原型,指向了一个person的实例对象
Student.prototype=new Person('cloud');
var stu=new Student('amethyst');
// stu.study();//报错
stu.eat();//eat less
//student的原型对象中添加方法——后在原型中添加方法
Student.prototype.study=function(){
console.log('study more');
}
stu.study();//study more
stu.eat();//eat less
实例对象的原型__proto__指向的是该对象所在的构造函数的原型对象
构造函数的原型对象prototype如果改变了,实例对象的原型__proto__也会发生改变
原型的指向是可以改变的,实例对象和原型对象之间的关系是通过__proto__联系起来的,这个关系就是原型链
原型链最终的指向是Object的prototype的__proto__
<div id='root'>div>
<script>
var obj=document.querySelector('#root');
console.dir(obj);
script>
divObj的 __ proto__——>HTMLDivElement.prototype
的__proto__——>HTMLElement.prototype
的__proto__——>Element.prototype
的__proto__——>Node.prototype
的__proto__——>EventTarget.prototype
的__proto__——>Object.prototype
的__proto__是null