面向对象的三个特征

  JavaScript属于动态类型语言,所谓动态类型语言,就是只变量在运行使用到的时候,才会具有某种类型的语言。

  面向对象的三个基本特征:封装、继承、多态。下面我们来了解一下这三个特征。

  封装:封装的目的是隐藏信息,即不暴露函数中的属性和方法,让外界不能操作,但可以暴露接口给外界,外界只能通过暴露的接口来进行相关操作。下面这个栗子中,我们将会将变量封装到函数中,并对外暴露一个方法,以便于访问,不过这个栗子,我会用多种方式来实现,同样达到封装的目的,但是特性是不通的哦~

    //原始方法
    var myObj = (function() {
        var a = "a";
        return {
            getA: function() {
                return a;
            }
        }
    })();
    console.log(myObj.getA()); //a
    console.log(myObj.a); //undefined

    function A() {
        var b = 'b';
        this.getB = function() {
            return b;
        }
    };
    var B = new A();
    console.log(B.getB()); //b
    console.log(B.b); //undefined

    //对于有同样功能的函数,如果使用原始方法,需要多次创建,不利于代码的复用。
    //工厂加工方法
    function creatObj(name) {
        var name1 = "name1";
        var obj = new Object();
        obj.getName1 = function() {
            return name1;
        };
        obj.name2 = name;
        obj.getName2 = function() {
            return this.name2;
        };
        return obj;
    };
    var C = creatObj("jiangtengteng");
    console.log(C.getName1()); //name1
    console.log(C.name1); //undefined
    console.log(C.getName2()); //jiangtengteng
    console.log(C.name2); //jiangtengteng

    //工厂加工方法,可以复用功能了,但是这其实是对函数的引用,思想上和面向对象类的思想不符。
    //构造函数方法
    function creatObj(name) {
        var name1 = "name1";
        this.getName1 = function() {
            return name1;
        };
        this.name2 = name;
        this.getName2 = function() {
            return this.name2;
        };
    };
    var C = new creatObj("jiangtengteng");
    console.log(C.getName1()); //name1
    console.log(C.name1); //undefined
    console.log(C.getName2()); //jiangtengteng
    console.log(C.name2); //ujiangtengteng

    //此方法特性同工厂加工方法一致
    //原型方法
    function creatObj(){};
    creatObj.prototype.name = "Jhon";
    creatObj.prototype.array = ["11","22"];
    creatObj.prototype.getName = function(){
        return this.name;
    };
    creatObj.prototype.conArray = function(){
        return this.array;
    };
    var D = new creatObj();
    var E = new creatObj();
    console.log(D.getName());
    console.log(D.conArray());
    D.array.push('33'); 
    console.log(D.conArray());
    console.log(E.conArray());

    //此方法实例化的函数由于引用的是同一个对象,任何一个函数对对象做了修改,那其他实例化的函数也同样会收到影响
    //构造函数+原型方法
    function creatObj(name, age){
        this.name = name;
        this.age = age;
    };
    creatObj.prototype.getName = function(){
        return this.name;
    };
    creatObj.prototype.getAge = function(){
        return this.age;
    };
    var F = new creatObj("me","11");
    console.log(F.getName());
    console.log(F.getAge());

    //属性私有后,改变各自的属性不会影响别的对象。同时,方法也是由各个对象共享的。在语义上,这符合了面向对象编程的要求。

   从上面的例子里,我们可以看出,封装完成后,封装的内容可以是公开的,也可以是私有的,使用原型创建的方法是共享的,而函数里声明的变量则是私有的,如果我们希望某个属性或者方法可以共用,则最好使用原型方法添加函数。

  继承:主要是指属性的继承和方法的继承。我们可以将需要复用的方法和属性,定义在父类中,而子类在需要使用到相关的方法和属性时,直接从父类继承即可。

    //通过对象冒充来实现继承
    //顾客信息
    function Customer(name, phone) {
        this.name = name;
        this.phone = phone;
        this.show = function() {
            alert(this.name + ":" + this.phone);
        }
    };
    //普通顾客折扣
    function NormalCustomer(name, phone, price) {
        this.norCos = Customer;
        this.norCos(name, phone);
        this.price = price;
        this.discount = function() {
            alert("普通顾客:" + this.name + ",你打完9折的价格为:" + this.price * 0.9);
        }
    };
    var jhon = new NormalCustomer("Jhon", "", "100");
    jhon.discount();
    //vip顾客折扣
    function VipCustomer(name, phone) {
        this.vipCos = Customer;
        this.vipCos(name, phone);
        this.discount = function(price) {
            alert("VIP顾客:" + this.name + ",你打完6折的价格为:" + price * 0.6);
        }
    };
    var lucy = new VipCustomer("Lucy", "");
    lucy.discount("100");

  上面的示例是通过冒充对象来实现继承的,下面我们使用call或者apply来实现继承:

    //通过call或者apply实现继承
    //顾客信息
    function Customer(name, phone) {
        this.name = name;
        this.phone = phone;
        this.show = function() {
            alert(this.name + ":" + this.phone);
        }
    };
    //普通顾客折扣 call
    function NormalCustomer(name, phone) {
        Customer.call(this, name, phone);
        //如果用apply实现,则可以 
        //Customer.apply(this,[name, phone]); //说明传入的参数是 数组方式 
        this.discount = function(price) {
            alert("普通顾客:" + this.name + ",你打完8折的价格为:" + price * 0.8);
        };
    };
    var jhon = new NormalCustomer("Jhon", "");
    jhon.discount("100");
    //vip顾客折扣 apply
    function VipCustomer(name, phone) {
        //如果用call实现,则可以 
        // Customer.call(this, name, phone); 
        Customer.apply(this,[name, phone]); //说明传入的参数是 数组方式 
        this.discount = function(price) {
            alert("普通顾客:" + this.name + ",你打完5折的价格为:" + price * 0.5);
        };
    };
    var lucy = new VipCustomer("Lucy", "");
    lucy.discount("100");

  多态:即同一操作作用于不同的对象上面,可以产生不同的解释和不同的执行结果。比如说,朋友家养了一条狗和一只猫,当我朋友喂小动物们时,狗要吃骨头,而猫要吃鱼~。多态的宗旨是把不变的部分隔离开,把可变的部分封装起来,就是著名的开发-封闭原则啦~,来段代码理解下~

    //声明主人 主人有名字以及行为
    function Master(name) {
        this.name = name;
    };
    //给主人添加喂养动物的行为
    Master.prototype.feed = function(animal, food) {
        alert(animal.name + "要吃" + food.name);
    };
    //食物
    function Food(name) {
        this.name = name;
    };
    //动物
    function Animal(name) {
        this.name = name;
    };
    var cat = new Animal("猫");
    var fish = new Food("鱼");
    var dog = new Animal("狗");
    var bone = new Animal("骨头");
    var master = new Master("Kate");
    master.feed(cat, fish);
    master.feed(dog, bone);

 

posted @ 2018-09-18 11:07  姜腾腾  阅读(2253)  评论(0编辑  收藏  举报