构造函数、实例对象、原型对象

构造函数与实例对象之间的关系

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

おすすめ

転載: blog.csdn.net/Amethystlry/article/details/114390883