美文网首页
对象_原型

对象_原型

作者: jrg_memo | 来源:发表于2017-03-03 11:48 被阅读16次

    理解对象

    对象

    定义
    有属性property和方法function就是对象。
    解析
    属性property:描述对象的状态
    方法function:操作对象的属性-->改变对象的状态

    对象 人类{
            姓名:memo
            身高:165cm
            体重:60kg  
    }
        方法
            改名
            长高
            运动
    
    从这个意义上来说,对象是一个容器,封装了一些属性和方法。
    

    面向对象编程

    定义
    OOPObject-oriented programming是一种编程方式
    特点
    继承性:子类自动继承其父级类中的属性和方法,并可以添加新的属性和方法或者对部分属性和方法进行重写。继承增加了代码的可重用性。
    多态性:子类继承了来自父级类中的属性和方法,并对其中部分方法进行重写。
    封装性:将一个类的使用和实现分开,只保留部分接口和方法与外部联系。

    类 & 对象

    基于(例如JAVA C++)的编程语言:
    对象object 依靠 类class来产生。
    解析
    class:把对象的功能和方法抽象成一个模板,是虚拟的。
    对象object:把虚拟的 类 具化成一个实例,是存在的。

    原型 & 对象

    基于原型(例如 JS)的编程语言:
    对象object 利用 原型prototype 构造出来的。
    解析
    原型:是一个对象,其他对象可以通过它实现继承。
    原型有个属性prototype = constructor:原型 实例的构造器指向原型本身 Method 原型的各种方法 __proto__ 实例的原型链 追溯 实例来源 constructor 显示构造器,追溯 这个原型的来源 prototype = constructor:原型的原型 原型的构造器指向 原型的原型 Method 原型的原型 的各种方法 __proto__ 原型的原型链,追溯原型的来源 ▼ 总结:原型的 prototype属性 = 构造实例的属性 + 存储可用的方法

    原型链:如上所示↑
    调用对象一个实例的方法时,先从自身开始查找
    如果没有就从原型上查找,找到了就可以使用
    如果没有就从原型的原型查找…直到找不到返回null
    像这样顺着原型一层一层查找的行为就是原型链。
    ▼ 总结:原型链 = __proto__.__proto__.__proto__...null

    创建对象

    JS中没有这种模板,如何创建对象?
    使用构造函数作为对象的模板。

    构造函数

    作用
    这个函数的目的,就是操作一个新生的空对象,将其“构造”为需要的样子。
    特点
    函数体内部使用了this关键字,代表了所要生成的对象实例。
    生成对象的时候,必需用new命令,调用这个函数。
    形式

      function Car(name,color,status){
        this.name = name;
        this.color = color;              =>  构造函数:构造this的属性,把参数赋给属性
        this.status = status;
      }
      Car.prototype.run = function(){
        console.log('running');
      };
      Car.prototype.stop = function(){   =>  给构造函数的prototype属性上添加方法  
        console.log('stop');
      };
      Car.prototype.getStatus = function(){
        console.log(this.status);
      };
    
      var Benz = new Car('Benz','black',30); =>  使用new命令 生成一个实例,赋给Benz
      Benz.run();//running
      Benz.stop();//stop
      Benz.getStatus();//30
    
      var Audi = new Car('Audi','red',20)
    
    *分析   
        Car是一个构造函数,用来构造实例Benz;(Car是个概念,Benz是个实物)
        name,color,status  是Car的属性;(描述Car的状态,生来既有)
        run,stop,getStatus 是Car的方法;(改变Car的状态,后来添加)   
        Benz 是这个构造函数所生成的实例,继承了Car的属性和方法。
    
    *关系----------------------------------------——————--
          构造函数                                                      
          Car                                             
            属性         name,color,status   => 用来构造 Benz       
            prototype    Constructor:Car    => 指向自身 (本构造器是Car)
                         原型链 __proto__  
                               Constructor    指向Object(Car的构造器是Object)
                               Object方法
    
          实例1
          Benz
            原型Car                          => 显示构造器,说明Benz是由Car创造的
              属性1:属性值    
              属性2:属性值                    => 继承Car属性 :传入的参数作为值
              属性3:属性值       
              __proto__                      => Car的 prototype
                    constructor:Car         => 指向构造器Car本身
                    Method1
                    Method2                  => Car的方法
                    Method3                    
                    __proto__
                          constructor:Object => 指向Car的 构造器Object
                          Method              => Object的方法
                          Null
          实例2
          Audi 
            同上
    
    *new——————————————————————————————————————————
        new做了什么:
          创建一个空对象,作为Benz
          将Benz.__proto__指向Car.prototype
          将Benz赋值给函数内部的this关键字
          传入参数,调用Car,返回实例Benz。
     
        new的作用:
          如果不写new,这只是一个普通函数,相当于给函数Car又起了一个新名字,它返回undefined。
          如果写了new,它就变成了一个构造函数,它绑定的this指向新创建的对象,并默认返回this。
      
    *this——————————————————————————————————————————
        this 是什么
          执行上下文环境
    
        this 怎么改
          .call()   &   .apply() 
    
    *Demo——————————————————————————————————————————
        1 人类有身高,体重,性别;会吃饭,跑步,学习。
        2 有个人叫小明,
        3 他的 身高180cm,体重65kg,性别男;
        4 他当然也会吃饭,跑步,学习;而且拥有一个新技能:写代码。
        5 小明有个儿子叫小小明;
        6 他会吃饭,跑步,学习,写代码。因为爸爸是个程序员。
        -------------------------------------------------------------------------------
        0 人类是抽象了小明的一个概念,是虚拟的;小明是一个实体化的人类,现实存在的。
    
        1 身高,体重,性别,是人类的属性,描述了人是什么状态;
          吃饭,跑步,学习,是人类的方法,可以用这些方法改变人的一些状态。
    
        2 var XiaoMing = new People => 初始化一个人类代号小明,把人的属性赋给小明。
    
        3 他 = this 指代小明,数据180cm...是传入的参数,是小明的属性值,
          所以他的身高180cm   =>   this.height = 180cm  。
    
        4 小明继承了人类的方法,这些方法所有人都可以用;写代码是小明独有的技能,其他人不可以用;
          所以不能在小明的原型(xiaoMing.__proto__)=>人类(People.prototype)上添加。
          需要使用Object.create()进行差异化继承。
    
        5 小小明由小明而来,小明由人类而来,所以小小明一共继承了4个方法 。
          判断谁从哪来,使用 instanceOf;判断方法从哪来,使用 hasOwnProperty 。
    
        6 根据上下文环境,他 指代小小明,所以此时 this => 由小明变为小小明。
          在小小明的语境里使用小明,不能用this指代,可以取个新代词 var father = xiaoming.
    

    应用

    1 构造函数:
    创建一个 GoTop 对象 Demo

     需求
        new 一个 GotTop 对象则会在页面上创建一个回到顶部的元素,点击页面滚动到顶部。
     属性
        ct       GoTop 对应的 DOM 元素的容器
        target   GoTop 对应的 DOM 元素
     方法
        bindEvent  用于绑定事件
        createNode 用于在容器内创建节点
     函数
      function GotTop(ct,target){
        this.ct = ;
        this.target = ;
      }
      GotTop.prototype.createNode = function(){   
      };
      GotTop.prototype.bindEvent = function(){       
      };
    

    2 this
    2.1 this被动态修改的3种方法

      .call() & .apply() 
      前提
          函数在执行的时候,传入的参数默认为( this,arguments )
     *相同  
          传入的第一个参数是this,之后的参数为arguments
     *区别 
          .call的arguments是列表 =>  .call( Obj, a1, a2, a3, a4, a5 )  ↘ 两种写法
          .apply的arguments是数组 => .apply(Obj, [a1, a2, a3, a4, a5]) ↗   等价
     *不修改this
           第一个参数为null
     *Demo
          var john = { 
            firstName: "John" 
          }     
          function func() {               =>    this = window
            alert( this.firstName )
          }
          func.call(john) //alert(John)   =>    this = john
    
     *其他用法
       1   Math.max.apply(null, Array) =>返回数组中最大的元素
    
       2   Array.prototype.slice.apply(arguments) 
           作用:把类数组对象转化为真正的数组
           注意:类数组对象是这种形式=> arguments={key:number,length:n} 
    
       3   Array.apply(null, ["a",,"b"]) =>把空对象转化为undefined
           作用:把空对象转化为undefined
           注意:使用forEach遍历数组的时候,会跳过空对象,不会跳过undefined
    
      .bind()
      ?????????????????
    

    2.2 this根据函数执行环境改变的4种方式

      var john = { 
        firstName: "John" 
      }
      function func() {                     
      alert(this.firstName + ": hi!")
      }
      john.sayHi = func                     ■ 属于 方法调用模式,this => 调用方
     john.sayHi()  //alert(John: hi!)     
     
    
     var func= function(){ 
          alert(this.firstName + ": hi!")
          }                                 ■ 属于 函数调用模式,this => window
      func('john') // alert(undefined: hi!) 
      
    
    
      function func() { 
      this.firstName + ": hi!"
      }                                     ■ 属于 构造函数调用模式,this=>新创建的对象
      new func()// 返回一个新对象
    
    
    
     .call()   &   .apply()                 ■ 属于 动态修改调用模式,this => 传入的第一个参数
    

    2.3 thissetTimeout / setInterval方法中

      document.addEventListener('click', function(e){
          console.log(this);              => this = document
                                             在事件处理程序中this代表事件源DOM对象
          setTimeout(function(){
              console.log(this);          => this = window
                                             setTimeout/setInterval执行的函数this是全局对象
          }, 200);
      }, false);
    

    2.4 this的储存

      var module= {
        bind: function(){
          $btn.on('click', function(){   
            console.log(this)
            this.showMsg();              =>   this = $btn
          })
        },
        showMsg: function(){             =>   showMsg这个方法绑在$btn上
          console.log('饥人谷');               无法通过调用module获得
        }
      }
      修改-------------------------------------------------------------
      var module= {
         bind: function(){
           var mod = this;               =>  给此时this指代的module换个名字
           $btn.on('click',function(){
               console.log(this);        =>  代码运行到这里,this指向$btn
               mod.showMsg();            =>  showMsg方法仍然绑定在module上
            })
         },
         showMsg:function(){
            console.log('jirengu');
         }
      }
    

    3 原型
    3.1 扩展String

      需求
          var str = 'ahbbccdeddddfg';
          var ch = str.getMostOften();
          console.log(ch); //d , 因为d 出现了5次
      实现
          String.prototype.getMostOften = function(){
    
            var obj = {};
            for(var i=0; i<this.length; i++){
              var k = this[i];
              if(obj[k]){
                obj[k]++;
              }else{
                obj[k] = 1;
              }
            }
           console.log(obj); // Object {a: 1, h: 1, b: 2, c: 2, d: 5…}
    
            var num = 0;
            var word = '';
    
            for(var key in obj){
              if(obj[key] > num){
                num = obj[key];
                word = key;
              }
            }
            return  word + ',因为' + word + ' 出现了' + num + '次'
          }
    

    3.2 instanceOf

    *作用
          判断一个对象是否为另一个对象的实例
    *Demo   
          function instanceOf(obj,fn){
            var oldpro = obj.__proto__;
            while(oldpro){
              if(oldpro === fn.prototype){     => 如果obj.__proto__ 指向 fn.prototype
                  return true;                     则 obj 是 fn 的实例
              }else{
                  oldpro = oldpro.__proto__;
             }
           }
             return false;
          }
    

    4 继承

    *定义
         继承是指一个对象直接使用另一个对象的属性和方法。
    *作用
         继承划分了类的层次性,父类代表的是更一般、更泛化的类,而子类则是更为具体、更为细化;
         继承是实现代码复用、扩展软件功能的重要手段,
         完全相同的属性和方法不必重写,只需写出新增或改写的内容。
    

    4.1 继承的复用性

     //方法1
     function People(name, sex){
         this.name = name;
         this.sex = sex;
         this.printName = function(){     =>   方法作为属性储存在构造器里
             console.log(this.name);
         }
     }
     var p1 = new People('饥人谷', 2)     =>   新建一个对象就重新生成一次printName
    
     //方法2
     function Person(name, sex){
         this.name = name;
         this.sex = sex;
     }
     Person.prototype.printName = function(){   =>  方法储存在__prootype__里,
         console.log(this.name);                    使用时只要顺着原型链查找即可
     }
     var p1 = new Person('若愚', 27);           优点:节省内存
    

    4.2 继承的新增

     *方法  Object.create
     *作用  创建一个拥有指定原型和若干个指定属性的对象
     *Demo
            function Person(name, age){
              this.name = name;
              this.age = age;
            }
            Person.prototype.sayName = function(){
              console.log(this.name);
            } ------------------------------------------- 构造函数Person
            function Male(name, age, sex){
              Person.call(this, name, age); => 初始化Person,使Male实现继承
              this.sex = sex;
            } ------------------------------------------- 复制Person的属性
    
            方法1  使用场景:不兼容Object.create()
            Male.prototype = new Person(); ---------
                                                    丨--- 使Male的原型指向Person
            方法2  使用场景 :兼容Object.create() ----      
            Male.prototype = Object.create(Person.prototype);
    
            Male.prototype.constructor = Male; ---------- 把Male的原型构造器改为male 
            Male.prototype.sayAge = function(){---------- 给Male的原型绑定方法
              console.log(this.age);
            };
            var p1 = new Male('hunger', 20, 'nan');------ 实例化Male
            p1.sayName();//hunger
            p1.sayAge();//20
    

    4.3 继承的层次性

     *方法  .hasOwnProperty()
     *作用  判断一个对象是否包含自定义属性而不是原型链上的属性;
            是JavaScript中唯一 处理属性但是不查找原型链的函数。
     *Demo
            p1.hasOwnProperty('name');//true
            p1.hasOwnProperty('sayName');//false
            Male.prototype.hasOwnProperty('sayAge');//true

    相关文章

      网友评论

          本文标题:对象_原型

          本文链接:https://www.haomeiwen.com/subject/wjlnwttx.html