JS中的面向对象

目录

一、创建对象

1. 工厂模式

2. 构造函数模式 

3. 原型模式

4. 混合模式 

二、继承 

1. 原型链继承

2. 构造函数继承

3. 组合继承


一、创建对象

1. 工厂模式

<script>
    // 定义Person类
    var Person = function(name, hobby) {
        var o = new Object();
        o.name = name;
        o.hobby = hobby;
        o.talk = function() {
           console.log("my name is " + this.name);
        }
            
        return o;
    }
        
    var xiaoming = Person("xiaoming", "swimming");
    console.log(xiaoming);  //{name: "xiaoming", hobby: "swimming", talk: ƒ}  
    xiaoming.talk();  //my name is xiaoming
    var xiaohong = Person("xiaohong", "run");
    console.log(xiaohong);  //{name: "xiaohong", hobby: "run", talk: ƒ}
    xiaohong.talk();  //my name is xiaohong

    // 缺点: 1.无法识别对象的类型; 
    // 2. xiaoming和xiaohong的talk方法 虽然同名但是不相等
    console.log(xiaoming.talk == xiaohong.talk);    //false
</script>

2. 构造函数模式 

<script>
    //申明构造函数
    function Person(name, hobby) {
        this.name = name;
        this.hobby = hobby;
        this.talk = function() {
            console.log("my name is " + name);
        }
    }

    // 实例化对象
    var xiaoming = new Person("xiaoming", "swimming");
    console.log(xiaoming);  //Person {name: "xiaoming", hobby: "swimming", talk: ƒ}
    xiaoming.talk(); //my name is xiaoming
    var xiaohong = new Person("xiaohong", "run");
    console.log(xiaohong); //Person {name: "xiaohong", hobby: "run", talk: ƒ}
    xiaohong.talk(); //my name is xiaohong


    //可以使用 instanceof 方法检测是否为该对象类型
    console.log(xiaoming instanceof Person); //true
    console.log(xiaoming instanceof Object); //true
    console.log(xiaohong instanceof Person); //true
    console.log(xiaohong instanceof Object); //true
    
    console.log("缺点: xiaoming和xiaohong的talk方法 虽然同名但是不相等");
    console.log(xiaoming.talk == xiaohong.talk);
</script>

3. 原型模式

<script>
    //申明Person函数
    var Person = function() {};

    Person.prototype.name = "default name";
    Person.prototype.hobby = ["swimming", "run"];
    Person.prototype.talk = function() {
        console.log("my name is " + this.name);
    }

    var xiaoming = new Person();
    console.log(xiaoming); //Person {}
    xiaoming.talk(); //my name is default name
    var xiaohong = new Person();
    console.log(xiaohong); //Person {}
    xiaohong.talk(); //my name is default name

    // 优点: 可以使用 instanceof 方法检测是否为该对象类型
    console.log(xiaoming instanceof Person); //true
    console.log(xiaoming instanceof Object); //true
    console.log(xiaohong instanceof Person); //true
    console.log(xiaohong instanceof Object); //true
    
    // 优点: xiaoming和xiaohong的talk方法 同名且相等
    console.log(xiaoming.talk == xiaohong.talk);

    // 缺点: 当数据为引用类型时, 所有实例会公用一个数据,如下
    xiaoming.hobby.push("code");
    console.log(xiaoming.hobby); // ["swimming", "run", "code"]
    //似乎没什么问题
    //我们再来看看小红的
    console.log(xiaohong.hobby); // ["swimming", "run", "code"]
    //小红的hobby也被加上了数据

    // js的数据分为两种类型,基础类型和引用类型
    // 基础类型为String, Number, Boolean, null, underfined, Symbol
    // 引用类型为Object, Array, Date, RegExp, Function 
</script>

4. 混合模式 

<script>
    //申明构造函数
    var Person = function(name, hobby) {
        this.name = name;
        this.hobby = hobby;
    }

    Person.prototype.talk = function() {
        console.log("my name is " + this.name);
    }

    // 实例化对象
    var xiaoming = new Person("xiaoming", ["swimming"]);
    console.log(xiaoming); //Person {name: "xiaoming", hobby: Array(1)}
    xiaoming.talk(); //my name is xiaoming
    var xiaohong = new Person("xiaohong", ["run"]);
    console.log(xiaohong); //Person {name: "xiaohong", hobby: Array(1)}
    xiaohong.talk(); //my name is xiaohong

    // 判断对象类型
    console.log("可以使用 instanceof 方法检测是否为该对象类型");
    console.log(xiaoming instanceof Person); //true
    console.log(xiaoming instanceof Object); //true
    console.log(xiaohong instanceof Person); //true
    console.log(xiaohong instanceof Object); //true
    

    console.log("优点: xiaoming和xiaohong的talk方法 同名且相等");
    console.log(xiaoming.talk == xiaohong.talk);
    console.log("优点: 当数据为引用类型时, 所有实例 不会 公用一个数据,如下")
    xiaoming.hobby.push("code");
    console.log(xiaoming.hobby); //["swimming", "code"]
    //似乎没什么问题
    console.log(xiaohong.hobby); //["run"]
    //小红的hobby也正确
</script>

这种构造函数与原型混成的模式,是目前在ECMAScript中使用最广泛、认同度最高的一种创建自定义类型的方法。可以说,这是用来定义引用类型的一种默认模式。

——《JavaScript高级程序设计(第3版)》

二、继承 

1. 原型链继承

<script>
    // 子构造函数.prototype = new 父构造函数();
    function Person() {
        this.name = "default name";
        this.hobby = ["swim"];
        this.talk = function() {
            console.log("my name is " +  this.name);
        }
    }
    
    function Student(name) {
        this.name = name;
        this.grade = "high"
    }

    Student.prototype = new Person();

    var xiaoming = new Student("xiaoming");
    console.log(xiaoming); //Student {name: "xiaoming", grade: "high"}
    xiaoming.talk(); //my name is xiaoming

    var xiaohong = new Student("xiaohong");
    console.log(xiaohong); //Student {name: "xiaohong", grade: "high"}
    xiaohong.talk(); //my name is xiaohong

    // 缺点: Parent的引用属性会被所有Child实例共享
    xiaoming.hobby.push("run");
    console.log(xiaoming.hobby); //["swim", "run"]
    console.log(xiaohong.hobby); //["swim", "run"]

    // 缺点: 无法向父级传递参数
</script>

2. 构造函数继承

<script>
    // 父构造函数().call(this);
    function Person(name) {
        this.name = name;
        this.hobby = ["swim"];
        this.talk = function() {
            console.log("my name is " +  this.name);
        }
    }
    
    Person.prototype.age = 18;

    function Student(name) {
        Person.call(this, name);
        this.grade = "high";
    }

    var xiaoming = new Student("xiaoming");
    console.log(xiaoming); //Student {name: "xiaoming", hobby: Array(1), grade: "high", talk: ƒ}
    xiaoming.talk(); //my name is xiaoming

    var xiaohong = new Student("xiaohong");
    console.log(xiaohong); //Student {name: "xiaohong", hobby: Array(1), grade: "high", talk: ƒ}
    xiaohong.talk(); //my name is xiaohong

    // 优点: Parent的引用属性不会被所有Child实例共享
    xiaoming.hobby.push("run");
    console.log(xiaoming.hobby); //["swim", "run"]
    console.log(xiaohong.hobby); //["swim"]

    // 缺点: 没有实现函数复用,Parent构造函数中的方法会在每个Child中复制一份,浪费内存
    console.log(xiaoming.talk == xiaohong.talk); //false

    // 缺点: Person原型对象上的方法不会被Child继承
    console.log(xiaoming.age); //undefined
    console.log(xiaohong.age); //undefined
</script>

3. 组合继承

<script>
    // 属性使用构造函数继承,方法使用原型继承
    function Person(name) {
        this.name = name;
        this.hobby = ["swim"];
    }
    
    Person.prototype.talk = function() {
        console.log("my name is " + this.name);
    }

    function Student(name) {
        Person.call(this, name);
        this.school = "high"
    }

    Student.prototype = new Person();

    var xiaoming = new Student("xiaoming");
    console.log(xiaoming); // Student {name: "xiaoming", hobby: Array(1), school: "high"}
    xiaoming.talk(); //my name is xiaoming

    var xiaohong = new Student("xiaohong");
    console.log(xiaohong); //Student {name: "xiaohong", hobby: Array(1), school: "high"}
    xiaohong.talk(); //my name is xiaohong

    // 优点: 实现函数复用
    console.log(xiaoming.talk == xiaohong.talk); //true

    // 优点: Parent的引用属性不会被所有Child实例共享
    xiaoming.hobby.push("run");
    console.log(xiaoming.hobby); //["swim", "run"]
    console.log(xiaohong.hobby); //["swim"]

    //PS: 此时Child的constructor指向Parent,需要自己重新指向
    console.log(Student.prototype.constructor); //ƒ Person(name) {this.name = name;this.hobby = ["swim"];}
    Student.prototype.constructor = Student;
    console.log(Student.prototype.constructor); //ƒ Student(name) {Person.call(this, name);this.school = "high"}
</script>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值