Javascript中的原型与原型链

 

 //先定义构造函数  
function Person(name, age){
    this.name = name;
    this.age = age;
    this.sayHi = function(){
         console.log("Hello");
    }
}
var per = new Person("xiao", 30);
/*
  如果想要使用一些属性和方法,并且属性的值在每个对象中都是一样的,方法在每个对象中的
  操作也是一样的,那么,为了共享数据,节省内存空间,是可以把属性和方法通过原型的方式进行共享
*/
Person.prototype.sex = "男";
Person.prototype.eat = function(){
    console.log("吃吃吃");
}

//因为该方法在构造函数中,不属于原型,如果创建一百个对象调用该方法,则会消耗一百个内存空间
//所以在构造函数中声明的方法大都为私有的方法
per.sayHi();

//该方法为原型中的方法,所有的实例化对象调用的方法都是同一个内存空间的,很大的节省了内存空间
per.eat(); 
//在控制台打印两个对象
console.dir(per);
console.dir(Person);
//实例对象的原型__proto__和构造函数的原型prototype指向是相同的
//实例对象中的原型__proto__指向的是构造函数中的原型
console.log(per.__proto__===Person.prototype);//true
//实例对象中__proto__是原型,浏览器使用的
//构造函数中的prototype是原型,程序员使用的

如下图:

原型和原型链之间的关系图解:

原型对象的指向可以改变:

       例1:

//人的构造函数
 function Person(age){
     this.age = age;
}
//人的原型链对象方法
Person.prototype.eat = function () {
     console.log("人的吃");
}
//学生的构造函数
function Student(){
            
}
Student.prototype.sayHi = function () {
     console.log("hihihi");
}
//原型指向的改变:把学生的原型指向了人的原型
Student.prototype = new Person(10);
var stu = new Student(); //实例化对象stu指向的是Person而不是Student
stu.eat(); //输出"人的吃"
stu.sayHi(); //报错:"stu.sayHi is not a function"因为Peron构造函数中没有sayHi方法,所以报错

       例2:

//学生的构造函数
function Student(){
            
}
Student.prototype.sayHi = function () {
     console.log("hihihi");
}
//原型指向的改变:把学生的原型指向了{}
Student.prototype = {
     eat:function(){
          console.log("吃吃吃");
     }
};
var stu = new Student(); //实例化对象stu指向的是{}而不是Student
stu.eat(); //输出"吃吃吃"
stu.sayHi(); //报错:"stu.sayHi is not a function"因为{}对象中没有sayHi方法,所以报错

       

       分析:

       原本实例对象的原型__proto__指向的是该对象所在的构造函数的原型对象

       如:实例对象stu指向的应该是Student构造函数的原型对象prototype

       构造函数的原型对象(prototype)指向如果改变了,实例对象的原型(__proto__)指向也会发生改变

       如:Student.prototype = new Person(10),表示Student的原型指向了实例对象new Person(10),而该实例对象

       new Person(10)指向的是构造函数Person的原型对象prototype,而构造函数Person的原型对象里只有eat()方法,

       没有sayHi方法,所以实例对象stu只能调用eat方法。当然,如果要访问sayHi方法,就应该在改变Student原型指向之后

       添加方法,如:

Student.prototype = new Person(10);

Student.prototype.sayHi = function(){

     console.log("hihihihi");

}

   

     如上方法添加就可以访问了,上述方法就相当于给实例对象new Person(10)添加sayHi方法。

原型最终指向哪里:

function Person(age){
     this.age = age;
}
//人的原型链对象方法
 Person.prototype.eat = function () {
     console.log("人的吃");
}
            
var per = new Person(); //实例化对象stu指向的是Person而不是Student
per.eat(); //输出"人的吃"
console.dir(per);
console.dir(Person);
console.log(Person.prototype.__proto__);

    实例对象per中有__proto__原型,

    构造函数中有prototype原型,

    实例对象中的__proto__指向的是构造函数中的prototype。

    prototype是对象,

    所以,prototype这个对象中也有__proto__,那么它指向了哪里?prototype这个对象中的__proto__指向的应该是

    某个构造函数的原型prototype。

    打印构造函数console.dir(Person)

    

   如上图可知,prototype对象中的__proto__指向构造函数Object中的原型prototype

   打印console.log(Person.prototype.__proto__)   

   

   输出结果为prototype中_proto__指向的构造函数Object。

   所以实例对象per的_proto__原型——>Person.prototype的__proto__ ——>Object.prototype._proto__———>null

   所以我们也可以打印得到如下输出结果:

console.log(per.__proto__ === Person.prototype);  //true
console.log(per.__proto__.__proto__ === Person.prototype.__proto__);  //true
console.log(Person.prototype.__proto__ === Object.prototype);   //true
console.log(Object.prototype.__proto__);   //null

 

    总结:

       1.原型对象的指向是可以改变的

       2.实例对象和原型对象之间的关系通过__proto__原型来联系起来,这个关系就是原型链

       3.任何函数的下划线原型__proto__都指向Object的原型对象prototype

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值