面向对象编程

本文介绍了面向对象编程的基本概念,包括对象、面向对象特性、创建对象的方法(构造函数),区分实例成员和静态成员,以及如何通过原型链解决构造函数带来的内存问题。通过实例演示了原型对象和原型链的原理,并提供了更简洁的原型语法和内置构造函数的使用技巧。
摘要由CSDN通过智能技术生成


前言

这部分学习一下面向对象编程思想,面向对象编程会使编程更加高效。


面向对象概念

1.对象

在实际开发中,对象是一个抽象的概念,可以将其简单理解为:数据集或功能集。
ECMAScript-262把对象定义为:无序属性的集合,其属性可以包含基本值、对象或者函数。

2.面向对象

面向对象编程——0bject Oriented Programming,简称 0OP,是一种编程开发思想。
它将真实世界各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟。
面向对象特性:封装性、继承性、(多态性)抽象
面向对象优点:面向对象编程具有灵活、代码可复用、高度模块化等特点,容易维护和开发,比起由一系列函数或指令组成的传统的过程式编程,更适合多人合作的大型软件项目。
接下来两段代码初步体会一下,面向过程与面向对象的区别:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // //面向过程
        // var std1 = {name: "Bob",score: 96};
        // var std2 = {name: "Mike",score: 88};
        // //打印输出成绩
        // function printScore(student) {
        //     console.log("姓名:" + student.name + "成绩:" + student.score);
        // }
        // //调用函数
        // printScore(std1);
        // printScore(std2);

        //面向对象
        function Student(name,score) {
            this.name = name;
            this.score = score;
            this.printScore = function () {
                console.log("姓名:" + this.name + "成绩:" + this.score);
            };
        }
        //实例化
        var std1 = new Student("Bob",96);
        var std2 = new Student("Mike",88);
        //调用实例对象自己的方法
        std1.printScore();
        std2.printScore();
    </script>
</body>
</html>

3.创建对象的方法(构造函数)

(1)new Object构造函数
(2)对象字面量
(3)工厂函数
(4)自定义构造函数
这里重点讲解一下自定义构造函数:构造函数是根据具体的事物抽象出来的抽象模板,实例对象是根据抽象的构造函数模板得到的具体实例对象;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        //自定义构造函数
        function Person(name,age) {
            this.name = name;
            this.age = age;
            this.isName = function () {
                console.log(this.name);
            }
        }
        //对象实例化
        var per1 = new Person("gg",20);
        var per2 = new Person("ax",22);
        //调用方法
        per1.isName();
        per2.isName();
        //判断实例和构造函数之间的关系
        console.log(per1 instanceof Person);
    </script>
</body>
</html>

4.实例成员和静态成员

使用构造函数方法创建对象时,可以给构造函数和创建的实例对象添加属性和方法,这些属性和方法都叫做成员。
(1)实例成员:在构造函数内部添加给 this的成员,属于实例对象的成员,在创建实例对象后必须由对象调用。
(2)静态成员:添加给构造函数自身的成员,只能使用构造函数调用,不能使用生成的实例对象调用。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function Person(name,age) {
            //实例成员,只能通过后期添加的实例对象进行调用
            this.name = name;
            this.age = age;
            this.isName = function () {
                console.log(this.name);
            }
        }
        //静态成员,直接给构造函数添加的成员
        Person.version = "1.0";
        //对象实例化
        var per1 = new Person("gg",20);
        var per2 = new Person("ax",22);

        //实例成员调用,只能实例对象调用,函数本身不能调用
        console.log(per1.age);
        console.log(Person.name);
        //静态成员只能通过函数本身调用,不能通过实例对象调用
        console.log(Person.version);
        console.log(per1.version);
    </script>
</body>
</html>

5.构造函数的问题

构造函数,可能会存在内存浪费的情况,这个时候可以采取以下解决办法:
(1)将公共的函数提取到构造函数之外
(2)存在多个公共函数,可以将多个公共函数存入构造函数之外的一个对象中
(3)原型对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>

        // //解决方法1:将公共函数提取出来
        // function isName() {
        //     console.log(this.name);
        // }
        // function Person(name,age) {
        //     this.name = name;
        //     this.age = age;
        //     //多次创建,造成资源浪费
        //     this.isName = isName;
        // }
        // //对象实例化
        // var per1 = new Person("gg",20);
        // var per2 = new Person("ax",22);
        // per1.isName();

        //解决方法2:多个公共函数提取到一个对对象
        var fns = {
            isName: function () {
                console.log(this.name);
            },
            isAge: function () {
                console.log(this.age);
            },
        }
        
        function Person(name,age) {
            this.name = name;
            this.age = age;
            //多次创建,造成资源浪费
            this.isName = fns.isName;
            this.isAge = fns.isAge;
        }
        //对象实例化
        var per1 = new Person("gg",20);
        var per2 = new Person("ax",22);
        per1.isAge();
    </script>
</body>
</html>

原型对象
任何函数都具有一个 prototype属性,该属性是一个对象。可以在原型对象上添加属性和方法。
构造函数的prototype对象默认都有一个constructor属性,指向prototype对象所在函数。
通过构造函数得到的实例对象内部会包含一个指向构造函数的 prototype 对象的指针proto
实例对象可以直接访问原型对象成员。
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function Person(name,age) {
            this.name = name;
            this.age = age;
            this.isName = function () {
                console.log(this.name);
            };
        }
        //构造函数的原型对象
        console.log(Person.prototype);
        //可以给原型对象添加属性
        Person.prototype.type = "human";
        Person.prototype.sayHi = function () {
            console.log("hello");
        }
        //实例对象的构造函数的原型对象
        var p1 = new Person("gg",20);
        console.log(p1.__proto__);
    </script>
</body>
</html>

解决构造函数导致内存浪费的最佳方法:原型对象prototype

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function Person(name,age) {
            this.name = name;
            this.age = age;
        }
        //解决内存浪费的最佳方法
        Person.prototype.type = "human";
        Person.prototype.sayName = function () {
            console.log(this.name);
        };
        Person.prototype.sayAge = function () {
            console.log(this.age);
        };
        //对象实例化
        var per1 = new Person("gg",20);
        var per2 = new Person("ax",22);
        per1.sayAge();
    </script>
</body>
</html>

6.原型链

在这里插入图片描述
原型链的查找机制:
每当代码读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性:
1.搜索首先从对象实例本身开始
2.如果在实例中找到了具有给定名字的属性,则返回该属性的值
3.如果没有找到,则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性
4.如果在原型对象中找到了这个属性,则返回该属性的值

7.实例对象读取原型对象的成员

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function Person(name,age) {
            this.name = name;
            this.age = age;
        }
        Person.prototype.type = "human";
        Person.prototype.sayName = function () {
            console.log(this.name);
        };
        Person.prototype.address = {
            city: "北京"
        };
        //对象实例化
        var per1 = new Person("gg",20);

        //读取 属性和方法
        console.log(per1.name);
        console.log(per1.city);
        console.log(per1.sayAge);

        //通过实例对象添加新成员,给自己添加,屏蔽掉对原型对象的访问,不会给原型对象添加
        per1.sex = "male";

        //更改实例对象的成员,只会更改自己,会屏蔽掉对原型对象的访问,不会对原型对象进行更改
        per1.type = "person";
        console.dir(per1);

        //通过实例来更改原型对象中  复杂类型的数据 这时会更改原型对象中的值,而实例对象自身不会增加新成员。
        per1.address.city = "上海";
        console.dir(per1);
    </script>
</body>
</html>

8.更简单的原型语法

在进行定义构造函数时,可以通过成员的功能不同,而进行分别设置:
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function Person(name,age) {
            this.name = name;
            this.age = age;
        }
        //解决内存浪费的最佳方法
        // Person.prototype.type = "human";
        // Person.prototype.sayName = function () {
        //     console.log(this.name);
        // };
        // Person.prototype.sayAge = function () {
        //     console.log(this.age);
        // };

        //包含所有属性和方法的对象字面量 来重写原型对象 (不要忘记将constructor 指针重新指向构造函数)
        Person.prototype = {
            constructor: Person,
            type: "human",
            sayName: function () {
                console.log(this.name);
            }
        }
        //对象实例化
        var per1 = new Person("gg",20);
        per1.sayName();
    </script>
</body>
</html>

9.内置构造函数的原型对象

在这里插入图片描述
给内置对象添加新的方法,用数组举例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        //不能用字面量的方式给内置对象添加新成员
        //只能给内置对象添加一条新属性
        Array.prototype.getEvenSum = function () {
            //给数组计算偶数项 的和
            //先写一个累加器
            var sum = 0;
            for (var i = 0;i < this.length;i++) {
                if (i % 2 == 0) {
                    sum += this[i];
                }
            }
            return sum;
        };
        //定义一个数组
        var arr = [2,4,6,9,2,6];
        console.log(arr.getEvenSum());
        console.dir(Array.prototype);
    </script>
</body>
</html>

总结

这部分学习了面向对象编程思想,可以通过案例的练习,来锻炼自己的编程思想。每天坚持学习前端,加油~
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值