zoukankan      html  css  js  c++  java
  • JavaScript面向对象(OOP)

    前 言

    JRedu

    ​ 面向对象程序设计(简称OOP)是现在最流行的程序设计方法,这种方法有别于基于过程的程序设计方法。在写面向对象的WEB应用程序方面JavaScript是一种很好的选择.它能支持OOP.因为它通过原型支持继承的方式和通过属性和方法的方式一样好.很多开发者试图抛弃JS,试着用C#或JAVA仅是因为JS不是他认为合适的面向对象的语言.许多人还没有认识到javascript支持继承.当你写面向对象的代码时.它能给你很强大的能量.你也可以使用它写出可复用,可封装的代码.

    一、什么是面向对象编程(OOP)?

    ​ 在了解什么是面向对象编程之前,我们来看看语言的分类。总体可以分为三类:面向机器面向过程还有面向对象。面向对象的语言主要有C++、Java、PHP等。

    1面向过程与面向对象

    1)面向过程:面向过程专注于如何去解决一个问题的过程步骤。编程特点是由一个个函数去实现每一步的过程步骤,没有类和对象的概念。
    2)面向对象:专注于由哪一个对象来解决这个问题,编程特点是出现了一个类,从类中拿到对象,由这个对象去解决具体问题。
    对于调用者来说,面向过程需要调用者自己去实现各种函数。而面向对象,只需要告诉调用者,对象中具体方法的功能,而不需要调用者了解方法中的实现细节。

    2面向对象的三大特征

    这个对于计算机专业的人来说,相信大家已经很熟悉啦,那我就再说一遍吧~

    面向对象的三大特征是继承、封装、多态。JS可以模拟实现继承和封装,但是无法模拟实现多态,所以我们说JS是一门基于对象的语言,而非是面向对象的语言。

    3类和对象

    1、类:一类具有相同特征(属性)和行为(方法)的集合。
    比如,人类具有身高、体重等属性,吃饭、大笑等行为,所以,我们可以把人划分为一类。

    2、对象:从类中,拿出具有确定属性值和方法的个体。
    比如,张三-->属性:身高180体重180 方法:说话-->我叫张三,身高180

    3、类和对象的关系:
    ①类是抽象的,对象是具体的(类是对象的抽象化,对象是类的具体化)

    ②类是一个抽象的概念,只能说类有属性和方法,但是不能给属性赋具体的。比如,人类有姓名,但是不能说人类的姓名叫什么。
    对象是一个具体的个例,是将类中的属性进行具体赋值而来的个体。
    比如,张三是一个人类的个体。可以说张三的姓名叫张三。也就是张三对人类的每一个属性进行了具体的赋值,那么张三就是由人类产生的一个对象。

    4、使用类和对象的步骤:

    1)创建一个类(构造函数):类名必须使用大驼峰法则。即每个单词首字母都要大写

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

    2)通过类实例化(new)出一个对象。

    var obj=new 类名(属性1的具体值);
    obj.属性; 调用属性
    obj.方法; 调用方法
    

    3)注意事项
    ①通过类名,new出一个对象的过程,叫做"类的实例化"。
    ②类中的this,会在实例化的时候,指向新new出的对象。
    所以,this.属性 this.方法实际上是将属性和方法绑定在即将new出的对象上面。
    ③在类中,要调用自身属性,必须使用this.属性名。如果直接使用变量名,则无法访问对应的属性。

    function Person(name,age){
       this.name=name;
       this.age=age;
       this.say=function(content){
           //在类中,访问类自身的属性,必须使用this.属性调用。
           alert("我叫"+this.name+",今年"+this.age+"岁,我说了一句话:"+content);
       }
    }
    var zhangsan=new Person("姐姐",18);
    zhangsan.say("你好呀");
    

    ④类名必须使用大驼峰法则,注意与普通函数区分。

    4面向对象的两个重要属性

    1)constructor:返回当前对象的构造函数。
    >>>zhangsan.constructor==Person; ( true)
    2)instanceof:检测一个对象是不是一个类的实例;
    >>>lisi instanceof Person √ lisi是通过Person类new出的
    >>>lisi instanceof Object √ 所有对象都是Object的实例
    >>>Person instanceof Object √ 函数本身也是对象

    5广义对象与狭义对象

    1)狭义对象:只有属性和方法,除此之外没有任何其他内容。

    var obj={};  //用{}声明的对象
    var obj=new Object(); //用new声明的对象
    

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

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

    二、 成员属性、静态属性和私有属性

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

    【静态属性与静态方法】
    2、通过“类名.属性名”、“类名.方法名”声明的属性和方法,称为静态属性静态方法。也叫类属性和类方法。
    类属性/类方法,是属于类的(属于构造函数的)
    通过"类名.属性名"调用。

    3、成员属性是属于实例化出的对象的,只能使用对象调用。
    静态属性是属于构造函数的,只能使用类名调用。

    [私有属性和私有方法]
    4、在构造函数中,使用var声明的变量称为私有属性;
    在构造函数中,使用function声明的函数,称为私有方法;

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

    私有属性和私有方法的作用域,只在构造函数内容有效。即只能在构造函数内部使用,在构造函数外部,无论使用对象名还是类名都无法调用。

    function Person(name){
        this.name=name; //声明成员属性
        var sex="男";//私有属性
                    
    }
                
    var zhangsan=new Person("张三");
    zhangsan.age=14; //追加成员属性
    alert(zhangsan.name); //调用成员属性
                
    Person.count="60亿"; //声明静态属性
    alert(Person.count); //调用静态属性
    var lisi=new Person("李四");console.log(lisi.count); //undefined 静态属性是属于类的,只能用类名调用。
    

    三、 JavaScript模拟实现封装

    1、什么叫封装?
    ①方法的封装:将类内部的函数进行私有化处理,不对外提供接口,无法在类外部使用的方法,称为私有方法,即方法的封装。
    ②属性的封装:将类中的属性进行私有化处理,对外不能直接使用对象名访问(私有属性)。同时,需要提供专门用于设置和读取私有属性的set/get方法,让外部使用我们提供的方法,对属性进行操作。这就叫属性的封装。
    2、注意:封装不是拒绝访问,而是限制访问。要求调用者,必须使用我们提供的set/get方法进行属性的操作,而不是直接拒绝操作。
    因此,单纯的属性私有化,不能称为封装!必须要有私有化后,提供对应的set/get方法。

    function Person(name,age1){
        this.name=name;//  this.age=age;
        var age=0;
                     
        this.setAge=function(ages){
            if(ages>0&&ages<=120){
                age=ages;
            }else{
                alert("年龄赋值失败");
            }
        }
    // 当实例化类拿到对象时,可以直接通过类名的()传入年龄,设置私有属性
       if(age1!=undefined) this.setAge(age1);
       this.getAge=function(){
           return age;
       }
       this.sayTime=function(){
           alert("我说当前时间是:"+getTime());
       }
       this.writeTime=function(){
           alert("我写了当前时间是:"+getTime());
       }
                    /*私有化的方法,只能在类内部被其他方法调用,而不能对外提供功能。这就是方法的封装*/
       function getTime(){
           return new Date();
       }
    }
                
    var zhangsan=new Person("张三",99);
    zhangsan.setAge(99);
    alert("张三的年龄是"+zhangsan.getAge());
                
    var lisi=new Person("李四",99);
    lisi.setAge(110);
    alert("李四的年龄是:"+lisi.getAge());
    

    四、JavaScript中的this指向详解

    1、谁最终调用函数,this最终指向谁(记住!)
    ①this指向谁,不应考虑函数在哪声明,而应该考虑函数在哪调用!!!
    ②this指向的永远只可能是对象,而不可能是函数。
    ③this指向的对象,叫做函数的上下文context,也叫函数的调用者。

    2、this指向的规律!!!(跟函数的调用方式息息相关,记住这点,相信你一定会分清this指向哒)
    ①通过函数名()调用的,this永远指向window
    ②通过对象.方法调用的,this指向这个对象。
    ③函数作为数组中的一个元素,用数组下标调用的,this指向这个数组
    ④函数作为window内置函数的回调函数使用,this指向window。
    setInterval setTimeout 等。
    ⑤函数作为构造函数,使用new关键字调用,this指向新new出的对象。

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

    现在,你一定分清了this指向了吧,下面我们来看一个综合案例:

    var obj1={
        name:"obj1",
        arr:[func,1,{name:"obj2",func:func},3,4],
    }
    obj1.arr[0]();//最终的调用者是数组。this-->obj.arr
    setTimeout(obj1,arr[0],2000);//obj.arr[0]仅仅是取到函数赋给setTimeout,但并没有调用。函数的最终调用者是setTimeout。这个式子相当于setTimeout(func,2000);
    obj1.arr[2].func();//最终调用者是{name:"obj2",func:func}
    setTimeout(obj1.arr[2].func,2000);//最终调用者是setTimeout
                
    //↓最终的调用者是div1//document.getElementById("div1").onclick=obj1.arr[0];
    //document.getElementById("div1").onclick=arr[2].func;
    

    最后,我们再来看一道面试题:

    var fullname = 'John Doe';
    var obj = {
       fullname: 'Colin Ihrig',
       prop: {
          fullname: 'Aurelio De Rosa',
          getFullname: function() {
             return this.fullname;
          }
       }
    };
    console.log(obj.prop.getFullname()); 
    // 函数的最终调用者 obj.prop 
                
    var test = obj.prop.getFullname;
    console.log(test());  
    // 函数的最终调用者 test()  this-> window
                
    obj.func = obj.prop.getFullname;
    console.log(obj.func()); 
    // 函数最终调用者是obj
                
    var arr = [obj.prop.getFullname,1,2];
    arr.fullname = "JiangHao";
    console.log(arr[0]());// 函数最终调用者数组
    
  • 相关阅读:
    ORA-04013,CACHE 值必须小于CYCLE值;解决方案
    .net 调用WCF服务接收数据对象属性为空
    各JAVA JDK版本下载地址
    记录一次基于Echart的数据可视化平台开发
    Swiper轮播使用记录--一个页面有多个DIV区域使用swiper进行轮播
    Echart使用记录-动态设置series的时候,设置了color属性,但所有的柱状图显示灰白色
    记录一次SignalR服务的搭建注意事项
    C#关于ListBox绑定list,不会刷新数据的问题
    关于bootstrap-fileinput上传后删除选中上传的文件,回到最初的选择文件界面
    Oracle 数据库 alert日志及trace日志的清理
  • 原文地址:https://www.cnblogs.com/AaronNotes/p/14551300.html
Copyright © 2011-2022 走看看