zoukankan      html  css  js  c++  java
  • javascript面向对象编程

    1.封装

    // 面向对象编程-类的封装
    // 类中的属性和方法:
    //      私有属性
    //      私有方法
    //      公有属性
    //      特权方法
    //      原型属性(位于原型中)
    //      公有方法(位于原型中)
    
    // 寄生组合式继承
    // 父类
    function Person(name, age) {
        // 公有属性
        this.name = name;
        this.age = age;
    
        // 特权方法
        // 特权方法可以访问私有属性、私有方法、特权属性、特权方法
        // 特权方法不能放在prototype内,因此无法复用
    
        // 访问私有属性sexOrientation的特权方法
        this.getSexOrientation = function () {
            return sexOrientation;
        };
    
        // 访问私有方法setSexOrientation的特权方法
        this.admittedByBUPT = function () {
            console.log("I'm admitted by BUPT!");
            setSexOrientation('同性恋');
        };
    
        // 私有属性
        var sexOrientation = '异性恋';
    
        // 私有方法
        // 私有方法可以访问私有属性(闭包)、私有方法(闭包)
        // 因为在私有方法中this指向的是全局对象window(不信可以打印this看一下),所以无法通过this访问到公有属性和特权方法
        var setSexOrientation = function (sex) {
            sexOrientation = sex;
            // console.log(this);
        };
    }
    
    // 原型属性
    Person.prototype.className = 'Person';
    
    // 原型方法
    // 原型方法可以访问原型属性、原型方法、公有属性、特权方法,但不可以访问私有属性和私有方法
    Person.prototype.getName = function () {
        return this.name;
    };
    Person.prototype.getAge = function () {
        return this.age;
    };
    
    // 静态属性
    Person.country = 'Chinese';
    // 静态方法
    Person.setCountry = function (country) {
        this.country = country;
    };
    Person.getCountry = function () {
        return this.country;
    };
    
    // 寄生组合式继承
    // 继承公有属性、特权方法、原型属性、公有方法
    // 本写法是纯净的组合式继承
    // 组合式继承指的是“原型链继承”+“构造函数式继承”
    function Teacher(name, age, school) {
        // 构造函数式继承
        Person.call(this, name, age);
    
        // 子类新增公有属性
        this.school = school;
    }
    
    // 子类新增公有方法
    Teacher.prototype.getSchool = function () {
        return this.school
    };
    
    // 实现继承
    // 可以将这段实现继承的代码封装成一个inherit函数
    var F = function () {};
    F.prototype = Person.prototype;
    var o = new F();
    o.constructor = Teacher;
    Teacher.prototype = o;

    2.原型链继承

    // 原型链继承
    // 父类
    function Person(name,age) {
        this.name = name;
        this.age = age;
    }
    
    Person.prototype.getName = function () {
        return this.name;
    }
    Person.prototype.getAge = function () {
        return this.age;
    }
    
    // 子类
    function Teacher(school) {
        this.school = school;
    }
    
    // 注意
    // 创建继承关系时无法向父类传递参数(因为传什么参数都会被所有子类实例共享,因此最好不传递任何参数),因此无法对父类中的属性进行实例化
    // 这是原型链继承的第一个缺点
    Teacher.prototype = new Person();
    Teacher.prototype.getSchool = function () {
        return this.school;
    }
    
    var t1 = new Teacher('BUPT');
    var t2 = new Teacher('BUPT');
    
    console.log(t1 instanceof Teacher);
    console.log(t1 instanceof Person);
    
    console.log(t2 instanceof Teacher);
    console.log(t2 instanceof Person);
    
    console.log(Teacher.prototype.isPrototypeOf(t1));
    console.log(Person.prototype.isPrototypeOf(t1));
    
    console.log(Teacher.prototype.isPrototypeOf(t2));
    console.log(Person.prototype.isPrototypeOf(t2));
    
    console.log(t1.getSchool());
    console.log(t1.getName());
    console.log(t1.getAge());
    
    
    console.log(t2.getSchool());
    console.log(t2.getName());
    console.log(t2.getAge());
    
    t1.school = 'BNU';
    
    // 注意
    // 如果采用第一种设置属性的方式,那么在对象t1和其__proto__里面有相同的两份属性,只不过属性值不一样
    // 如果采用第二种设置属性的方式,那么很显然,对象t2也将获得与对象t1相同的属性值
    // 这是原型链继承的第2个缺点
    
    // 第一种
    // t1.name = 'Tom';
    // t1.age = 20;
    
    // 第二种
    t1.__proto__.name = 'Tom';
    t1.__proto__.age = 20;
    
    console.log(t1.getSchool());
    console.log(t1.getName());
    console.log(t1.getAge());
    
    
    console.log(t2.getSchool());
    console.log(t2.getName());
    console.log(t2.getAge());

    3.构造函数式继承

    // 构造函数式继承
    // 父类
    function Person(name,age) {
        this.name = name;
        this.age = age;
    }
    
    Person.prototype.getName = function () {
        return this.name;
    }
    Person.prototype.getAge = function () {
        return this.age;
    }
    
    // 子类
    function Teacher(name, age, school) {
        Person.apply(this, arguments);
        this.school = school;
    }
    
    Teacher.prototype.getSchool = function () {
        return this.school;
    }
    
    var t1 = new Teacher('Tom', 20, 'BUPT');
    var t2 = new Teacher('Joy', 18, 'BNU');
    
    console.log(t1 instanceof Teacher);
    console.log(t1 instanceof Person);// false
    
    console.log(t2 instanceof Teacher);
    console.log(t2 instanceof Person);// false
    
    console.log(Teacher.prototype.isPrototypeOf(t1));
    console.log(Person.prototype.isPrototypeOf(t1));
    
    console.log(Teacher.prototype.isPrototypeOf(t2));
    console.log(Person.prototype.isPrototypeOf(t2));
    
    // 注意
    // 由于这种构造函数式继承没有涉及到父类的原型,因此子类实例无法访问父类prototype中定义的属性和方法
    // 这是构造函数式继承的明显缺点
    
    // console.log(t1.getName());
    console.log(t1.name);
    console.log(t1.getSchool());
    
    // console.log(t2.getName())
    console.log(t2.name);
    console.log(t2.getSchool());

    4.组合式继承:原型链继承+构造函数式继承

    // 原型链继承+构造函数式继承=组合式继承
    // 父类
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    
    Person.prototype.getName = function () {
        return this.name;
    }
    
    Person.prototype.getAge = function () {
        return this.age;
    }
    
    // 子类
    function Teacher(name, age, school) {
        // 构造函数式继承
        Person.apply(this, arguments);
        this.school = school;
    }
    
    // 原型链继承
    Teacher.prototype = new Person();
    Teacher.prototype.getSchool = function () {
        return this.school;
    }
    
    var t1 = new Teacher('Tom', 20, 'BUPT');
    var t2 = new Teacher('Joy', 18, 'BNU');
    
    console.log(t1 instanceof Teacher);
    console.log(t1 instanceof Person);
    
    console.log(t2 instanceof Teacher);
    console.log(t2 instanceof Person);
    
    console.log(Teacher.prototype.isPrototypeOf(t1));
    console.log(Person.prototype.isPrototypeOf(t1));
    
    console.log(Teacher.prototype.isPrototypeOf(t2));
    console.log(Person.prototype.isPrototypeOf(t2));
    
    console.log(t1.getName());
    console.log(t1.name);
    console.log(t1.getSchool());
    
    console.log(t2.getName())
    console.log(t2.name);
    console.log(t2.getSchool());
    
    // 注意
    // 这种组合式继承将父类构造函数执行了(n+1)遍,n为实例化的对象个数。
    // 如果n远大于1的话倒是没什么问题,但是如果n比较小(一般情况应该也不会很大吧),比如n=1,即只实例化一次,那么这一次额外的父类构造函数调用(添加原型时的那次调用)将不能忽略。
    // 并且,这次构造函数的调用将在子类的原型添加父类的属性,可以通过下面查看__proto__来看到。
    // 因此这种继承方式存在两个缺点:多调用一次父类构造函数造成额外开销,继承冗余不纯净。
    console.log(t1.__proto__);
    console.log(t2.__proto__);

    5.寄生组合式继承

      请移步1封装。

  • 相关阅读:
    消息中间件与kafka(二)
    维度建模基本概念(二)
    阿里开源canal
    ETL-kettle报错--org.gjt.mm.mysql.Driver
    消息中间件与rabbitmq(一)
    python装饰器--这个很pythonic
    Swift开发小技巧--识别选中照片中的二维码
    Swift开发小技巧--扫描二维码,二维码的描边与锁定,设置扫描范围,二维码的生成(高清,无码,你懂得!)
    Swift开发小技巧--自定义转场动画
    Swift基础--通知,代理和block的使用抉择以及Swift中的代理
  • 原文地址:https://www.cnblogs.com/iamswf/p/5229093.html
Copyright © 2011-2022 走看看