对象_原型

理解对象

对象

定义
有属性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 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

你可能感兴趣的:(对象_原型)