美文网首页
初识面向对象

初识面向对象

作者: Simon海明月 | 来源:发表于2017-12-26 21:12 被阅读0次

    日期:2017-12-26 by:simoon

    javaScript中一切都是对象,对象的来源于null。

    什么是类?

        类:具有一些特点,就是属性(property)。同时具有一些行为,就是方法e(method);
    
        类是某一类具有相同的特性。而其中的某一个就是对象的实例。
    

    那么如何理解面向过程和面向对象呢。
    举一个现实中的例子:
    比如说:我叫小明去帮我买个汉堡包这个例子。

    面向过程如下:
    //面向过程:
                console.log("我喊小明过来");
                console.log("小明过来了");
                console.log("给你十块钱去KFC给我买汉堡,记得找零钱");
                console.log("小明拿着钱下去去肯德基");
                console.log("排队,跟营业员沟通");
                console.log("给钱,等待");
                console.log("营业员找钱,准备食物");
                console.log("小明收好零钱,拿好汉堡,准备回来");
                console.log("把汉堡给我,给我零钱);*/
    
    面向对象如下:
    //面向对象
                var tech={
                    name:"李响",
                    act1:function(){
                        console.log("我喊小明过来");
                    },
                    act2:function(){
                        console.log("给小明十块钱去KFC给我买汉堡,记得找零钱");
                    },
                    act3:function(){
                        console.log("拿汉堡,收好零钱");
                    }
                };
                var xiaoming={
                    name:"小明",
                    age:18,
                    act1:function(){
                        console.log("被老师喊过来");
                    },
                    act2:function(){
                        console.log("拿钱去KFC");
                    },
                    act3:function(){
                        console.log("排队");
                    }
                var saler={
                    name:"小花",
                    age:20,
                    act1:function(){
                        console.log("跟小明眉来眼去,沟通");
                    },
                    act2:function(){
                        console.log("收钱准备食物");
                    },
                    act3:function(){
                        console.log("找零,给食物");
                    },
                }
    

    javaScript中是自带了很多内置对象的,比如:

    var arr = new Array();
    var date = newDate();
    

    什么是对象的属性呢?就是它的特点,比如arr就具有长度的属性.

    arr.lenght
    

    什么是对象的方法呢?比如:

    arr.sort();
    arr.join();
    arr.reverse();
    

    这样就很好理解javascript中的对象的属性和方法了,属性就是具有的特征,而对象就是一种行为。

    那么如何自己创建一个对象呢?

    字面量创建:
    1: var 对象名 = {属性1:方法1,属性2:方法2}
    2: var 对象名 = {}
    2-1: 对象名.属性1 = 方法1;
    2-1: 对象名.属性2 = 方法2;
    比如说:

            var obj={};
            obj.name="小花";
            obj.act=function(){
                alert(1);
            }
            obj.cc=function(){
                name:"小红";
                aa:function(){
                    alert(this.name);
                }
            }           
    

    这样的obj对象就具有一个name属性,一个sct的方法了,一个cc方法。
    那么问题出来了,这里的this指向谁??
    回顾:在单独的函数中,匿名函数,this指向window,非匿名函数指向事件源。

    如果出现函数的嵌套,这时候this指向离哪个近,就指向哪个。

    那么如何改变this的指向呢?方法有两个:

    • call() 方法
    • apply()方法

    call(a,b,c) 方法可以传多个参数,第一个方法是this的指向,后面的是传入的参数。
    apply(a,[b,c])方法传入一个参数和一个数组,如果不是数组,将会报错。
    如果什么都不传,相当于函数调用

    比如说:

    function fn(a,b){
        console.log(this);
        console.log(a+"+"+b+"="+(a+b));
    }
    fn.call(5,7,8)
    控制台输出:5和7+8=15;
    
    function fn(a,b,c){
        console.log(this);
        console.log(a,b,c);
    }
    fn.apply(6,[5,6,7]);
    控制台输出:6和5 6 7
    

    利用上面的特点,我们可以求数组最大值。实现代码如下:

    console.log(Math.max.apply(Math,[1,3,55,4]));
    ···
    原理是,apply()没有改变指向,依然指向Math,
    

    关于与保留this的问题

    <body>
        <button id="btn">按钮</button>
    </body>
    <script>
        var btn = document.getElementById('btn');
        btn.onclick = function(){
            function fn1(){
                console.log(this.innerHTML);
            }
        }
        fn1();
    </script>
    

    一段这样的代码,控制台输出:Window undefined。为什么呢?
    因为这时候this指向的是window。如果想指向btn,那么就需要预保留this。
    代码如下:

    <body>
        <button id="btn">按钮</button>
    </body>
    <script>
        var btn = document.getElementById('btn');
        btn.onclick = function(){
            var _this = this;//通过_this预保留
            function fn1(){
                console.log(_this,_this.innerHTML);
            }
            fn1();
        }
    </script>
    

    我们可以通过new来创建对象

    <body>
        <script>
            var obj = new Object();
            obj.name = "小明";
            obj.act = function(){
                alert(this.name);
            }
            obj.act();
        </script>
    </body>
    

    但是这样的创建太麻烦了,所以我们需要工厂函数创建对象。
    具体如下:这样就可以重用了。

    <body>
        <script>
            function createPerson(n,a){
                var obj = new Object();
                obj.name = n;
                obj.age = a;
                obj.showName = function(){
                    alert(this.name);
                }
                // 出厂
                return obj;
            }
            var p1 = createPerson("小花",18);
            var p2 = createPerson("小明",16);
            p1.showName();
            p2.showName();
            console.log(p1.age);
            console.log(p2.age);
        </script>
    </body>
    

    当new一个对象时会发生什么呢?

    会创建一个实例对象,这是的this指向实例对象。函数会有一个默认的返回值,就是这个对象。

    <body>
        <script>
            function CreatePerson(n,a){
                this.name=n;
                this.age=a;
                this.showName=function(){
                    alert(this.name);
                }
            }
            var p1 = new CreatePerson("小花",19);
            p1.showName();
            var p2 = new CreatePerson("小明",16);
            p2.showName();
        </script>
    </body>
    

    构造函数在解决了上面所有问题,同时为实例带来了类型,但可以注意到每个实例printName方法实际上作用一样,但是每个实例要重复一遍,大量对象存在的时候是浪费内存。

    那么如何解决呢?
    • 任何函数使用new都是表达式就是构造函数(工厂函数)
    • 每一个函数都会添加一个原型
    • 每个对象都有一个内部属性 proto(规范中没有指定这个名称,但是浏览器都这么实现的) 指向其类型的prototype属性,类的实例也是对象,其proto属性指向“类”的prototype。
      比如有一个代码
    function Person(nick, age){
        this.nick = nick;
        this.age = age;
        this.sayName = function(){
                console.log(this.nick);
        }
    }
    var p1 = new Person();
    

    这段代码中的sayname就是每次new 对象都会重复的方法。

    构造函数.png

    通过这个原理,我们可以抽象重复。

    • 所有函数都会通过原型链来引用类型的prototype
    • prototype相当于特定类型所有实例都可以访问到的一个公共容器
    • 我们可以把重复的东西放到prototype中。
      这时候,把重复的方法挂在到prototype中,代码如下:
    function Person(nick, age){
        this.nick = nick;
        this.age = age;
    }
    Person.prototype.sayName = function(){
        console.log(this.nick);
    }
    
    var p1 = new Person();
    p1.sayName();
    

    这时候,相对应的关系如下:


    解决方法重复.png

    再写个小例子

    <script>
            function CreatPerson(n,a){
                this.name = n;
                this.age = a;
                this.showName=function(){
                    alert(this.name);
                }
            }
            var p1=new CreatePerson("小明",16);
            p1.showName();
            p1.showAge=function(){
                alert(this.age);
            }
            var p2=new CreatePerson("小花",19);
            p2.showName();
    </script>
    

    这里的showName方法就重复了,如何使用原型链来解决呢?

    代码如下:

    <body>
            function CreatPerson(n,a){
                this.name = n;
                this.age = a;
            }
            CreatPerson.prototype.showName = function(){
                alert(this.name);
            }
            var p1 = new CreatPerson("小花",18);
            p1.showName();
            var p1 = new CreatPerson("小花花",16);
            p1.showName();
            alert(p1.age);
        </script>
        
    </body>
    

    最后尝试封装一个数组求和的函数,实现代码如下:

    <body>
        <script>
            Array.prototype.sum = function(){
                var result = 0;
                for(var i=0;i<this.length;i++){
                    result += this[i];
                }
                return result;
            }
            var arr = new Array(1,2,3,44);
            console.log(arr.sum());
        </script>
    </body>
    

    THE END

    相关文章

      网友评论

          本文标题:初识面向对象

          本文链接:https://www.haomeiwen.com/subject/krqsgxtx.html