JS三大特性

抽象

在分析三大特性之前我们要先了解什么叫抽象。

定义:

在定义一个类的时候,实际上就是把一类事物的共有的属性和行为提取出来,形成一个物理模型(模板),这种研究问题的方法就称为抽象

一、封装

定义:

就是把抽象出来的属性和对属性的操作封装在一起,属性被保护在内部,程序的其他部分只能通过特定的操作(函数),才能对属性进行操作。

公开属性和私有属性

<script>

    function Person(in_name, in_age, in_sql) {
        this.name = in_name;
        var age = in_age;
        var sql = in_sql;
    }

    var p1 = new Person("haha", 20, 1000)
    alert(p1.name)

</script>

结果:

image

但是此时我们访问,age和sql:

<script>

    function Person(in_name, in_age, in_sql) {
        this.name = in_name;
        var age = in_age;
        var sql = in_sql;
    }

    var p1 = new Person("haha", 20, 1000)
    alert(p1.age)

</script>

结果:

image

说明:

这里我们就看到了name是公开属性,而age和sql则是私有属性

问题:属性有公开属性和私有属性,那方法有没私有和公开之分那?

类中的公开方法有个别名特权方法,私有方法有个别名内部方法

公开方法

<script>

        function Person(in_name, in_age, in_sql) {
            this.name = in_name;  // 公开属性
            var age = in_age;  // 私有属性
            var sql = in_sql;  // 私有属性

            // 在类中如何定义公开方法(特权方法);私有方法(内部方法)
            // 如果我们希望操作私有的属性,则可用公开方法实现
            this.show = function () {
                alert(age + "" + sql)
            }
        }

        var p1 = new Person("haha", 20, 1000)
        p1.show();

    </script>
公开方法

结果:

image

说明:

外部要想操作私有属性,可以通过公开方法来实现

私有方法

<script>

        function Person(in_name, in_age, in_sql) {
            this.name = in_name;  // 公开属性
            var age = in_age;  // 私有属性
            var sql = in_sql;  // 私有属性

            // 私有方法
            function show2() {
                alert(age + ' ' + sql)
            }

        }

        var p1 = new Person("haha", 20, 1000)
        p1.show2();  // 这样调用会报错!

    </script>
私有方法

说明:

私有方法同样可以使用同 中的私有属性,但是私有方法在外部却无法被操作。

 

上面的方法,在每次实例化对象的时候,会为每个对象生成一次,即每个对象中都有一个类似的方法,在一定程度上会造成资源浪费。

原型对象 prototype

因此我们想到 原型对象(prototype) 的基础上添加方法,间接的效果也让让每个对象也具有这个方法,这样操作只让方法在类中存一份,不会在每个对象中储存。

但是这个样处理,也有小问题;即不能调用私有变量和私有方法。

定义的方法操作公有属性:

<script>

        function Person() {
            this.name = "abc";
            var age = 90;
        }

        Person.prototype.fun1 = function() {
            alert(this.name);
        }

        var p1 = new Person();
        p1.fun1();  // 结果:弹出abc

    </script>
公有属性

定义的方法操作私有属性:

<script>

        function Person() {
            this.name = "abc";
            var age = 90;
        }

        Person.prototype.fun1 = function() {
            alert(age);
        }

        var p1 = new Person();
        p1.fun1();  // 结果:报错 age is not defined(…)

    </script>
私有属性

操作私有方法和公有方法:

<script>

        function Person() {
            this.name = "abc";  // 公有属性
            var age = 90;  // 私有属性
            // 共有方法
            this.show1 = function() {
                alert("haha")
            }
            // 私有方法
            function show2() {
                alert("xxx")
            }
        }

        Person.prototype.fun1 = function() {
            this.show1();  // 正确

            show2();  // 报错
        }

        var p1 = new Person();
        p1.fun1();

    </script>
操作方法

二、继承

问题:为什么需要继承?

最直接的回答,解决代码冗余。

 

需求:学生交学费,中学生打8折;小学生打5折,然后通过打印的方法,显示学生的名字、年龄记应缴学费。

我们初步的代码:

<script>
        // 中学生
        function MidStu(name,age) {
            this.name = name;
            this.age = age;
            this.show = function() {
                alert(this.name + ' ' + this.age);
            }

            // 计算学费
            this.payFee = function(mon) {
                alert("应缴" + mon*0.8);
            }
        }

        // 小学生
        function PupStu(name,age) {
            this.name = name;
            this.age = age;
            this.show = function() {
                alert(this.name + ' ' + this.age);
            }

            // 计算学费
            this.payFee = function(mon) {
                alert("应缴" + mon*0.5);
            }
        }

    </script>

可以看出两个类型学生代码中有很多相同的代码,出现了代码冗余的问题。

问题:怎么解决上面的代码冗余?

抽象出一个学生类(即,把两类学生共性取出来形成的类);然后通过继承的方式处理。

<script>
        // 抽象出两类学生共性的类
        function Stu(name, age) {
            this.name = name;
            this.age = age;
            this.show = function() {
                alert(this.name + ' ' + this.age);
            }
        }

        // 中学生
        function MidStu(name,age) {
            // js实际上是通过对象冒充来实现继承的。
            this.stu = Stu;
            this.stu(name, age);  // 这段代码很重要,如果没有它则继承就失败了

            // 计算学费
            this.payFee = function(mon) {
                alert("应缴" + mon*0.8);
            }
        }

        // 小学生
        function PupStu(name,age) {
            this.stu = Stu;
            this.stu(name, age);

            // 计算学费
            this.payFee = function(mon) {
                alert("应缴" + mon*0.5);
            }
        }

        // 测试继承
        var midStu = new MidStu("haha", 30);
        midStu.show();

    </script>
继承

结果:

image

结果我们发现,我们的MidStu中并没show方法,但是我们结果却能调用。

说明:

js的继承实际上是通过对象冒充来实现的。

js对象继承的关键点:

  • this.stu = Stu;这里相当于将整个Stu函数赋值给stu;赋值的是内存中的索引。此时如果alert(this.stu)的话;会将Stu的整个函数打印出来
  • image

 

  • this.stu(‘xxx’, 20):这段代码相当重要,关乎继承能否成功,前面我们知道,第一步只是接收了Stu的内存中的索引,这步的执行,就相当于将Stu的属性和方法,具体的赋给MidStu。

总结:

1、这里体现了js是动态语言的特性,在执行的过程中开辟内存空间。

2、js的继承是通过对象冒充来完成的。

3、js可以实现多重继承,虽然很少用,但是它具备这个功能。

4、Object类是js所有类的基类。

多态

定义:

指一个引用(类型)在不同情况下的多种状态。

js实际上是舞台的,是一种动态语言,一个变量的类型是在运行的过程中有js引擎来决定的,所以,也可以说js天生就支持多态。

典型案例:

<script>

        function Person() {
            this.test = function() {
                alert("Person");
            }
        }

        function Dog() {
            this.test = function() {
                alert("Dog");
            }
        }

        var v = new Person();
        alert(v.constructor);

        v = new Dog();
        alert(v.constructor);

    </script>
多态

通过打印对象的构造函数来判断对象的类型。v会随着对象的创建,而变化类型。

 

posted on 2016-12-25 14:08  jayafs  阅读(12486)  评论(0编辑  收藏  举报

导航