javaScript:3天理解面向对象(2)

javaScript:3天理解面向对象(2)


prototype

理解:每个构造函数都有prototype原型属性,这个属性是对象类型,这个属性里面有两个属性constructor和proto;原型属性的constructor指向构造函数;(原型对象上面的属性proto我们今天先不考虑)实例对象的proto指向构造函数的原型;

根据案例来讲解:

function Person(name,age){
    this.name=name;
    this.age=age;
 }
 Person.prototype.showName=function(){
      console.log(this.name+"helloWord!");
}
var p1=new Person("小白",18);
var p2=new Person("小黄",18);
这是一个标准的构造函数,接下来我们来分析一下,prototype这个属性;
1.每个构造函数都有prototype这个原型属性;

证明:console.dir(Person);


从这张图片可以看出,每个构造函数都有一个prototype属性(红色的方框标记的),这个属性是对象类型(因为prototype的值是键值对,键值对是对象的标志)这个对象里面有两个属性一个是constructor(绿色的边框标记的)一个是proto(黑色边框标记的);

2.constructor属性指向构造函数;

证明:console.log(Person.prototype.constructor===Person);
输出的结果为:true;这就证明了,prototype的constructor属性指向,构造函数;

3.proto,实例对象里面也有一个proto属性,这个属性指向构造函数的原型;

证明:console.log(p1.proto===Person.prototype);
输出的结果为:true;这就说明了,实例对象的属性proto,指向构造函数的原型;

我们从内存图的角度来说明这个Person这个对象;



好好的理解一下这个内存图;

Tab栏案例;

用面向对象的方式编程;

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        #tab div{
            width: 200px;
            height: 200px;
            background: red;
            font-size: 30px;
            display: none;
        }
    </style>
</head>
<body>
    <div id="tab">
        <input type="button" value="苹果"/>
        <input type="button" value="橘子"/>
        <input type="button" value="香蕉"/>
        <div>苹果</div>
        <div>橘子</div>
        <div>香蕉</div>
    </div>
    <script>
        function Tab (id) {
            this.odiv=document.getElementById("tab");
            this.adiv=this.odiv.getElementsByTagName('div');
            this.ainput=this.odiv.getElementsByTagName('input');
        }
        Tab.prototype.innit=function  () {
            this.adiv[0].style.display='block';
            this.ainput[0].style.backgroundColor='orange';
            for (var i=0;i<this.ainput.length;i++) {
                this.ainput[i].index=i;
                var _this=this;
                this.ainput[i].onclick=function  () {
                    _this.change(this);
                }
            }
            this.autoplay();
        }
        Tab.prototype.change=function  (obj) {
            for (var j=0;j<this.adiv.length;j++) {
                this.ainput[j].style.backgroundColor='';
                this.adiv[j].style.display='none';
            }
            obj.style.backgroundColor='orange';
            this.adiv[obj.index].style.display='block';
        }
        Tab.prototype.autoplay=function  () {
            this.nowIdex=0;
            var that=this;
            setInterval(function  () {
                if(that.nowIdex===that.adiv.length-1){
                    that.nowIdex=0;
                }else{
                    that.nowIdex++;
                }
                that.change(that.ainput[that.nowIdex]);
            },1000);
        }
        var tab=new Tab('tab');
        tab.innit();
    </script>
</body>
</html>

初识原型链

原型链是什么?
原型链是有实例对象的属性和方法组成,通过protot链接到一起;
function Person(name,age){
      this.name=name;
      this.age=age;
}
Person.prototype.showAge=function(){
      console.log(this.name+'hello word !');
 }
 var p=new Person("zhangsan",18);

从以上的知识可以知道:

1).每个构造函数都有一个prototype属性,这个属性是一个对象,这个属性里面有两个属性一个是constructor另一个是proto;
2).原型中的constructor指向构造函数;
3).实例对象中的proto指向构造函数的原型;
证明:
console.log(Person.prototype.constructor===Person);//true;
console.log(P.proto===Person.prototype);//true;

既然构造函数的原型有两个属性,一个是constructot(指向构造函数),一个是proto,那么proto指向哪里?

我们先来打印一下,console.dir(Person.prototype.proto);


然后我们在来打印一下,console.dir(Object.prototype);

从图中可以知道,Person.prototype.proto===Object.prototype;
console.log(Person.prototype.proto===Object.prototype);//true;
从这里可以知道,prototype下面的constructor指向构造函数,prototype中的proto
指向,Object.prototype;
所以,就产生了一条链式结构;
p->Person.prototype->Object.prototype->null;
var arr=[];
arr->arr.prototype->Object.prototype->null;
var obj={};
obj->Object.prototype->null;

为什么Object.prototype.proto指向空呢??


大家看一下,Object.prototype上面没有proto属性,所以指向null;
证明:
console.dir(p.proto.proto.proto);

那么了解这写有什么用呢??
function Animal(name){
this.name=name;
}
Animal.prototype.showAge=function(){
console.log(this.name+'hello word');
}
function Dog(color){
this.color=color;
}
Dog.prototype=new Animal('小白');
var dog=new Dog('黄色');
console.log(dog.color);
console.log(dog.name);
dog.showAge();
为什么构造函数Animal上面的方法,构造函数Dog可以访问的到,我们画一张图来表示一下;

那我们把下面的代码在更改一下:

  function Animal(name){
  this.name=name;
}
Animal.prototype.showAge=function(){
    console.log(this.name+'hello word');
} 
function Dog(color){
    this.color=color;
}
Dog.prototype=new Animal('小白');
Dog.prototype.showAge=function(){
       console.log(this.name+':hellow word');
}
var dog=new Dog('黄色');

我在Dog的prototype上面加了一个方法,那么dog的实例能不能访问的到?

dog.showAge();

我们看一下内存图的变化;
![]


dog.showAge()是可以访问到的,因为Dog.prototype被指向为new Animal(),所以dog的showAge方法加在了new Animal()上面,new dog的实例通过proto可以访问到new Animal()上面。但是这样的话,我们就会发现,Dog.prototype.construcot===Animal;这样是不符合我们规定的;

那要是这样改动,内存图会有什么变化;

function Animal(name){
  this.name=name;
}
Animal.prototype.showAge=function(){
    console.log(this.name+'hello word');
} 
function Dog(color){
    this.color=color;
}
Dog.prototype=new Animal('小白');
Dog.prototype.showAge=function(){
       console.log(this.name+':hellow word');
}
Dog.prototype.constructor=Dog;
var dog=new Dog('黄色');  

代码我们在改动一下:

function Animal(name){
  this.name=name;
}
Animal.prototype.showAge=function(){
    console.log(this.name+'hello word');
} 
function Dog(color){
    this.color=color;
}
Dog.prototype=new Animal('小白');
Dog.prototype.showAge=function(){
       console.log(this.name+':hellow word');
}
Dog.prototype.constructor=Dog;
Object.prototype.showFn=function () {
      console.log(this.name+':1122222222');
};
var dog=new Dog('黄色'); 
Dog.prototype.constructor=Dog;

内存图发生了什么变化?


;
我们在来看一下这个案例,内存图的变化;

        function Animal (name,age) {
                this.name=name;
                this.age=age;
        }
        Animal.prototype={
          constructor:Animal,
            showAge:function  () {
                 console.log(this.name+'hello Word');
           },
          showName: function (){
                 console.log(this.name+"我今年"+this.age+"岁了");
           }
        };
            var animal=new Animal('小白',19);
            animal.showAge();
            animal.showName();

继承;

继承分为原型继承和构造函数继承;
原型继承;
          function Person (name) {
                    this.name=name;
                    this.score=[20,30,40,50];
                }
                function Student (age) {
                    this.age=age;
                }
             Person.prototype.showName=function(){
                  console.log(this.name+':下班回家很晚');
              }
                Student.prototype=new Person('tom');
                Student.prototype.showAge=function  () {
                    console.log(this.name+":下班回来晚了");
                }
                var stu=new Student(29);
                var stu1=new Student(35);
                stu.score.push(100);
                console.log(stu.score);
                console.log(stu1.score);
                stu.showAge();
                stu1.showAge();
                console.log(stu.name);
                console.log(stu1.name);

原型继承的缺点:

1.原型继承中的要传的参数已经无法更改(我想让stu1获取name的属性为tom,stu2获取name的属性为Jerry,但是这样无法做到);
2.所继承的函数中的引用类型的数据被所有的实例,所共享;

借用构造函数继承;
          function Person (name) {
                    this.name=name;
                    this.score=[20,30,40,50];
                }
            Person.prototype.showAge=function  () {
                console.log(this.name+':我已经完成le');
            }
            function Student (name,age) {
                    Person.call(this,name);
                    this.age=age;
                }
            var stu=new Student("Jerry",29);
                stu.score.push(100);
                console.log(stu.score);
                var stu1=new Student("Tom",35);
                console.log(stu1.score);
                console.log(stu.name);
                console.log(stu.age);
                console.log(stu1.name);
                console.log(stu1.age);
                stu.showAge();
                stu1.showAge();

借用构造函数继承的缺点:

1.无法继承构造函数原型上面的方法;

最佳的继承方法:组合继承;
            function Person (name) {
                    this.name=name;
                    this.score=[20,30,40,50];
                }
            Person.prototype.showAge=function  () {
                console.log(this.name+':我已经完成le');
                }
            function Student (name,age) {
                    Person.call(this,name);
                    this.age=age;
                }
            Student.prototype=new Person();
            var stu=new Student("Jerry",29);
          stu.score.push(100);
            var stu1=new Student("Tom",35);
对象全家福

1.每个函数都有一个prototype和proto;
2.如果这个函数是构造函数,那么主要用这个Prototype这个属性,这个属性是个对象,
默认有两个属性一个是constructor和proto;constructor指向这个构造函数,proto指向Object.prototype;
3.实力对象中的proto指向构造函数的原型;
4.如果这个函数是普通函数,那么proto指向Function.prototype,Function的 proto指向Object.prototype;
5.Function中的proto指向Function.prototype,也就是说,Function是Function的实例;
6.所有的函数都是Function的实例。

对象的本质

无续的键值对的组合;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容