面向对象(OOP)--OOP基础与this指向详解

  前  言编程

          

 学过程序语言的都知道,咱们的程序语言进化是从“面向机器”、到“面向过程”、再到“面向对象”一步步的发展而来。相似于汇编语言这样的面向机器的语言,随着时代的发展已经逐渐淘汰;而面向过程的语言也只有C语言老大哥依然坚挺;如今主流的语言(例如Java、C++、PHP等)都是面向对象的语言。 而咱们的JavaScript语言,偏偏介于面向过程与面向对象之间,咱们称它为“基于对象”的语言。可是,JS中的OOP依然是咱们学习JS的重要一环,固然像“继承”“封装”这样的面向对象特征,都是由模拟实现的。今天,咱们就一块儿来探讨一下JS中的面向对象吧!数组

 


1、OOP基础知识


1类和对象

面向对象编程(OOP)  思惟导图函数

 

 

一、类:学习

    一类具备相同的特征(属性)和行为(方法)的集合。
      eg:人类--> 属性:身高、性别; 方法:吃饭、说话
二、对象:this

    从类中拿出具备肯定属性值和方法的个体。
      eg:张三--> 属性:身高:170、 体重;50kg; 方法: 说话-->我叫张三,身高170

三、类和对象的关系
      类是抽象的,对象是具体的。 (类是对象的抽象化,对象是类的具体化)
      类是一个抽象的概念,只能说类属性和方法,可是,不能给属性赋具体的值
        好比:人类有姓名,可是不能说人类的姓名叫什么。。。。
      对象是一个具体的个例,是将类中的属性进行具体赋值而来的个体。
        好比:张三时人类的一个个体,能够说张三的姓名叫张三。也就是,张三对人类的每个属性进行了具体的赋值,那么张三就是由人类产生的一个对象。

四、使用类和对象的步骤:
  ① 建立一个类(构造函数):类名必须使用大驼峰法则。即,每一个单词的首字母都要大写,spa

function 类名(属性值1,属性值2,...){
    this.属性1 = 属性值1;
    this.属性2 = 属性值2;
    ...
    this.方法 = fucntion(形参){
        //方法中要调用自身属性必须使用thi.属性
    }
}        

 


  ② 经过类,实例化(new)出一个对象:code

var obj = new 类名(属性值);
obj.属性;    //调用属性
obj.方法(); //调用方法



  ③ 注意事项:
       一、经过类名,new出一个对象的过程,叫作"类的实例化";

         二、类中的this,会在实例化的时候指向新new出的对象。
          因此,this.属性、 this.方法 其实是将属性和方法绑定在即将new出的对象上面;

       三、在类中,要调用自身的属性,必须使用this.属性。若是,直接使用变量名,则没法访问对象的属性。

       四、类名必须使用大驼峰法则,注意与普通函数的分。
五、两个重要属性
    ① constructor :返回当前 对象 的构造函数。
     对象

 zhangsan.constructor == Person; √

 


    ② instanceof :检测一个对象是否是一个类的实例;blog

lisi instanceof Person          √ lisi是经过Person类new出的
lisi instanceof Object           √ 全部对象都是Object的实例
Person instanceof Object     √ 函数自己也是对象

 



六、广义对象与狭义对象:
  ① 狭义对象:只有属性和方法,除此以外没有任何其余内容;继承

var obj = {};
var obj = new Object();




  ② 广义对象: 用字面量声明的基本数据类型不是对象,不可以添加属性和方法
    除了用字面量声明的基本数据类型外JS中万物皆对象。换句话说,只要可以添加属性和方法的变量,均可以称之为对象。

var s = "12"; //不是对象
s.name = "aaa";
console.log(typeof(s)); //string
console.log(s.name);    // undefined 字面量声明的字符串不是对象,不能添加属性

var s = new String("123"); //是对象
s.name = "aaa";
console.log(typeof(s)); //object 
console.log(s.name);    // aaa 使用new关键字声明的字符串是对象,能添加属性和方法

 

 

2OOP的属性和方法

 

成员属性和成员方法

 

一、在构造函数中,使用this.属性声明,或者在实例化出对象之后,使用"对象.属性"追加的,都属于成员属性或成员方法。也叫实例属性和实例方法
  成员属性/成员方法: 是属于由类new出的对象的。
  须要使用"对象名.属性名"调用.

 

私有属性和私有方法

二、经过"类名.属性名"、"类名.方法名"申明的属性和方法,称为静态属性、静态方法 。也叫类属性和类方法;
    类属性/类方法,是属于类的(属于构造函数)。
    经过"类名.属性名"调用
三、成员属性是属于实例化出的对象的,只能使用对象调用;
    静态属性是属于构造函数的,只能使用类名调用。

 

私有属性和私有方法

 

四、在构造函数中使用var申明的变量称为私有属性,使用function申明的函数称为私有方法

function Person (){
  var num = 1 ; //私有属性
  function func(){}    //私有方法
}

 

私有属性和私有方法的做用域,只在构造函数中有效。即,只能在构造函数内部使用,在构造函数外部,不管使用对象仍是类名都没法调用。

 

 

 
代码解释
 

 

function Person(name){
                this.name = name;                //声明成员属性
                var sex = "男";             //私有属性
                this.sayTime =  function(){      //声明成员方法
                    alert("我说当前时间为"+getTime());
                }
                this.writTime =  function(){
                    alert("我写了当前时间为"+getTime());  //调用私有方法
                }               
                function getTime(){                //私有方法
                    return new Date;
                }
       }
  /***************************成员属性/方法*************************/ var zhangsan = new Person("张三");      //类的实例化 zhangsan .age = 18;      //追加成员属性 alert(zhangsan .name);    //调用成员属性 /***************************静态属性/方法***************************/ Person.count = "60亿"; //声明静态属性 alert(Person.count); //调用静态属性 var lisi = new Person("李四"); alert(lisi.count); //undefined 静态属性是属于类的,只能用类名调用 /*************************私有属性/方法**************/ lisi.sayTime(); //外部间接调用 lisi.writTime();

 

 


2  this指向详解

 

一、相关知识:

对于判断this的指向问题,总的来讲,就是:谁最终调用函数,this就指向谁。


  ① this指向谁,不该该考虑函数在哪声明,而应该考虑函数在哪调用;
  ② this指向的永远只多是对象,而不多是函数;
  ③ this指向的对象,叫作函数的上下文(context),也叫函数的调用者。

二、虽然知道了,谁最终调用函数,this就指向谁。可是,仍是以为有点笼统,不够详细。对this的指向问题仍是太模糊。

因而,在这里,影子特向你们介绍,this指向问题规律的5条通用判断方法。

  ① 经过 函数名() 调用的,this永远指向window;
  ② 经过 对象.方法 调用的,this指向该对象;
  ③ 函数做为 数组 中的一个元素,用数组下标调用的,this指向该数组;
  ④ 函数做为Window内置函数的 回调函数 使用,this指向window;
    setInterval、 setTimeout
  ⑤ 函数做为构造函数,使用 new关键字 调用,this指向新new出的对象。

 

下面,将对每条规律,作出案例,以供你们,理解:

<div id="div1"style="width: 200px;height: 200px;background-color: red;">
            这是一个div
</div>

 

function func(){
            console.log(this);
        }
        var obj ={
            func : func
        }
        function func1(){
            func();        //this指向Window
        }
        //① 经过  函数名()  调用的,this永远指向window;
        func();            //this指向Window
//② 经过 对象.方法 调用的,this指向该对象; obj.func(); //this指向对象obj window.onclick = function(){ document.getElementById("div1").onclick = function(){ func(); // 最终仍是使用()调用,全部指向window } document.getElementById("div1").onclick = func;//广义对象,指向div1 } //③ 函数最为数组中的一个元素,用数组下标调用的,this指向该数组 var arr = [1,2,3,func,4,5]; arr[3](); //④ 函数做为Window内置函数的回调函数使用,this指向window; setTimeout(func,1000); //⑤ 函数做为构造函数,使用new关键字调用,this指向新new出的对象。 var obj1 = new func();

 

下面是一个影子总结的一个综合案例:

        /************************综合案例****************/
        var obj1 = {
            name : "obj1",
            arr : [func, 1,{name : "obj2",func : func},3,4],
        }
        obj1.arr[0]();                        //最终的调用者是数组,this指向数组
        setTimeout(obj1.arr[0],1000);        //obj1.arr[0仅仅是取到函数func,但并无调用。函数的最终调用者是setTimeout,指向window;这个式子至关于setTimeout(func,1000);
        setTimeout(obj1.arr[2].func,1000);    //函数的最终调用者是setTimeout.缘由同上↑
        obj1.arr[2].func();                    //最终的调用者是{name : obj2,func : func},this指向{name : obj2,func : func}
        

 

好了,今天影子给你们分享的东西就这么多了。最后,影子这里还有一道this指向的题,就一这道题结束今天的分享吧。至于答案就留到下次。哈哈。。。

var fullname = 'John Doe';
        var obj = {
           fullname: 'Colin Ihrig',
           prop: {
              fullname: 'Aurelio De Rosa',
              getFullname: function() {
                 return this.fullname;
              }
           }
        };
       console.log(obj.prop.getFullname());          //??
        var test = obj.prop.getFullname;
        console.log(test());  
        //??
        obj.func = obj.prop.getFullname;
        console.log(obj.func());             //???
        var arr = [obj.prop.getFullname,1,2];
        arr.fullname = "JiangHao";      
        console.log(arr[0]());              
        console.log(arr[0]);        //????         
相关文章
相关标签/搜索